emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/ssh-deploy f8366e9: Updated to version 3.1


From: Christian Johansson
Subject: [elpa] externals/ssh-deploy f8366e9: Updated to version 3.1
Date: Mon, 22 Apr 2019 01:02:13 -0400 (EDT)

branch: externals/ssh-deploy
commit f8366e9002618aecf8f31d34edf8caecea63ba92
Author: Christian Johansson <address@hidden>
Commit: Christian Johansson <address@hidden>

    Updated to version 3.1
---
 Makefile                |  21 ++
 README.md               |  77 ++--
 ssh-deploy-diff-mode.el | 106 +++---
 ssh-deploy-hydra.el     |  90 +++++
 ssh-deploy-test.el      | 420 +++++++++++++++++++++
 ssh-deploy.el           | 981 +++++++++++++++++++++++-------------------------
 6 files changed, 1100 insertions(+), 595 deletions(-)

diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..2f607b6
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,21 @@
+EMACS = emacs
+ifdef emacs
+       EMACS = $(emacs)
+endif
+
+EMACS_CMD := $(EMACS) -Q -batch -L .
+
+EL  := ssh-deploy-diff-mode.el ssh-deploy-test.el ssh-deploy.el
+ELC := $(EL:.el=.elc)
+
+.PHONY: test
+test:
+       $(EMACS_CMD) -l ssh-deploy-test.el
+
+.PHONY: clean
+clean:
+       rm -f $(ELC)
+
+.PHONY: compile
+compile:
+       $(EMACS_CMD) -f batch-byte-compile $(EL)
diff --git a/README.md b/README.md
index 5e5967a..4ebc4bd 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,13 @@
 # `emacs-ssh-deploy`
-[![License GPL 
3](https://img.shields.io/badge/license-GPL_3-green.svg)](https://www.gnu.org/licenses/gpl-3.0.txt)
 
[![MELPA](https://melpa.org/packages/ssh-deploy-badge.svg)](https://melpa.org/#/ssh-deploy)
 [![MELPA 
Stable](https://stable.melpa.org/packages/ssh-deploy-badge.svg)](https://stable.melpa.org/#/ssh-deploy)
+[![License GPL 
3](https://img.shields.io/badge/license-GPL_3-green.svg)](https://www.gnu.org/licenses/gpl-3.0.txt)
+[![MELPA](https://melpa.org/packages/ssh-deploy-badge.svg)](https://melpa.org/#/ssh-deploy)
+[![MELPA 
Stable](https://stable.melpa.org/packages/ssh-deploy-badge.svg)](https://stable.melpa.org/#/ssh-deploy)
+[![Build 
Status](https://travis-ci.org/cjohansson/emacs-ssh-deploy.svg?branch=master)](https://travis-ci.org/cjohansson/emacs-ssh-deploy)
 
-The `ssh-deploy` plug-in for Emacs makes it possible to effortlessly deploy 
local files and directories to remote hosts via TRAMP (including but not 
limited to SSH, SFTP, FTP). It tries to provide functions that can be easily 
used by custom scripts.
+The `ssh-deploy` plug-in for Emacs makes it possible to effortlessly deploy 
local files and directories to remote hosts via Tramp (including but not 
limited to SSH, SFTP, FTP). It tries to provide functions that can be easily 
used by custom scripts.
 
 ## Features:
+
 * Define syncing configuration per directory or per file (using 
`DirectoryVariables` or `File Variables`)
 * Control whether uploads of files should be automatic on save
 * Manual downloads and uploads of directories and files
@@ -11,13 +15,14 @@ The `ssh-deploy` plug-in for Emacs makes it possible to 
effortlessly deploy loca
 * Launch remote `eshell` and `shell` terminals in base or relative directory
 * Launch remote `dired` browsing in base or relative directory
 * Launch difference sessions for files using `ediff`
-* Launch difference sessions for directories using a custom implementation of 
recursive directory differences over TRAMP based on `ediff`
+* Launch difference sessions for directories using a custom implementation of 
recursive directory differences over Tramp based on `ediff`
 * Rename files and directories on local host and have it mirrored on the remote
 * Delete files and directories on local host and have it mirrored on the remote
 * Open corresponding file on the remote host
 * Open SQL database-session on remote hosts
 * Run custom deployment scripts
 * All operations support asynchronous mode if `(make-thread`) or `async.el` is 
installed. (You need to setup an automatic authorization for this, i.e. 
`~/.authinfo.gpg` and/or key-based password-less authorization)
+* Tries to follow best-practice both in terms of performance and code style
 
 The idea for this plug-in was to mimic the behavior of **PhpStorm** deployment 
functionality.
 
@@ -28,7 +33,7 @@ This application is made by Christian Johansson 
<address@hidden> 2016-2018 and
 Here is a list of other variables you can set globally or per directory:
 
 * `ssh-deploy-root-local` The local root that should be under deployment 
*(string)*
-* `ssh-deploy-root-remote` The remote TRAMP root that is used for deployment 
*(string)*
+* `ssh-deploy-root-remote` The remote Tramp root that is used for deployment 
*(string)*
 * `ssh-deploy-debug` Enables debugging messages *(integer)*
 * `ssh-deploy-revision-folder` The folder used for storing local revisions 
*(string)*
 * `ssh-deploy-automatically-detect-remote-changes` Enables automatic detection 
of remote changes *(integer)*
@@ -52,7 +57,7 @@ When integers are used as booleans, above zero means true, 
zero means false and
 * Download ssh-deploy and place it at `~/.emacs.d/ssh-deploy/` or install via 
`package.el` (`M-x list-packages` or `M-x package-install` + `ssh-deploy`) from 
the `ELPA` or `MELPA` repository.
 * So if you want to deploy `/Users/username/Web/MySite/` to create this 
`DirectoryVariables` file in your project root at 
`/Users/username/Web/MySite/.dir-locals.el`.
 
-You really need to do a bit of research about how to connect via different 
protocols using TRAMP on your operating system, I think Windows users should 
use `plink` for most protocols. Linux should work out of the box and macOS 
requires a bit of tweaking to get FTP support.
+You really need to do a bit of research about how to connect via different 
protocols using Tramp on your operating system, I think Windows users should 
use `plink` for most protocols. Linux should work out of the box and macOS 
requires a bit of tweaking to get FTP support.
 
 ### SSH, with automatic uploads and SQL
 
@@ -90,19 +95,33 @@ You really need to do a bit of research about how to 
connect via different proto
 
 You can pipe remote connections as well like this:
 
-### SSH, not asynchronous, with automatic uploads, piped to other user on 
remote server and with custom deployment script.
+### SSH, asynchronous using threads, with automatic uploads, piped to other 
user on remote server and with custom deployment script.
 
 ``` emacs-lisp
 ((nil . (
   (ssh-deploy-root-local . "/Users/username/Web/MySite/")
   (ssh-deploy-root-remote . 
"/ssh:address@hidden|sudo:address@hidden:/var/www/MySite/")
-  (ssh-deploy-async . 0)
+  (ssh-deploy-async . 1)
+  (ssh-deploy-async-with-threads . 1)
   (ssh-deploy-on-explicit-save . 1)
-  (ssh-deploy-script . (lambda() (let ((default-directory 
ssh-deploy-root-remote))(shell-command "bash compile.sh"))))
+  (ssh-deploy-script . (lambda() (let ((default-directory 
ssh-deploy-root-remote)) (shell-command "bash compile.sh"))))
+)))
+```
+
+### SSH, asynchronous not using threads, without automatic uploads, piped to 
other user on remote server and with custom deployment script.
+
+``` emacs-lisp
+((nil . (
+  (ssh-deploy-root-local . "/Users/username/Web/MySite/")
+  (ssh-deploy-root-remote . 
"/ssh:address@hidden|sudo:address@hidden:/var/www/MySite/")
+  (ssh-deploy-async . 1)
+  (ssh-deploy-async-with-threads . 0)
+  (ssh-deploy-on-explicit-save . 0)
+  (ssh-deploy-script . (lambda() (let ((default-directory 
ssh-deploy-root-local)) (shell-command "bash compile.sh") 
(ssh-deploy-upload-handler))))
 )))
 ```
 
-If you have a password-less sudo on your remote host you should be to do this 
asynchronously.
+If you have a password-less sudo on your remote host you should be to do this 
asynchronously or if you have your sudo credentials in your `~/.authinfo.gpg` 
file.
 
 ### FTP, with automatic uploads
 
@@ -162,7 +181,7 @@ By combining a `~/.authinfo.gpg` setup and a `public-key` 
setup you should be ab
 
 If you want to use the pre-defined hydra you can use this key-binding instead:
 ``` elisp
-(global-set-key (kbd "C-c C-z") 'ssh-deploy-hydra/body)
+(ssh-deploy-hydra "C-c C-z")
 ```
 
 * Or use the `use-package` and `hydra-script` I'm using:
@@ -171,12 +190,13 @@ If you want to use the pre-defined hydra you can use this 
key-binding instead:
       (use-package ssh-deploy
         :ensure t
         :demand
-        :bind (("C-c C-z" . ssh-deploy-hydra/body))
+        :after hydra
         :hook ((after-save . ssh-deploy-after-save)
                (find-file . ssh-deploy-find-file))
         :config
         (ssh-deploy-line-mode) ;; If you want mode-line feature
         (ssh-deploy-add-menu) ;; If you want menu-bar feature
+        (ssh-deploy-hydra "C-c C-z") ;; If you want the hydra feature
       )
 ```
 
@@ -199,7 +219,7 @@ File contents `/Users/username/Web/MySite/.dir-locals.el`:
 ```
 
 * Now when you save a file somewhere under the directory 
`/Users/username/Web/MySite/`, the script will launch and deploy the file with 
the remote server.
-* If you press `C-c C-z x` and the current buffer is a file, you will launch a 
`ediff` session showing differences between local file and remote file via 
TRAMP, or if current buffer is a directory it will open a buffer showing 
directory differences
+* If you press `C-c C-z x` and the current buffer is a file, you will launch a 
`ediff` session showing differences between local file and remote file via 
Tramp, or if current buffer is a directory it will open a buffer showing 
directory differences
 w* If you press `C-c C-z f` you will **force** upload local file or directory 
to remote host even if they have external changes.
 * If you press `C-c C-z u` you will upload local file or directory to remote 
host.
 * If you press `C-c C-z d` you will download the current file or directory 
from remote host and then reload current buffer.
@@ -220,9 +240,9 @@ The local path and local root is evaluated based on their 
`truename` so if you u
 
 The above configuration example uses the Emacs plug-in `use-package` which I 
highly recommend.
 
-## TRAMP FTP problem in macOS 10.13
+## Tramp FTP problem in macOS 10.13
 
-macOS 10.13 removed the Darwin port of BSD `ftp` which is needed for 
`ange-ftp`, which is required by TRAMP. You can get it back by doing this:
+macOS 10.13 removed the Darwin port of BSD `ftp` which is needed for 
`ange-ftp`, which is required by Tramp. You can get it back by doing this:
 
 1. Download 
<https://opensource.apple.com/tarballs/lukemftp/lukemftp-16.tar.gz> or some 
other version from <https://opensource.apple.com/tarballs/lukemftp/>
 2. Extract archive
@@ -230,7 +250,7 @@ macOS 10.13 removed the Darwin port of BSD `ftp` which is 
needed for `ange-ftp`,
 4. Type `./configure` then `make` and then `sudo make install`
 5. Type `mv ./src/ftp /usr/local/bin/ftp`
 
-## TRAMP FTP doesn't read my ~/.authinfo.gpg
+## Tramp FTP doesn't read my ~/.authinfo.gpg
 
 Ange-FTP defaults to `~/.netrc` so you need to add this to your init script:
 
@@ -238,11 +258,24 @@ Ange-FTP defaults to `~/.netrc` so you need to add this 
to your init script:
 (setq ange-ftp-netrc-filename "~/.authinfo.gpg")
 ```
 
+## Tests
+
+Run `make test` from plug-in folder to run tests
+
+### From custom Emacs version
+
+if you need to specify specific Emacs use export syntax i.e. `export 
emacs="YOUR_PATH" && make tests`
+
+### With tests for async.el integration
+
+Make sure to load if before the unit tests, i.e. `~/Documents/emacs/src/emacs 
-Q -batch -L ../elpa/async-20180527.1730/ -L . -l 
../elpa/async-20180527.1730/async.el -l ssh-deploy-test.el`
+
 ## Read more
-* <https://www.gnu.org/software/tramp/>
-* <https://elpa.gnu.org/>
-* <https://melpa.org/>
-* <https://www.emacswiki.org/emacs/DirectoryVariables>
-* <https://www.emacswiki.org/emacs/EdiffMode>
-* <https://github.com/jwiegley/emacs-async>
-* <https://github.com/jwiegley/use-package>
+* [Tramp](https://www.gnu.org/software/tramp/) - Transparent Remote (file) 
Access, Multiple Protocol
+* [ELPA](https://elpa.gnu.org/) - GNU Emacs Lisp Package Archive
+* [MELPA](https://melpa.org/) - Milkypostman’s Emacs Lisp Package Archive
+* [Directory Variables](https://www.emacswiki.org/emacs/DirectoryVariables)
+* [Ediff Mode](https://www.emacswiki.org/emacs/EdiffMode)
+* [emacs-async](https://github.com/jwiegley/emacs-async)
+* [use-package](https://github.com/jwiegley/use-package)
+* [The Emacs Lisp Style 
Guide](https://github.com/bbatsov/emacs-lisp-style-guide)
diff --git a/ssh-deploy-diff-mode.el b/ssh-deploy-diff-mode.el
index c6db269..52abf6f 100644
--- a/ssh-deploy-diff-mode.el
+++ b/ssh-deploy-diff-mode.el
@@ -2,16 +2,6 @@
 
 ;; Copyright (C) 2017-2018  Free Software Foundation, Inc.
 
-;; Author: Christian Johansson <address@hidden>
-;; Maintainer: Christian Johansson <address@hidden>
-;; Created: 1 Feb 2018
-;; Modified: 28 Nov 2018
-;; Version: 2.0
-;; Keywords: tools, convenience
-;; URL: https://github.com/cjohansson/emacs-ssh-deploy
-
-;; Package-Requires: ((emacs "24"))
-
 ;; This file is not part of GNU Emacs.
 
 ;; This program is free software; you can redistribute it and/or
@@ -87,61 +77,61 @@
   (save-excursion
     (beginning-of-line)
     (let ((file nil))
-      (if (looking-at "^- ")
-          (let* ((start (+ 2 (line-beginning-position)))
-                 (end (line-end-position)))
-            (setq file (buffer-substring-no-properties start end))))
+      (when (looking-at "^- ")
+        (let* ((start (+ 2 (line-beginning-position)))
+               (end (line-end-position)))
+          (setq file (buffer-substring-no-properties start end))))
       (while (and (> (line-number-at-pos) 1)
                   (not (looking-at "^[A-Z]+")))
         (forward-line -1))
-      (if (looking-at "^[A-Z]")
-          (let* ((start (line-beginning-position))
-                 (end (line-end-position))
-                 (section (buffer-substring-no-properties start end)))
-            (setq section (replace-regexp-in-string ": ([0-9]+)\\'" "" 
section))
-            (setq section
-                  (pcase section
-                    ("DIRECTORY A" 'directory-a)
-                    ("DIRECTORY B" 'directory-b)
-                    ("EXCLUDE-LIST" 'exclude-list)
-                    ("FILES ONLY IN A" 'only-in-a)
-                    ("FILES ONLY IN B" 'only-in-b)
-                    ("FILES IN BOTH BUT DIFFERS" 'in-both)
-                    (_ (message "Could not find section %s" section)
-                       section)))
-            (while (and (> (line-number-at-pos) 1)
-                        (not (looking-at "^DIRECTORY B:")))
-              (forward-line -1))
-            (if (looking-at "^DIRECTORY B:")
+      (when (looking-at "^[A-Z]")
+        (let* ((start (line-beginning-position))
+               (end (line-end-position))
+               (section (buffer-substring-no-properties start end)))
+          (setq section (replace-regexp-in-string ": ([0-9]+)\\'" "" section))
+          (setq section
+                (pcase section
+                  ("DIRECTORY A" 'directory-a)
+                  ("DIRECTORY B" 'directory-b)
+                  ("EXCLUDE-LIST" 'exclude-list)
+                  ("FILES ONLY IN A" 'only-in-a)
+                  ("FILES ONLY IN B" 'only-in-b)
+                  ("FILES IN BOTH BUT DIFFERS" 'in-both)
+                  (_ (message "Could not find section %s" section)
+                     section)))
+          (while (and (> (line-number-at-pos) 1)
+                      (not (looking-at "^DIRECTORY B:")))
+            (forward-line -1))
+          (when (looking-at "^DIRECTORY B:")
+            (let* ((start (line-beginning-position))
+                   (end (line-end-position))
+                   (directory-b (buffer-substring-no-properties start end)))
+              (setq directory-b (replace-regexp-in-string "DIRECTORY B: " "" 
directory-b))
+
+              (while (and (> (line-number-at-pos) 1)
+                          (not (looking-at "^DIRECTORY A:")))
+                (forward-line -1))
+              (when (looking-at "^DIRECTORY A:")
                 (let* ((start (line-beginning-position))
                        (end (line-end-position))
-                       (directory-b (buffer-substring-no-properties start 
end)))
-                  (setq directory-b (replace-regexp-in-string "DIRECTORY B: " 
"" directory-b))
-
-                  (while (and (> (line-number-at-pos) 1)
-                              (not (looking-at "^DIRECTORY A:")))
-                    (forward-line -1))
-                  (if (looking-at "^DIRECTORY A:")
-                      (let* ((start (line-beginning-position))
-                             (end (line-end-position))
-                             (directory-a (buffer-substring-no-properties 
start end)))
-                        (setq directory-a (replace-regexp-in-string "DIRECTORY 
A: " "" directory-a))
-                        (list file section directory-a directory-b))))))))))
+                       (directory-a (buffer-substring-no-properties start 
end)))
+                  (setq directory-a (replace-regexp-in-string "DIRECTORY A: " 
"" directory-a))
+                  (list file section directory-a directory-b))))))))))
 
 (defun ssh-deploy-diff-mode--action-handler (action)
   "Route valid ACTION to their functions."
   (interactive)
   (let ((parts (ssh-deploy-diff-mode--get-parts)))
-    (if (not (eq parts nil))
-        (cond
-         ((null parts) (message "Found nothing to do"))
-         ((not (or (nth 0 parts)
-                   ;; FIXME: Comparing equality of functions is bad karma!
-                   (eq action #'ssh-deploy-diff-mode--refresh)))
-          (message "Found nothing to do in the section for action %s"
-                   (replace-regexp-in-string "ssh-deploy-diff-mode--" ""
-                                             (format "%s" action))))
-         (t (funcall action parts))))))
+    (unless (eq parts nil)
+      (cond
+       ((null parts) (message "Found nothing to do"))
+       ((not (or (nth 0 parts)
+                 ;; FIXME: Comparing equality of functions is bad karma!
+                 (eq action #'ssh-deploy-diff-mode--refresh)))
+        (message "Found nothing to do in the section for action %s"
+                 (replace-regexp-in-string "ssh-deploy-diff-mode--" ""
+                                           (format "%s" action))))
+       (t (funcall action parts))))))
 
 (defun ssh-deploy-diff-mode--refresh (parts)
   "Refresh current difference query based on PARTS."
@@ -180,7 +170,6 @@
 
 (defun ssh-deploy-diff-mode--copy-b (parts)
   "Perform an download of remote-path to local-path based on PARTS from 
section B or section BOTH."
-  (require 'ssh-deploy)
   (let* ((section (nth 1 parts))
          (file-name (nth 0 parts))
          (root-local (file-truename (nth 2 parts)))
@@ -202,8 +191,8 @@
     (pcase section
       ('in-both
        (let ((yes-no-prompt (read-string (format "Type 'yes' to confirm that 
you want to delete the file '%s': " file-name))))
-         (if (string= yes-no-prompt "yes")
-             (ssh-deploy-delete-both path-local))))
+         (when (string= yes-no-prompt "yes")
+           (ssh-deploy-delete-both path-local))))
       ('only-in-a
        (ssh-deploy-delete path-local))
       ('only-in-b
@@ -224,7 +213,6 @@
 
 (defun ssh-deploy-diff-mode--open (parts)
   "Perform a open file action based on PARTS from section A or section B."
-  (require 'ssh-deploy)
   (let* ((section (nth 1 parts))
          (file-name (nth 0 parts))
          (root-local (file-truename (nth 2 parts)))
diff --git a/ssh-deploy-hydra.el b/ssh-deploy-hydra.el
new file mode 100644
index 0000000..2f406e2
--- /dev/null
+++ b/ssh-deploy-hydra.el
@@ -0,0 +1,90 @@
+;;; ssh-deploy-hydra.el --- Deployment via Tramp, global or per directory.  
-*- lexical-binding:t -*-
+
+;; Copyright (C) 2017-2019  Free Software Foundation, Inc.
+
+;; Package-Requires: ((emacs "25"))
+
+;; 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.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This file only contains hydra shortcut
+
+;; Please see README.md from the same repository for more extended 
documentation.
+
+;;; Code:
+
+
+(autoload 'ssh-deploy-upload-handler-forced "ssh-deploy")
+(autoload 'ssh-deploy-upload-handler "ssh-deploy")
+(autoload 'ssh-deploy-download-handler "ssh-deploy")
+(autoload 'ssh-deploy-delete-handler "ssh-deploy")
+(autoload 'ssh-deploy-diff-handler "ssh-deploy")
+(autoload 'ssh-deploy-remote-terminal-eshell-base-handler "ssh-deploy")
+(autoload 'ssh-deploy-remote-terminal-eshell-handler "ssh-deploy")
+(autoload 'ssh-deploy-remote-terminal-shell-base-handler "ssh-deploy")
+(autoload 'ssh-deploy-remote-terminal-shell-handler "ssh-deploy")
+(autoload 'ssh-deploy-remote-changes-handler "ssh-deploy")
+(autoload 'ssh-deploy-rename-handler "ssh-deploy")
+(autoload 'ssh-deploy-browse-remote-base-handler "ssh-deploy")
+(autoload 'ssh-deploy-browse-remote-handler "ssh-deploy")
+(autoload 'ssh-deploy-open-remote-file-handler "ssh-deploy")
+(autoload 'ssh-deploy-remote-sql-mysql-handler "ssh-deploy")
+(autoload 'ssh-deploy-run-deploy-script-handler "ssh-deploy")
+
+(require 'hydra)
+
+;;;###autoload
+(defun ssh-deploy-hydra (shortcut)
+  "Attach hydra at SHORTCUT."
+  (when (fboundp 'defhydra)
+    (defhydra ssh-deploy-hydra (:color red :hint nil)
+      "
+    SSH Deploy Menu
+    
+    _u_: Upload                              _f_: Force Upload
+    _d_: Download
+    _D_: Delete
+    _x_: Difference
+    _t_: Eshell Base Terminal                _T_: Eshell Relative Terminal
+    _h_: Shell Base Terminal                 _H_: Shell Relative Terminal
+    _e_: Detect Remote Changes
+    _R_: Rename
+    _b_: Browse Base                         _B_: Browse Relative
+    _o_: Open current file on remote         _m_: Open sql-mysql on remote
+    _s_: Run deploy script
+    "
+      ("f" #'ssh-deploy-upload-handler-forced)
+      ("u" #'ssh-deploy-upload-handler)
+      ("d" #'ssh-deploy-download-handler)
+      ("D" #'ssh-deploy-delete-handler)
+      ("x" #'ssh-deploy-diff-handler)
+      ("t" #'ssh-deploy-remote-terminal-eshell-base-handler)
+      ("T" #'ssh-deploy-remote-terminal-eshell-handler)
+      ("h" #'ssh-deploy-remote-terminal-shell-base-handler)
+      ("H" #'ssh-deploy-remote-terminal-shell-handler)
+      ("e" #'ssh-deploy-remote-changes-handler)
+      ("R" #'ssh-deploy-rename-handler)
+      ("b" #'ssh-deploy-browse-remote-base-handler)
+      ("B" #'ssh-deploy-browse-remote-handler)
+      ("o" #'ssh-deploy-open-remote-file-handler)
+      ("m" #'ssh-deploy-remote-sql-mysql-handler)
+      ("s" #'ssh-deploy-run-deploy-script-handler))
+    (when (fboundp 'ssh-deploy-hydra/body)
+      (global-set-key (kbd shortcut) #'ssh-deploy-hydra/body))))
+
+(provide 'ssh-deploy-hydra)
+;;; ssh-deploy-hydra.el ends here
diff --git a/ssh-deploy-test.el b/ssh-deploy-test.el
new file mode 100644
index 0000000..3fac61b
--- /dev/null
+++ b/ssh-deploy-test.el
@@ -0,0 +1,420 @@
+;;; ssh-deploy-test.el --- Unit and integration tests for ssh-deploy.  -*- 
lexical-binding:t -*-
+
+;; Copyright (C) 2017-2018  Free Software Foundation, Inc.
+
+;; 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.  If not, see <http://www.gnu.org/licenses/>.
+
+
+;;; Commentary:
+
+
+;; This file contains unit and integration tests for ssh-deploy plug-in for 
Emacs.
+
+
+;;; Code:
+
+
+(autoload 'should "ert")
+
+(autoload 'ediff-same-file-contents "ediff-util")
+
+(autoload 'ssh-deploy-diff-mode "ssh-deploy-diff-mode")
+
+(autoload 'ssh-deploy "ssh-deploy")
+(autoload 'ssh-deploy--get-revision-path "ssh-deploy")
+(autoload 'ssh-deploy--file-is-in-path-p "ssh-deploy")
+(autoload 'ssh-deploy--is-not-empty-string-p "ssh-deploy")
+(autoload 'ssh-deploy-download "ssh-deploy")
+(autoload 'ssh-deploy-upload "ssh-deploy")
+(autoload 'ssh-deploy-rename "ssh-deploy")
+(autoload 'ssh-deploy-delete-both "ssh-deploy")
+(autoload 'ssh-deploy-add-after-save-hook "ssh-deploy")
+(autoload 'ssh-deploy-add-after-save-hook "ssh-deploy")
+(autoload 'ssh-deploy-upload-handler "ssh-deploy")
+(autoload 'ssh-deploy--remote-changes-data "ssh-deploy")
+(autoload 'ssh-deploy-download-handler "ssh-deploy")
+(autoload 'ssh-deploy--async-process "ssh-deploy")
+
+(defun ssh-deploy-test--download (async async-with-threads)
+  "Test downloads asynchronously if ASYNC is above zero, with threads if 
ASYNC-WITH-THREADS is above zero."
+  (message "\nTest Download\n")
+  (let ((directory-a (expand-file-name "test-a/"))
+        (directory-b (expand-file-name "test-b/")))
+
+    ;; Delete directories if they already exists
+    (when (file-directory-p directory-a)
+      (delete-directory directory-a t))
+    (when (file-directory-p directory-b)
+      (delete-directory directory-b t))
+
+    (make-directory-internal directory-a)
+    (make-directory-internal directory-b)
+
+    (let* ((file-a (expand-file-name "test-b" directory-a))
+           (file-b (expand-file-name "test-b" directory-b))
+           (file-b-contents "Random text")
+           (ssh-deploy-root-local directory-a)
+           (ssh-deploy-root-remote directory-b)
+           (ssh-deploy-on-explicit-save 0)
+           (ssh-deploy-debug 0)
+           (ssh-deploy-async async)
+           (ssh-deploy-async-with-threads async-with-threads))
+
+      ;; Just bypass the linter here
+      (when (and ssh-deploy-root-local
+                 ssh-deploy-root-remote
+                 ssh-deploy-on-explicit-save
+                 ssh-deploy-debug
+                 ssh-deploy-async
+                 ssh-deploy-async-with-threads)
+
+        ;; Create a new file and add it's contents
+        (find-file file-b)
+        (insert file-b-contents)
+        (save-buffer)
+        (kill-buffer)
+
+        ;; Download file
+        (ssh-deploy-download file-b file-a 0 nil 0)
+        (when (> async 0)
+          (sleep-for 1))
+
+        ;; Verify that both files have equal contents
+        (should (equal t (ediff-same-file-contents file-a file-b)))
+
+        (delete-file file-b)
+        (delete-file file-a)))
+
+    (delete-directory directory-a t)
+    (delete-directory directory-b t)))
+
+(defun ssh-deploy-test--rename-and-delete (async async-with-threads)
+  "Test downloads asynchronous if ASYNC is above zero, with threads if 
ASYNC-WITH-THREADS is above zero."
+  (message "\nTest Rename and delete\n")
+  (let ((directory-a (expand-file-name "test-a/"))
+        (directory-b (expand-file-name "test-b/"))
+        (filename-old "testfile.txt")
+        (filename-new "testfile-renamed.txt"))
+
+    ;; Delete directories if they already exists
+    (when (file-directory-p directory-a)
+      (delete-directory directory-a t))
+    (when (file-directory-p directory-b)
+      (delete-directory directory-b t))
+
+    (make-directory-internal directory-a)
+    (make-directory-internal directory-b)
+
+    (let* ((file-a-old (expand-file-name filename-old directory-a))
+           (file-a-new (expand-file-name filename-new directory-a))
+           (file-b-old (expand-file-name filename-old directory-b))
+           (file-b-new (expand-file-name filename-new directory-b))
+           (file-contents "Random text")
+           (ssh-deploy-root-local directory-a)
+           (ssh-deploy-root-remote directory-b)
+           (ssh-deploy-on-explicit-save 0)
+           (ssh-deploy-debug 0)
+           (ssh-deploy-async async)
+           (ssh-deploy-async-with-threads async-with-threads))
+
+      ;; Just bypass the linter here
+      (when (and ssh-deploy-root-local
+                 ssh-deploy-root-remote
+                 ssh-deploy-on-explicit-save
+                 ssh-deploy-debug
+                 ssh-deploy-async
+                 ssh-deploy-async-with-threads)
+
+        ;; Create new files and add it's contents
+        (find-file file-a-old)
+        (insert file-contents)
+        (save-buffer)
+        (kill-buffer)
+
+        ;; Create new files and add it's contents
+        (find-file file-b-old)
+        (insert file-contents)
+        (save-buffer)
+        (kill-buffer)
+
+        ;; Both files should exist
+        (should (equal t (file-exists-p file-a-old)))
+        (should (equal t (file-exists-p file-b-old)))
+
+        ;; Rename filename
+        (find-file file-a-old)
+        (ssh-deploy-rename file-a-old file-a-new)
+        (when (> async 0)
+          (sleep-for 1))
+
+        ;; Both old files should not exist any more
+        (should (equal nil (file-exists-p file-a-old)))
+        (should (equal nil (file-exists-p file-b-old)))
+
+        ;; Both new files should exist any more
+        (should (equal t (file-exists-p file-a-new)))
+        (should (equal t (file-exists-p file-b-new)))
+
+        ;; Delete file
+        (ssh-deploy-delete-both file-a-new)
+        (when (> async 0)
+          (sleep-for 1))
+        (kill-buffer)
+
+        ;; Both new files should not exist anymore
+        (should (equal nil (file-exists-p file-a-new)))
+        (should (equal nil (file-exists-p file-b-new)))))
+
+    (delete-directory directory-a t)
+    (delete-directory directory-b t)))
+
+(defun ssh-deploy-test--upload (async async-with-threads)
+  "Test uploads asynchronously if ASYNC is above zero, with threads if 
ASYNC-WITH-THREADS is above zero."
+  (message "\nTest Upload\n")
+  (let ((directory-a (expand-file-name "test-a/"))
+        (directory-b (expand-file-name "test-b/")))
+
+    ;; Delete directories if they already exists
+    (when (file-directory-p directory-a)
+      (delete-directory directory-a t))
+    (when (file-directory-p directory-b)
+      (delete-directory directory-b t))
+
+    (make-directory-internal directory-a)
+    (make-directory-internal directory-b)
+
+    (let* ((file-a (expand-file-name "test.txt" directory-a))
+           (file-b (expand-file-name "test.txt" directory-b))
+           (file-a-contents "Random text")
+           (ssh-deploy-root-local directory-a)
+           (ssh-deploy-root-remote directory-b)
+           (ssh-deploy-on-explicit-save 1)
+           (ssh-deploy-debug 0)
+           (ssh-deploy-async async)
+           (ssh-deploy-async-with-threads async-with-threads))
+
+      ;; Just bypass the linter here
+      (when (and ssh-deploy-root-local
+                 ssh-deploy-root-remote
+                 ssh-deploy-on-explicit-save
+                 ssh-deploy-debug
+                 ssh-deploy-async
+                 ssh-deploy-async-with-threads)
+
+        (ssh-deploy-add-after-save-hook)
+        (find-file file-a)
+        (insert file-a-contents)
+        (save-buffer) ;; NOTE Should trigger upload action
+        (when (> async 0)
+          (sleep-for 1))
+
+        ;; Verify that both files have equal contents
+        (should (equal t (ediff-same-file-contents file-a file-b)))
+
+        ;; Turn of automatic uploads
+        (let ((ssh-deploy-on-explicit-save 0))
+          ;; Bypass linter again
+          (when ssh-deploy-on-explicit-save
+
+            ;; Update should not trigger upload
+            (insert file-a-contents)
+            (save-buffer)
+            (when (> async 0)
+              (sleep-for 1))
+
+            ;; Verify that both files have equal contents
+            (should (equal nil (ediff-same-file-contents file-a file-b)))
+
+            (ssh-deploy-upload-handler)
+            (when (> async 0)
+              (sleep-for 1))
+            (kill-buffer)
+
+            ;; Verify that both files have equal contents
+            (should (equal t (ediff-same-file-contents file-a file-b)))
+
+            ;; Delete both test files
+            (delete-file file-b)
+            (delete-file file-a)))))
+
+    (delete-directory directory-a t)
+    (delete-directory directory-b t)))
+
+(defun ssh-deploy-test--detect-remote-changes (async async-with-threads)
+  "Test uploads asynchronously if ASYNC is above zero, with threads if 
ASYNC-WITH-THREADS is above zero."
+
+  (message "\nTest Detect Remote Changes\n")
+  (let ((directory-a (expand-file-name "test-a/"))
+        (directory-b (expand-file-name "test-b/")))
+
+    ;; Delete directories if they already exists
+    (when (file-directory-p directory-a)
+      (delete-directory directory-a t))
+    (when (file-directory-p directory-b)
+      (delete-directory directory-b t))
+
+    (make-directory-internal directory-a)
+    (make-directory-internal directory-b)
+
+    (let* ((file-a (file-truename (expand-file-name "test.txt" directory-a)))
+           (file-b (file-truename (expand-file-name "test.txt" directory-b)))
+           (file-a-contents "Random text")
+           (ssh-deploy-root-local (file-truename directory-a))
+           (ssh-deploy-root-remote (file-truename directory-b))
+           (ssh-deploy-on-explicit-save 1)
+           (ssh-deploy-debug 0)
+           (ssh-deploy-async async)
+           (ssh-deploy-async-with-threads async-with-threads))
+
+      ;; Just bypass the linter here
+      (when (and ssh-deploy-root-local
+                 ssh-deploy-root-remote
+                 ssh-deploy-on-explicit-save
+                 ssh-deploy-debug
+                 ssh-deploy-async
+                 ssh-deploy-async-with-threads)
+
+        (ssh-deploy-add-after-save-hook)
+        (find-file file-a)
+        (insert file-a-contents)
+        (save-buffer) ;; NOTE Should trigger upload action
+        (when (> async 0)
+          (sleep-for 1))
+        (kill-buffer)
+
+        ;; Verify that both files have equal contents
+        (should (equal t (ediff-same-file-contents file-a file-b)))
+
+        ;; Update should not trigger upload
+        (find-file file-b)
+        (insert "Random blob")
+        (save-buffer)
+        (kill-buffer)
+
+        ;; Verify that both files don't have equal contents
+        (should (equal nil (ediff-same-file-contents file-a file-b)))
+
+        ;; Remote file should signal change now
+        (if (> async 0)
+            (progn
+              (ssh-deploy--async-process
+               (lambda() (ssh-deploy--remote-changes-data file-a))
+               (lambda(response) (should (equal 5 (nth 0 response))))
+               async-with-threads)
+              (sleep-for 1))
+          (should (equal 5 (nth 0 (ssh-deploy--remote-changes-data file-a)))))
+
+        ;; Open file-a and download remote
+        (find-file file-a)
+        (ssh-deploy-download-handler)
+        (when (> async 0)
+          (sleep-for 1))
+        (kill-buffer)
+
+        ;; Remote file should not signal change now
+        (if (> async 0)
+            (progn
+              (ssh-deploy--async-process
+               (lambda() (ssh-deploy--remote-changes-data file-a))
+               (lambda(response) (should (equal 4 (nth 0 response))))
+               async-with-threads)
+              (sleep-for 1))
+          (should (equal 4 (nth 0 (ssh-deploy--remote-changes-data file-a)))))
+
+        ;; Delete both test files
+        (delete-file file-b)
+        (delete-file file-a)))
+
+    (delete-directory directory-a t)
+    (delete-directory directory-b t)))
+
+(defun ssh-deploy-test--get-revision-path ()
+  "Test this function."
+  (should (string= (expand-file-name "./_mydirectory_random-file.txt") 
(ssh-deploy--get-revision-path "/mydirectory/random-file.txt" (expand-file-name 
".")))))
+
+(defun ssh-deploy-test--file-is-in-path ()
+  "Test this function."
+  (should (equal t (ssh-deploy--file-is-in-path-p "/mydirectory/test.txt" 
"/mydirectory/")))
+  (should (equal nil (ssh-deploy--file-is-in-path-p "/mydirectory/test.txt" 
"/mydirectory2/")))
+  (should (equal nil (ssh-deploy--file-is-in-path-p "/mydirectory2/test.txt" 
"/mydirectory/"))))
+
+(defun ssh-deploy-test--is-not-empty-string ()
+  "Test this function."
+  (should (equal t (ssh-deploy--is-not-empty-string-p "abc")))
+  (should (equal nil (ssh-deploy--is-not-empty-string-p "")))
+  (should (equal nil (ssh-deploy--is-not-empty-string-p nil))))
+
+(defun ssh-deploy-test ()
+  "Run test for plug-in."
+  (require 'ssh-deploy)
+  (let ((ssh-deploy-verbose 1)
+        (ssh-deploy-debug 1)
+        ;; (debug-on-error t)
+        (async-threads (fboundp 'make-thread))
+        (async-el (fboundp 'async-start))
+        (ssh-deploy-revision-folder (file-truename (expand-file-name 
"revisions"))))
+    (when (and ssh-deploy-verbose
+               ssh-deploy-debug)
+
+      (if async-threads
+          (message "\nNOTE: Running tests for asynchronous threads as well 
since it's loaded\n")
+        (message "\nNOTE: Skipping tests for asynchronous threads since it's 
not loaded\n"))
+      
+      (if async-el
+          (message "\nNOTE: Running tests for async.el as well since it's 
loaded\n")
+        (message "\nNOTE: Skipping tests for async.el since it's not 
loaded\n"))
+
+      (ssh-deploy-test--get-revision-path)
+      (ssh-deploy-test--file-is-in-path)
+      (ssh-deploy-test--is-not-empty-string)
+
+      ;; Detect Remote Changes
+      (ssh-deploy-test--detect-remote-changes 0 0)
+      (when async-el
+        (ssh-deploy-test--detect-remote-changes 1 0))
+      (when async-threads
+        (ssh-deploy-test--detect-remote-changes 1 1))
+
+      ;; Upload
+      (ssh-deploy-test--upload 0 0)
+      (when async-el
+        (ssh-deploy-test--upload 1 0))
+      (when async-threads
+        (ssh-deploy-test--upload 1 1))
+
+      ;; Download
+      (ssh-deploy-test--download 0 0)
+      (when async-el
+        (ssh-deploy-test--download 1 0))
+      (when async-threads
+        (ssh-deploy-test--download 1 1))
+
+      ;; Rename And Delete
+      (ssh-deploy-test--rename-and-delete 0 0)
+      (when async-el
+        (ssh-deploy-test--rename-and-delete 1 0))
+      (when async-threads
+        (ssh-deploy-test--rename-and-delete 1 1))
+
+      (delete-directory ssh-deploy-revision-folder t)
+
+      )))
+
+(ssh-deploy-test)
+
+
+(provide 'ssh-deploy-test)
+;;; ssh-deploy-test.el ends here
diff --git a/ssh-deploy.el b/ssh-deploy.el
index 1ee612d..918d9ba 100644
--- a/ssh-deploy.el
+++ b/ssh-deploy.el
@@ -1,16 +1,16 @@
-;;; ssh-deploy.el --- Deployment via TRAMP, global or per directory.  -*- 
lexical-binding:t -*-
+;;; ssh-deploy.el --- Deployment via Tramp, global or per directory.  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2017-2018  Free Software Foundation, Inc.
+;; Copyright (C) 2017-2019  Free Software Foundation, Inc.
 
 ;; Author: Christian Johansson <address@hidden>
 ;; Maintainer: Christian Johansson <address@hidden>
 ;; Created: 5 Jul 2016
-;; Modified: 28 Nov 2018
-;; Version: 3.0
+;; Modified: 20 Apr 2019
+;; Version: 3.1
 ;; Keywords: tools, convenience
 ;; URL: https://github.com/cjohansson/emacs-ssh-deploy
 
-;; Package-Requires: ((emacs "24"))
+;; Package-Requires: ((emacs "25"))
 
 ;; This file is not part of GNU Emacs.
 
@@ -32,13 +32,13 @@
 ;; ssh-deploy enables automatic deploys on explicit-save actions, manual 
uploads, renaming,
 ;; deleting, downloads, file and directory differences, launching remote 
terminals (eshell, shell),
 ;; detection of remote changes, remote directory browsing, remote SQL database 
sessions and
-;; running custom deployment scripts via TRAMP.
+;; running custom deployment scripts via Tramp.
 ;;
 ;; For asynchronous operations it uses package '`make-thread' or if not 
available '`async.el'.
 ;;
 ;; By setting the variables (globally, per directory or per file):
 ;; ssh-deploy-root-local,ssh-deploy-root-remote, ssh-deploy-on-explicit-save
-;; you can setup a directory for TRAMP deployment.
+;; you can setup a directory for Tramp deployment.
 ;;
 ;; For asynchronous transfers you need to setup ~/.authinfo.gpg or key-based 
authorization or equivalent for automatic authentication.
 ;;
@@ -68,18 +68,19 @@
 ;;     (global-set-key (kbd "C-c C-z") 'ssh-deploy-prefix-map)
 ;;
 ;; - To set global key-bindings for the pre-defined hydra do something like 
this:
-;;     (global-set-key (kbd "C-c C-z") 'ssh-deploy-hydra/body)
+;;     (ssh-deploy-hydra "C-c C-z")
 ;;
 ;; - To install and set-up using use-package and hydra do this:
 ;;   (use-package ssh-deploy
 ;;     :ensure t
+;;     :after hydra
 ;;     :demand
-;;     :bind (("C-c C-z" . ssh-deploy-hydra/body))
 ;;     :hook ((after-save . ssh-deploy-after-save)
 ;;            (find-file . ssh-deploy-find-file))
 ;;     :config
 ;;     (ssh-deploy-line-mode) ;; If you want mode-line feature
 ;;     (ssh-deploy-add-menu) ;; If you want menu-bar feature
+;;     (ssh-deploy-hydra "C-c C-z") ;; If you the hydra feature
 ;;    )
 ;;
 ;;
@@ -110,7 +111,7 @@
 ;; Here is a list of other variables you can set globally or per directory:
 
 ;; * `ssh-deploy-root-local' - The local root that should be under deployment 
*(string)*
-;; * `ssh-deploy-root-remote' - The remote TRAMP root that is used for 
deployment *(string)*
+;; * `ssh-deploy-root-remote' - The remote Tramp root that is used for 
deployment *(string)*
 ;; * `ssh-deploy-debug' - Enables debugging messages *(integer)*
 ;; * `ssh-deploy-revision-folder' - The folder used for storing local 
revisions *(string)*
 ;; * `ssh-deploy-automatically-detect-remote-changes' - Enables automatic 
detection of remote changes *(integer)*
@@ -133,11 +134,17 @@
 
 ;;; Code:
 
+(autoload 'ediff-same-file-contents "ediff-util")
+(autoload 'string-remove-prefix "subr-x")
+(autoload 'eshell "eshell")
+(autoload 'shell "shell")
 
 (autoload 'ssh-deploy-diff-mode "ssh-deploy-diff-mode")
+(autoload 'ssh-deploy-hydra "ssh-deploy-hydra")
+
 
 (defgroup ssh-deploy nil
-  "Upload, download, difference, browse and terminal handler for files and 
directories on remote hosts via TRAMP."
+  "Upload, download, difference, browse and terminal handler for files and 
directories on remote hosts via Tramp."
   :group 'tools
   :group 'convenience)
 
@@ -155,38 +162,37 @@
 
 (defcustom ssh-deploy-on-explicit-save 1
   "Boolean variable if deploy should be made on explicit save, 1 by default."
-  :type 'boolean)
+  :type 'integer)
 (put 'ssh-deploy-on-explicit-save 'permanent-local t)
 (put 'ssh-deploy-on-explicit-save 'safe-local-variable 'integerp)
 
 (defcustom ssh-deploy-debug 0
   "Boolean variable if debug messages should be shown, 0 by default."
-  :type 'boolean)
+  :type 'integer)
 (put 'ssh-deploy-debug 'permanent-local t)
 (put 'ssh-deploy-debug 'safe-local-variable 'integerp)
 
-;; TODO This flag needs to work better, you should not miss any useful 
notifications when this is on
 (defcustom ssh-deploy-verbose 1
   "Boolean variable if debug messages should be shown, 1 by default."
-  :type 'boolean)
+  :type 'integer)
 (put 'ssh-deploy-verbose 'permanent-local t)
 (put 'ssh-deploy-verbose 'safe-local-variable 'integerp)
 
 (defcustom ssh-deploy-async 0
   "Boolean variable if asynchronous method for transfers should be used, 0 by 
default."
-  :type 'boolean)
+  :type 'integer)
 (put 'ssh-deploy-async 'permanent-local t)
 (put 'ssh-deploy-async 'safe-local-variable 'integerp)
 
 (defcustom ssh-deploy-async-with-threads 0
   "Boolean variable if asynchronous method should use threads if available, 0 
by default."
-  :type 'boolean)
+  :type 'integer)
 (put 'ssh-deploy-async-with-threads 'permanent-local t)
 (put 'ssh-deploy-async-with-threads 'safe-local-variable 'integerp)
 
 (defcustom ssh-deploy-async-with-threads 0
   "Boolean variable if asynchronous method should use threads if available, 0 
by default."
-  :type 'boolean)
+  :type 'integer)
 (put 'ssh-deploy-async-with-threads 'permanent-local t)
 (put 'ssh-deploy-async-with-threads 'safe-local-variable 'integerp)
 
@@ -198,7 +204,7 @@
 
 (defcustom ssh-deploy-automatically-detect-remote-changes 1
   "Detect remote changes and store base revisions automatically, 1 by default."
-  :type 'boolean)
+  :type 'integer)
 (put 'ssh-deploy-automatically-detect-remote-changes 'permanent-local t)
 (put 'ssh-deploy-automatically-detect-remote-changes 'safe-local-variable 
'integerp)
 
@@ -228,8 +234,7 @@
 
 (defcustom ssh-deploy-remote-sql-server nil
   "String variable of remote sql server, nil by default."
-  :type 'string
-  :group 'ssh-deploy)
+  :type 'string)
 (put 'ssh-deploy-remote-sql-server 'permanent-local t)
 (put 'ssh-deploy-remote-sql-server 'safe-local-variable 'stringp)
 
@@ -287,26 +292,66 @@
 
 (defun ssh-deploy--async-process (start &optional finish async-with-threads)
   "Asynchronously do START and then optionally do FINISH, use multi-treading 
if ASYNC-WITH-THREADS is above 0 otherwise use multi processes via async.el."
-  (if (and (fboundp 'make-thread)
-           async-with-threads
+  (if (and async-with-threads
            (> async-with-threads 0))
-      (make-thread (lambda()
-                     (if start
-                         (let ((result (funcall start)))
-                           (if finish
-                               (funcall finish result))))))
+      (if (fboundp 'make-thread)
+          (make-thread (lambda()
+                         (let ((ssh-deploy-async 0)
+                               (ssh-deploy-async-with-threads 0)
+                               (ssh-deploy-on-explicit-save 0)
+                               (ssh-deploy-automatically-detect-remote-changes 
0))
+                           (if start
+                               (let ((result (funcall start)))
+                                 (if finish
+                                     (funcall finish result)))))))
+        (display-warning 'ssh-deploy "make-thread function are not 
available!"))
     (if (fboundp 'async-start)
-        (if start
-            (let ((ftp-netrc nil))
-              (when (boundp 'ange-ftp-netrc-filename)
-                (setq ftp-netrc ange-ftp-netrc-filename))
+        (when start
+          (let ((ftp-netrc nil)
+                (root-local ssh-deploy-root-local)
+                (root-remote ssh-deploy-root-remote)
+                (revision-folder ssh-deploy-revision-folder)
+                (exclude-list ssh-deploy-exclude-list))
+            (when (boundp 'ange-ftp-netrc-filename)
+              (setq ftp-netrc ange-ftp-netrc-filename))
+            (let ((script-filename (file-name-directory (symbol-file 
'ssh-deploy-diff-directories))))
               (async-start
                (lambda()
-                 (if ftp-netrc
+                 (add-to-list 'load-path script-filename)
+                 (require 'ssh-deploy)
+                 (let ((ssh-deploy-async 0)
+                       (ssh-deploy-async-with-threads 0)
+                       (ssh-deploy-on-explicit-save 0)
+                       (ssh-deploy-automatically-detect-remote-changes 0)
+                       (ssh-deploy-root-local root-local)
+                       (ssh-deploy-root-remote root-remote)
+                       (ssh-deploy-revision-folder revision-folder)
+                       (ssh-deploy-exclude-list exclude-list))
+                   (when ftp-netrc
+                     ;; Pass ange-ftp setting to asynchronous process
                      (defvar ange-ftp-netrc-filename ftp-netrc))
-                 (funcall start))
-               finish)))
-      (display-warning 'ssh-deploy "Neither make-thread nor async-start 
functions are available!"))))
+
+                   (autoload 'ediff-same-file-contents "ediff-util")
+                   (autoload 'string-remove-prefix "subr-x")
+
+                   (autoload 'ssh-deploy-download "ssh-deploy")
+                   (autoload 'ssh-deploy-download-handler "ssh-deploy")
+                   (autoload 'ssh-deploy-upload "ssh-deploy")
+                   (autoload 'ssh-deploy-upload-handler "ssh-deploy")
+                   (autoload 'ssh-deploy-rename "ssh-deploy")
+                   (autoload 'ssh-deploy-rename-handler "ssh-deploy")
+                   (autoload 'ssh-deploy-delete "ssh-deploy")
+                   (autoload 'ssh-deploy-delete-both "ssh-deploy")
+                   (autoload 'ssh-deploy-delete-handler "ssh-deploy")
+                   (autoload 'ssh-deploy-diff "ssh-deploy")
+                   (autoload 'ssh-deploy-diff-handler "ssh-deploy")
+                   (autoload 'ssh-deploy--diff-directories-data "ssh-deploy")
+                   (autoload 'ssh-deploy--diff-directories-present 
"ssh-deploy")
+                   (autoload 'ssh-deploy--remote-changes-data "ssh-deploy")
+                   (autoload 'ssh-deploy--remote-changes-post-executor 
"ssh-deploy")
+                   (funcall start)))
+               finish))))
+      (display-warning 'ssh-deploy "async-start functions are not 
available!"))))
 
 (defun ssh-deploy--mode-line-set-status-and-update (status &optional filename)
   "Set the mode line STATUS in optionally in buffer visiting FILENAME."
@@ -355,14 +400,10 @@
      ((and ssh-deploy-root-local ssh-deploy-root-remote)
       (setq status-text "idle"))
 
-     (t (setq status-text ""))
-
-     )
+     (t (setq status-text "")))
 
     (make-local-variable 'ssh-deploy--mode-line-status-text)
-    (setq ssh-deploy--mode-line-status-text 
(ssh-deploy--mode-line-status-text-format status-text))
-    ;; (message "SSH Deploy - Updated status text to: '%s' from: %d" 
ssh-deploy--mode-line-status-text status)
-    ))
+    (setq ssh-deploy--mode-line-status-text 
(ssh-deploy--mode-line-status-text-format status-text))))
 
 (defun ssh-deploy--mode-line-status-text-format (text)
   "Return a formatted string based on TEXT."
@@ -381,111 +422,106 @@
       (make-directory root))
   (expand-file-name (replace-regexp-in-string "\\(/\\|@\\|:\\)" "_" path) 
root))
 
-(defun ssh-deploy--file-is-in-path (file path)
+(defun ssh-deploy--file-is-in-path-p (file path)
   "Return non-nil if FILE is in the path PATH."
   (not (null (string-match path file))))
 
-(defun ssh-deploy--file-is-included (path exclude-list)
+(defun ssh-deploy--file-is-included-p (path exclude-list)
   "Return non-nil if PATH is not in EXCLUDE-LIST."
   (let ((not-found t))
     (dolist (element exclude-list)
-      (if (and (not (null element))
-               (not (null (string-match element path))))
-          (setq not-found nil)))
+      (when (and (not (null element))
+                 (not (null (string-match element path))))
+        (setq not-found nil)))
     not-found))
 
 (defun ssh-deploy--get-relative-path (root path)
   "Return a string for the relative path based on ROOT and PATH."
   (replace-regexp-in-string root "" path))
 
-(defun ssh-deploy--is-not-empty-string (string)
+(defun ssh-deploy--is-not-empty-string-p (string)
   "Return non-nil if the STRING is not empty and not nil.  Expects string."
   (and (not (null string))
        (not (zerop (length string)))))
 
 (defun ssh-deploy--upload-via-tramp-async (path-local path-remote force 
revision-folder async-with-threads)
-  "Upload PATH-LOCAL to PATH-REMOTE via TRAMP asynchronously and FORCE upload 
despite remote change, check for revisions in REVISION-FOLDER.  Use 
multi-treaded async if ASYNC-WITH-THREADS is specified."
+  "Upload PATH-LOCAL to PATH-REMOTE via Tramp asynchronously and FORCE upload 
despite remote change, check for revisions in REVISION-FOLDER.  Use 
multi-treaded async if ASYNC-WITH-THREADS is specified."
   (let ((file-or-directory (not (file-directory-p path-local))))
     (ssh-deploy--mode-line-set-status-and-update ssh-deploy--status-uploading 
path-local)
     (if file-or-directory
         (let ((revision-path (ssh-deploy--get-revision-path path-local 
revision-folder)))
-          (when ssh-deploy-verbose (message "Uploading file '%s' to '%s'.. 
(asynchronously)" path-local path-remote))
+          (when (> ssh-deploy-verbose 0) (message "Uploading file '%s' to 
'%s'.. (asynchronously)" path-local path-remote))
           (ssh-deploy--async-process
            (lambda()
-             (require 'ediff-util)
-             (if (fboundp 'ediff-same-file-contents)
-                 (if (or (> force 0) (not (file-exists-p path-remote)) (and 
(file-exists-p revision-path) (ediff-same-file-contents revision-path 
path-remote)))
-                     (progn
-                       (if (not (file-directory-p (file-name-directory 
path-remote)))
-                           (make-directory (file-name-directory path-remote) 
t))
-                       (copy-file path-local path-remote t t t t)
-                       (copy-file path-local revision-path t t t t)
-                       (list 0 (format "Completed upload of file '%s'. 
(asynchronously)" path-remote) path-local))
-                   (list 1 (format "Remote file '%s' has changed please 
download or diff. (asynchronously)" path-remote) path-local))
-               (list 1 "Function 'ediff-same-file-contents' is missing. 
(asynchronously)" path-local)))
+             (if (or (> force 0) (not (file-exists-p path-remote))
+                     (and (file-exists-p revision-path)
+                          (ediff-same-file-contents revision-path 
path-remote)))
+                 (progn
+                   (unless (file-directory-p (file-name-directory path-remote))
+                     (make-directory (file-name-directory path-remote) t))
+                   (copy-file path-local path-remote t t t t)
+                   (copy-file path-local revision-path t t t t)
+                   (list 0 (format "Completed upload of file '%s'. 
(asynchronously)" path-remote) path-local))
+               (list 1 (format "Remote file '%s' has changed please download 
or diff. (asynchronously)" path-remote) path-local)))
            (lambda(return)
              (ssh-deploy--mode-line-set-status-and-update 
ssh-deploy--status-idle (nth 2 return))
              (if (= (nth 0 return) 0)
-                 (when ssh-deploy-verbose (message (nth 1 return)))
+                 (when (> ssh-deploy-verbose 0) (message (nth 1 return)))
                (display-warning 'ssh-deploy (nth 1 return) :warning)))
            async-with-threads))
-      (progn
-        (when ssh-deploy-verbose (message "Uploading directory '%s' to '%s'.. 
(asynchronously)" path-local path-remote))
-        (ssh-deploy--async-process
-         (lambda()
-           (copy-directory path-local path-remote t t t)
-           path-local)
-         (lambda(return-path)
-           (ssh-deploy--mode-line-set-status-and-update 
ssh-deploy--status-idle return-path)
-           (when ssh-deploy-verbose (message "Completed upload of directory 
'%s'. (asynchronously)" return-path))))))))
+      (when (> ssh-deploy-verbose 0) (message "Uploading directory '%s' to 
'%s'.. (asynchronously)" path-local path-remote))
+      (ssh-deploy--async-process
+       (lambda()
+         (copy-directory path-local path-remote t t t)
+         path-local)
+       (lambda(return-path)
+         (ssh-deploy--mode-line-set-status-and-update ssh-deploy--status-idle 
return-path)
+         (when (> ssh-deploy-verbose 0) (message "Completed upload of 
directory '%s'. (asynchronously)" return-path)))))))
 
 (defun ssh-deploy--upload-via-tramp (path-local path-remote force 
revision-folder)
-  "Upload PATH-LOCAL to PATH-REMOTE via TRAMP synchronously and FORCE despite 
remote change compared with copy in REVISION-FOLDER."
+  "Upload PATH-LOCAL to PATH-REMOTE via Tramp synchronously and FORCE despite 
remote change compared with copy in REVISION-FOLDER."
   (let ((file-or-directory (not (file-directory-p path-local)))
         (revision-path (ssh-deploy--get-revision-path path-local 
revision-folder)))
     (ssh-deploy--mode-line-set-status-and-update ssh-deploy--status-uploading)
     (if file-or-directory
         (progn
-          (require 'ediff-util)
-          (if (fboundp 'ediff-same-file-contents)
-              (if (or (> force 0)
-                      (not (file-exists-p path-remote))
-                      (and (file-exists-p revision-path) 
(ediff-same-file-contents revision-path path-remote)))
-                  (progn
-                    (when ssh-deploy-verbose (message "Uploading file '%s' to 
'%s'.. (synchronously)" path-local path-remote))
-                    (if (not (file-directory-p (file-name-directory 
path-remote)))
-                        (make-directory (file-name-directory path-remote) t))
-                    (copy-file path-local path-remote t t t t)
-                    (ssh-deploy-store-revision path-local revision-folder)
-                    (when ssh-deploy-verbose (message "Completed upload of 
'%s'. (synchronously)" path-local)))
-                (display-warning 'ssh-deploy (format "Remote file '%s' has 
changed, please download or diff. (synchronously)" path-remote) :warning))
-            (display-warning 'ssh-deploy "Function 'ediff-same-file-contents' 
is missing." :warning))
+          (if (or (> force 0)
+                  (not (file-exists-p path-remote))
+                  (and (file-exists-p revision-path)
+                       (ediff-same-file-contents revision-path path-remote)))
+              (progn
+                (when (> ssh-deploy-verbose 0) (message "Uploading file '%s' 
to '%s'.. (synchronously)" path-local path-remote))
+                (unless (file-directory-p (file-name-directory path-remote))
+                  (make-directory (file-name-directory path-remote) t))
+                (copy-file path-local path-remote t t t t)
+                (ssh-deploy-store-revision path-local revision-folder)
+                (when (> ssh-deploy-verbose 0) (message "Completed upload of 
'%s'. (synchronously)" path-local)))
+            (display-warning 'ssh-deploy (format "Remote file '%s' has 
changed, please download or diff. (synchronously)" path-remote) :warning))
           (ssh-deploy--mode-line-set-status-and-update 
ssh-deploy--status-idle))
-      (progn
-        (when ssh-deploy-verbose (message "Uploading directory '%s' to '%s'.. 
(synchronously)" path-local path-remote))
-        (copy-directory path-local path-remote t t t)
-        (ssh-deploy--mode-line-set-status-and-update ssh-deploy--status-idle)
-        (when ssh-deploy-verbose (message "Completed upload of '%s'. 
(synchronously)" path-local))))))
+      (when (> ssh-deploy-verbose 0) (message "Uploading directory '%s' to 
'%s'.. (synchronously)" path-local path-remote))
+      (copy-directory path-local path-remote t t t)
+      (ssh-deploy--mode-line-set-status-and-update ssh-deploy--status-idle)
+      (when (> ssh-deploy-verbose 0) (message "Completed upload of '%s'. 
(synchronously)" path-local)))))
 
 (defun ssh-deploy--download-via-tramp-async (path-remote path-local 
revision-folder async-with-threads)
-  "Download PATH-REMOTE to PATH-LOCAL via TRAMP asynchronously and make a copy 
in REVISION-FOLDER, use multi-threading if ASYNC-WITH-THREADS is above zero."
+  "Download PATH-REMOTE to PATH-LOCAL via Tramp asynchronously and make a copy 
in REVISION-FOLDER, use multi-threading if ASYNC-WITH-THREADS is above zero."
   (let ((revision-path (ssh-deploy--get-revision-path path-local 
revision-folder)))
     (ssh-deploy--mode-line-set-status-and-update 
ssh-deploy--status-downloading path-local)
-    (when ssh-deploy-verbose (message "Downloading '%s' to '%s'.. 
(asynchronously)" path-remote path-local))
+    (when (> ssh-deploy-verbose 0) (message "Downloading '%s' to '%s'.. 
(asynchronously)" path-remote path-local))
     (ssh-deploy--async-process
      (lambda()
        (let ((file-or-directory (not (file-directory-p path-remote))))
          (if file-or-directory
              (progn
-               (if (not (file-directory-p (file-name-directory path-local)))
-                   (make-directory (file-name-directory path-local) t))
+               (unless (file-directory-p (file-name-directory path-local))
+                 (make-directory (file-name-directory path-local) t))
                (copy-file path-remote path-local t t t t)
                (copy-file path-local revision-path t t t t))
            (copy-directory path-remote path-local t t t))
          path-local))
      (lambda(return-path)
        (ssh-deploy--mode-line-set-status-and-update ssh-deploy--status-idle 
return-path)
-       (when ssh-deploy-verbose (message "Completed download of '%s'. 
(asynchronously)" return-path))
+       (when (> ssh-deploy-verbose 0) (message "Completed download of '%s'. 
(asynchronously)" return-path))
        (let ((local-buffer (find-buffer-visiting return-path)))
          (when local-buffer
            (with-current-buffer local-buffer
@@ -493,28 +529,26 @@
      async-with-threads)))
 
 (defun ssh-deploy--download-via-tramp (path-remote path-local revision-folder)
-  "Download PATH-REMOTE to PATH-LOCAL via TRAMP synchronously and store a copy 
in REVISION-FOLDER."
+  "Download PATH-REMOTE to PATH-LOCAL via Tramp synchronously and store a copy 
in REVISION-FOLDER."
   (let ((file-or-directory (not (file-directory-p path-remote))))
     (ssh-deploy--mode-line-set-status-and-update 
ssh-deploy--status-downloading)
     (if file-or-directory
         (progn
-          (when ssh-deploy-verbose (message "Downloading file '%s' to '%s'.. 
(synchronously)" path-remote path-local))
-          (if (not (file-directory-p (file-name-directory path-local)))
-              (make-directory (file-name-directory path-local) t))
+          (when (> ssh-deploy-verbose 0) (message "Downloading file '%s' to 
'%s'.. (synchronously)" path-remote path-local))
+          (unless (file-directory-p (file-name-directory path-local))
+            (make-directory (file-name-directory path-local) t))
           (copy-file path-remote path-local t t t t)
           (ssh-deploy-store-revision path-local revision-folder)
           (ssh-deploy--mode-line-set-status-and-update ssh-deploy--status-idle)
-          (when ssh-deploy-verbose (message "Completed download of file '%s'. 
(synchronously)" path-local)))
-      (progn
-        (message "Downloading directory '%s' to '%s'.. (synchronously)" 
path-remote path-local)
-        (copy-directory path-remote path-local t t t)
-        (ssh-deploy--mode-line-set-status-and-update ssh-deploy--status-idle)
-        (message "Completed download of directory '%s'. (synchronously)" 
path-local)))))
+          (when (> ssh-deploy-verbose 0) (message "Completed download of file 
'%s'. (synchronously)" path-local)))
+      (message "Downloading directory '%s' to '%s'.. (synchronously)" 
path-remote path-local)
+      (copy-directory path-remote path-local t t t)
+      (ssh-deploy--mode-line-set-status-and-update ssh-deploy--status-idle)
+      (message "Completed download of directory '%s'. (synchronously)" 
path-local))))
 
 (defun ssh-deploy--diff-directories-data (directory-a directory-b exclude-list)
   "Find difference between DIRECTORY-A and DIRECTORY-B but exclude paths 
matching EXCLUDE-LIST."
   ;; (message "Comparing a: %s to b: %s" directory-a directory-b)
-  (require 'subr-x)
   (if (fboundp 'string-remove-prefix)
       (if (and (file-directory-p directory-a)
                (file-directory-p directory-b))
@@ -539,16 +573,16 @@
 
                    ;; Check if file is excluded
                    (dolist (element exclude-list)
-                     (if (and (not (null element))
-                              (not (null (string-match element 
relative-path))))
-                         (setq included nil)))
-
-                   (if included
-                       (progn
-                         (puthash relative-path file-a files-a-relative-hash)
-                         (if (equal files-a-relative-list nil)
-                             (setq files-a-relative-list (list relative-path))
-                           (push relative-path files-a-relative-list)))))))
+                     (when (and (not (null element))
+                                (not (null (string-match element 
relative-path))))
+                       (setq included nil)))
+
+                   (when included
+                     (progn
+                       (puthash relative-path file-a files-a-relative-hash)
+                       (if (equal files-a-relative-list nil)
+                           (setq files-a-relative-list (list relative-path))
+                         (push relative-path files-a-relative-list)))))))
              files-a)
 
             ;; Collected included files in directory b with relative paths
@@ -561,16 +595,15 @@
 
                    ;; Check if file is excluded
                    (dolist (element exclude-list)
-                     (if (and (not (null element))
-                              (not (null (string-match element 
relative-path))))
-                         (setq included nil)))
-
-                   (if included
-                       (progn
-                         (puthash relative-path file-b files-b-relative-hash)
-                         (if (equal files-b-relative-list nil)
-                             (setq files-b-relative-list (list relative-path))
-                           (push relative-path files-b-relative-list)))))))
+                     (when (and (not (null element))
+                                (not (null (string-match element 
relative-path))))
+                       (setq included nil)))
+
+                   (when included
+                     (puthash relative-path file-b files-b-relative-hash)
+                     (if (equal files-b-relative-list nil)
+                         (setq files-b-relative-list (list relative-path))
+                       (push relative-path files-b-relative-list))))))
              files-b)
 
             ;; Collect files that only exists in directory a and files that 
exist in both directory a and b
@@ -588,29 +621,26 @@
             ;; Collect files that only exists in directory b
             (mapc
              (lambda (file-b)
-               (if (equal (gethash file-b files-a-relative-hash) nil)
-                   (progn
-                     ;; (message "%s did not exist in hash-a" file-b)
-                     (if (equal files-b-only nil)
-                         (setq files-b-only (list file-b))
-                       (push file-b files-b-only)))))
+               (when (equal (gethash file-b files-a-relative-hash) nil)
+                 ;; (message "%s did not exist in hash-a" file-b)
+                 (if (equal files-b-only nil)
+                     (setq files-b-only (list file-b))
+                   (push file-b files-b-only))))
              files-b-relative-list)
 
             ;; Collect files that differ in contents and have equal contents
-            (require 'ediff-util)
-            (if (fboundp 'ediff-same-file-contents)
-                (mapc
-                 (lambda (file)
-                   (let ((file-a (gethash file files-a-relative-hash))
-                         (file-b (gethash file files-b-relative-hash)))
-                     (if (ediff-same-file-contents file-a file-b)
-                         (if (equal files-both-equals nil)
-                             (setq files-both-equals (list file))
-                           (push file files-both-equals))
-                       (if (equal files-both-differs nil)
-                           (setq files-both-differs (list file))
-                         (push file files-both-differs)))))
-                 files-both))
+            (mapc
+             (lambda (file)
+               (let ((file-a (gethash file files-a-relative-hash))
+                     (file-b (gethash file files-b-relative-hash)))
+                 (if (ediff-same-file-contents file-a file-b)
+                     (if (equal files-both-equals nil)
+                         (setq files-both-equals (list file))
+                       (push file files-both-equals))
+                   (if (equal files-both-differs nil)
+                       (setq files-both-differs (list file))
+                     (push file files-both-differs)))))
+             files-both)
 
             (list directory-a directory-b exclude-list files-both files-a-only 
files-b-only files-both-equals files-both-differs))
         (display-warning 'ssh-deploy "Both directories need to exist to 
perform difference generation." :warning))
@@ -628,36 +658,32 @@
     (ssh-deploy--insert-keyword "DIRECTORY B: ")
     (insert (nth 1 diff) "\n")
 
-    (if (> (length (nth 2 diff)) 0)
-        (progn
-          (insert "\n")
-          (ssh-deploy--insert-keyword (format "EXCLUDE-LIST: (%d)" (length 
(nth 2 diff))))
-          (dolist (element (nth 2 diff))
-            (insert "\n- " element))
-          (insert "\n")))
+    (when (> (length (nth 2 diff)) 0)
+      (insert "\n")
+      (ssh-deploy--insert-keyword (format "EXCLUDE-LIST: (%d)" (length (nth 2 
diff))))
+      (dolist (element (nth 2 diff))
+        (insert "\n- " element))
+      (insert "\n"))
 
     (insert "\n")
 
-    (if (> (length (nth 4 diff)) 0)
-        (progn
-          (ssh-deploy--insert-keyword (format "FILES ONLY IN A: (%d)" (length 
(nth 4 diff))))
-          (dolist (element (nth 4 diff))
-            (insert "\n- " element))
-          (insert "\n\n")))
+    (when (> (length (nth 4 diff)) 0)
+      (ssh-deploy--insert-keyword (format "FILES ONLY IN A: (%d)" (length (nth 
4 diff))))
+      (dolist (element (nth 4 diff))
+        (insert "\n- " element))
+      (insert "\n\n"))
 
-    (if (> (length (nth 5 diff)) 0)
-        (progn
-          (ssh-deploy--insert-keyword (format "FILES ONLY IN B: (%d)" (length 
(nth 5 diff))))
-          (dolist (element (nth 5 diff))
-            (insert "\n- " element))
-          (insert "\n\n")))
+    (when (> (length (nth 5 diff)) 0)
+      (ssh-deploy--insert-keyword (format "FILES ONLY IN B: (%d)" (length (nth 
5 diff))))
+      (dolist (element (nth 5 diff))
+        (insert "\n- " element))
+      (insert "\n\n"))
 
-    (if (> (length (nth 7 diff)) 0)
-        (progn
-          (ssh-deploy--insert-keyword (format "FILES IN BOTH BUT DIFFERS: 
(%d)" (length (nth 7 diff))))
-          (dolist (element (nth 7 diff))
-            (insert "\n- " element))
-          (insert "\n\n")))
+    (when (> (length (nth 7 diff)) 0)
+      (ssh-deploy--insert-keyword (format "FILES IN BOTH BUT DIFFERS: (%d)" 
(length (nth 7 diff))))
+      (dolist (element (nth 7 diff))
+        (insert "\n- " element))
+      (insert "\n\n"))
 
     (insert "\nHELP: quit (q), copy (C), copy A to B (a), copy B to A (b), 
delete (D), difference (TAB), refresh (g), open (RET)")
 
@@ -684,14 +710,10 @@
 ;;;###autoload
 (defun ssh-deploy-diff-files (file-a file-b)
   "Find difference between FILE-A and FILE-B."
-  (require 'ediff-util)
-  (if (fboundp 'ediff-same-file-contents)
-      (progn
-        (message "Comparing file '%s' to '%s'.." file-a file-b)
-        (if (ediff-same-file-contents file-a file-b)
-            (message "Files have identical contents.")
-          (ediff file-a file-b)))
-    (display-warning 'ssh-deploy "Function 'ediff-same-file-contents' is 
missing." :warning)))
+  (message "Comparing file '%s' to '%s'.." file-a file-b)
+  (if (ediff-same-file-contents file-a file-b)
+      (message "Files have identical contents.")
+    (ediff file-a file-b)))
 
 ;;;###autoload
 (defun ssh-deploy-diff-directories (directory-a directory-b &optional 
on-explicit-save debug async async-with-threads revision-folder remote-changes 
exclude-list)
@@ -704,158 +726,122 @@
         (remote-changes (or remote-changes 
ssh-deploy-automatically-detect-remote-changes))
         (exclude-list (or exclude-list ssh-deploy-exclude-list)))
     (if (> async 0)
-        (let ((script-filename (file-name-directory (symbol-file 
'ssh-deploy-diff-directories))))
+        (progn
           (message "Calculating differences between directory '%s' and '%s'.. 
(asynchronously)" directory-a directory-b)
           (ssh-deploy--async-process
            (lambda()
-             (add-to-list 'load-path script-filename)
-             (require 'ssh-deploy)
              (ssh-deploy--diff-directories-data directory-a directory-b 
exclude-list))
            (lambda(diff)
              (message "Completed calculation of differences between directory 
'%s' and '%s'. Result: %s only in A %s only in B %s differs. (asynchronously)" 
(nth 0 diff) (nth 1 diff) (length (nth 4 diff)) (length (nth 5 diff)) (length 
(nth 7 diff)))
-             (if (or (> (length (nth 4 diff)) 0) (> (length (nth 5 diff)) 0) 
(> (length (nth 7 diff)) 0))
-                 (ssh-deploy--diff-directories-present diff directory-a 
directory-b on-explicit-save debug async async-with-threads revision-folder 
remote-changes exclude-list)))
+             (when (or (> (length (nth 4 diff)) 0) (> (length (nth 5 diff)) 0) 
(> (length (nth 7 diff)) 0))
+               (ssh-deploy--diff-directories-present diff directory-a 
directory-b on-explicit-save debug async async-with-threads revision-folder 
remote-changes exclude-list)))
            async-with-threads))
-      (progn
-        (message "Calculating differences between directory '%s' and '%s'.. 
(synchronously)" directory-a directory-b)
-        (let ((diff (ssh-deploy--diff-directories-data directory-a directory-b 
exclude-list)))
-          (message "Completed calculation of differences between directory 
'%s' and '%s'. Result: %s only in A, %s only in B, %s differs. (synchronously)" 
(nth 0 diff) (nth 1 diff) (length (nth 4 diff)) (length (nth 5 diff)) (length 
(nth 7 diff)))
-          (if (or (> (length (nth 4 diff)) 0) (> (length (nth 5 diff)) 0) (> 
(length (nth 7 diff)) 0))
-              (ssh-deploy--diff-directories-present diff directory-a 
directory-b on-explicit-save debug async async-with-threads revision-folder 
remote-changes exclude-list)))))))
-
-;;;###autoload
-(defun ssh-deploy-remote-changes (path-local &optional root-local root-remote 
async revision-folder exclude-list async-with-threads)
-  "Check if a local revision for PATH-LOCAL on ROOT-LOCAL and if remote file 
has changed on ROOT-REMOTE, do it optionally asynchronously if ASYNC is true, 
check for copies in REVISION-FOLDER and skip if path is in EXCLUDE-LIST.  Use 
multi-threading if ASYNC-WITH-THREADS is above zero."
+      (message "Calculating differences between directory '%s' and '%s'.. 
(synchronously)" directory-a directory-b)
+      (let ((diff (ssh-deploy--diff-directories-data directory-a directory-b 
exclude-list)))
+        (message "Completed calculation of differences between directory '%s' 
and '%s'. Result: %s only in A, %s only in B, %s differs. (synchronously)" (nth 
0 diff) (nth 1 diff) (length (nth 4 diff)) (length (nth 5 diff)) (length (nth 7 
diff)))
+        (when (or (> (length (nth 4 diff)) 0) (> (length (nth 5 diff)) 0) (> 
(length (nth 7 diff)) 0))
+          (ssh-deploy--diff-directories-present diff directory-a directory-b 
on-explicit-save debug async async-with-threads revision-folder remote-changes 
exclude-list))))))
+
+(defun ssh-deploy--remote-changes-post-executor (response verbose)
+  "Process RESPONSE from `ssh-deploy--remote-changes-data' with flags: 
VERBOSE."
+  (pcase (nth 0 response)
+    (0
+     ;; File is outside of root
+     (when (> verbose 0) (message (nth 1 response))))
+    (1
+     ;; File is excluded from deployment
+     (when (> verbose 0) (message (nth 1 response))))
+    (2
+     ;; File is a directory ignore
+     (when (> verbose 0) (message (nth 1 response))))
+    (3
+     ;; Remote file does not exist
+     (when (message (nth 1 response))))
+    (4
+     ;; Remote file has not changed
+     (when (> verbose 0) (message (nth 1 response))))
+    (5
+     ;; Remote file has changed in comparison with local revision
+     (display-warning 'ssh-deploy (nth 1 response) :warning))
+    (6
+     ;; Remote file has not changed in comparison with local file
+     (copy-file (nth 2 response) (nth 3 response) t t t t)
+     (when (> verbose 0) (message (nth 1 response))))
+    (7
+     ;; Remote file has changed in comparison with local file
+     (display-warning 'ssh-deploy (nth 1 response) :warning))))
+
+(defun ssh-deploy--remote-changes-data (path-local &optional root-local 
root-remote revision-folder exclude-list)
+  "Check if a local revision for PATH-LOCAL on ROOT-LOCAL and if remote file 
has changed on ROOT-REMOTE, check for copies in REVISION-FOLDER and skip if 
path is in EXCLUDE-LIST.  Should only return status-code and message."
   (let ((root-local (or root-local ssh-deploy-root-local))
         (root-remote (or root-remote ssh-deploy-root-remote))
         (exclude-list (or exclude-list ssh-deploy-exclude-list)))
 
     ;; Is the file inside the local-root and should it not be excluded?
-    (if (and (ssh-deploy--file-is-in-path path-local root-local)
-             (ssh-deploy--file-is-included path-local exclude-list))
-        (let* ((revision-folder (or revision-folder 
ssh-deploy-revision-folder))
-               (revision-path (ssh-deploy--get-revision-path path-local 
revision-folder))
-               (path-remote (expand-file-name (ssh-deploy--get-relative-path 
root-local path-local) root-remote)))
-
-          ;; Is the file a regular file?
-          (if (not (file-directory-p path-local))
-              (progn
+    (if (ssh-deploy--file-is-in-path-p path-local root-local)
+        (if (ssh-deploy--file-is-included-p path-local exclude-list)
+            (let* ((revision-folder (or revision-folder 
ssh-deploy-revision-folder))
+                   (revision-path (ssh-deploy--get-revision-path path-local 
revision-folder))
+                   (path-remote (expand-file-name 
(ssh-deploy--get-relative-path root-local path-local) root-remote)))
+
+              ;; Is the file a regular file?
+              (if (not (file-directory-p path-local))
+
+                  ;; Does remote file exists?
+                  (if (file-exists-p path-remote)
 
-                ;; Does a local revision of the file exist?
-                (if (file-exists-p revision-path)
-
-                    ;; Local revision exist. Is async enabled?
-                    (if (> async 0)
-                        (progn
-
-                          ;; Update buffer status
-                          (ssh-deploy--mode-line-set-status-and-update 
ssh-deploy--status-detecting-remote-changes)
-
-                          ;; Asynchronous logic here
-                          (ssh-deploy--async-process
-                           (lambda()
-                             (if (file-exists-p path-remote)
-                                 (progn
-                                   (require 'ediff-util)
-                                   (if (fboundp 'ediff-same-file-contents)
-                                       (if (ediff-same-file-contents 
revision-path path-remote)
-                                           (list 0 (format "Remote file '%s' 
has not changed. (asynchronously)" path-remote) path-local)
-                                         (if (ediff-same-file-contents 
path-local path-remote)
-                                             (progn
-                                               (copy-file path-local 
revision-path t t t t)
-                                               (list 0 (format "Remote file 
'%s' is identical to local file '%s' but different to local revision. Updated 
local revision. (asynchronously)" path-remote path-local) path-local))
-                                           (list 1 (format "Remote file '%s' 
has changed please download or diff. (asynchronously)" path-remote) 
path-local)))
-                                     (list 1 "Function 
'ediff-same-file-contents' is missing. (asynchronously)" path-local)))
-                               (list 0 (format "Remote file '%s' doesn't 
exist. (asynchronously)" path-remote) path-local)))
-                           (lambda(return)
-
-                             ;; Update buffer status to idle
-                             (ssh-deploy--mode-line-set-status-and-update 
ssh-deploy--status-idle (nth 2 return))
-
-                             (if (= (nth 0 return) 0)
-                                 (when ssh-deploy-verbose (message (nth 1 
return)))
-                               (display-warning 'ssh-deploy (nth 1 return) 
:warning)))
-                           async-with-threads))
-
-                      ;; Async is not enabled - synchronous logic here
-                      (progn
-
-                        ;; Update buffer status
-                        (ssh-deploy--mode-line-set-status-and-update 
ssh-deploy--status-detecting-remote-changes)
-
-                        ;; Does remote file exist?
-                        (if (file-exists-p path-remote)
-                            (progn
-                              (require 'ediff-util)
-                              (if (fboundp 'ediff-same-file-contents)
-                                  (if (ediff-same-file-contents revision-path 
path-remote)
-                                      (when ssh-deploy-verbose (message 
"Remote file '%s' has not changed. (synchronously)" path-remote))
-                                    (display-warning 'ssh-deploy (format 
"Remote file '%s' has changed, please download or diff. (synchronously)" 
path-remote) :warning))
-                                (display-warning 'ssh-deploy "Function 
'ediff-same-file-contents' is missing. (synchronously)" :warning)))
-                          (when ssh-deploy-verbose (message "Remote file '%s' 
doesn't exist. (synchronously)" path-remote)))
-
-                        ;; Update buffer status to idle
-                        (ssh-deploy--mode-line-set-status-and-update 
ssh-deploy--status-idle)))
-
-                  ;; Does not have local revision. Is async enabled?
-                  (if (> async 0)
-                      (progn
-
-                        ;; Update buffer status
-                        (ssh-deploy--mode-line-set-status-and-update 
ssh-deploy--status-detecting-remote-changes)
-
-                        ;; Asynchronous logic here
-                        (ssh-deploy--async-process
-                         (lambda()
-
-                           ;; Does remote file exist?
-                           (if (file-exists-p path-remote)
-                               (progn
-                                 (require 'ediff-util)
-                                 (if (fboundp 'ediff-same-file-contents)
-                                     (if (ediff-same-file-contents path-local 
path-remote)
-                                         (progn
-                                           (copy-file path-local revision-path 
t t t t)
-                                           (list 0 (format "Remote file '%s' 
has not changed, created base revision. (asynchronously)" path-remote) 
path-local))
-                                       (list 1 (format "Remote file '%s' has 
changed please download or diff. (asynchronously)" path-remote) path-local))
-                                   (list 1 "Function ediff-file-same-contents 
is missing. (asynchronously)" path-local)))
-                             (list 0 (format "Remote file '%s' doesn't exist. 
(asynchronously)" path-remote) path-local)))
-                         (lambda(return)
-
-                           ;; Update buffer status to idle
-                           (ssh-deploy--mode-line-set-status-and-update 
ssh-deploy--status-idle (nth 2 return))
-
-                           (if (= (nth 0 return) 0)
-                               (when ssh-deploy-verbose (message (nth 1 
return)))
-                             (display-warning 'ssh-deploy (nth 1 return) 
:warning)))
-                         async-with-threads))
-
-                    ;; Async is not enabled - synchronous logic here
-                    (progn
-
-                      ;; Update buffer status
-                      (ssh-deploy--mode-line-set-status-and-update 
ssh-deploy--status-detecting-remote-changes)
-
-                      ;; Does remote file exist?
-                      (if (file-exists-p path-remote)
-                          (progn
-                            (require 'ediff-util)
-                            (if (fboundp 'ediff-same-file-contents)
-                                (if (ediff-same-file-contents path-local 
path-remote)
-                                    (progn
-                                      (copy-file path-local revision-path t t 
t t)
-                                      (when ssh-deploy-verbose (message 
"Remote file '%s' has not changed, created base revision. (synchronously)" 
path-remote)))
-                                  (display-warning 'ssh-deploy (format "Remote 
file '%s' has changed, please download or diff. (synchronously)" path-remote) 
:warning))
-                              (display-warning 'ssh-deploy "Function 
'ediff-same-file-contents' is missing. (synchronously)" :warning)))
-                        (when ssh-deploy-verbose (message "Remote file '%s' 
does not exist. (synchronously)" path-remote)))
-
-                      ;; Update buffer status to idle
-                      (ssh-deploy--mode-line-set-status-and-update 
ssh-deploy--status-idle)))))
-
-            ;; File is a directory
-            (when (> ssh-deploy-debug 0) (message "File %s is a directory, 
ignoring remote changes check." path-local))))
-
-      ;; File is not inside root or is excluded from it
+                      ;; Does a local revision of the file exist?
+                      (if (file-exists-p revision-path)
+
+                          (if (ediff-same-file-contents revision-path 
path-remote)
+                              (list 4 (format "Remote file '%s' has not 
changed." path-remote) path-local)
+                            (list 5 (format "Remote file '%s' has changed 
compared to local revision, please download or diff." path-remote) path-local 
revision-path))
+
+                        (if (ediff-same-file-contents path-local path-remote)
+                            (list 6 (format "Remote file '%s' has not changed 
compared to local file, created local revision." path-remote) path-local 
revision-path)
+                          (list 7 (format "Remote file '%s' has changed 
compared to local file, please download or diff." path-remote) path-local 
path-remote)))
+
+                    (list 3 (format "Remote file '%s' doesn't exist." 
path-remote) path-local))
+
+                ;; File is a directory
+                (list 2 (format "File '%s' is a directory, ignoring remote 
changes check." path-local) path-local)))
+
+          ;; File is excluded from root
+          (list 1 (format "File '%s' is excluded from deployment." path-local) 
path-local))
+
+      ;; File is not inside root
+      (list 0 (format "File '%s' is not in root '%s'" path-local root-local) 
path-local))))
+
+;;;###autoload
+(defun ssh-deploy-remote-changes (path-local &optional root-local root-remote 
async revision-folder exclude-list async-with-threads verbose)
+  "Check if a local revision for PATH-LOCAL on ROOT-LOCAL and if remote file 
has changed on ROOT-REMOTE, do it optionally asynchronously if ASYNC is true, 
check for copies in REVISION-FOLDER and skip if path is in EXCLUDE-LIST.  Use 
multi-threading if ASYNC-WITH-THREADS is above zero, VERBOSE if value above 
zero."
+  (let ((root-local (or root-local ssh-deploy-root-local))
+        (root-remote (or root-remote ssh-deploy-root-remote))
+        (exclude-list (or exclude-list ssh-deploy-exclude-list))
+        (verbose (or verbose ssh-deploy-verbose))
+        (revision-folder (or revision-folder ssh-deploy-revision-folder)))
+    ;; Is the file inside the local-root and should it not be excluded?
+    (if (and (ssh-deploy--file-is-in-path-p path-local root-local)
+             (ssh-deploy--file-is-included-p path-local exclude-list))
+        ;; Is the file a regular file?
+        (if (not (file-directory-p path-local))
+            (progn
+              ;; Update mode-line status to detecting remote changes
+              (ssh-deploy--mode-line-set-status-and-update 
ssh-deploy--status-detecting-remote-changes)
+              (if (> async 0)
+                  (ssh-deploy--async-process
+                   (lambda()
+                     (ssh-deploy--remote-changes-data path-local root-local 
root-remote revision-folder exclude-list))
+                   (lambda(response)
+                     ;; Update buffer status to idle
+                     (ssh-deploy--mode-line-set-status-and-update 
ssh-deploy--status-idle (nth 2 response))
+                     (ssh-deploy--remote-changes-post-executor response 
verbose))
+                   async-with-threads)
+                (let ((response (ssh-deploy--remote-changes-data path-local 
root-local root-remote revision-folder exclude-list)))
+                  ;; Update buffer status to idle
+                  (ssh-deploy--mode-line-set-status-and-update 
ssh-deploy--status-idle (nth 2 response))
+                  (ssh-deploy--remote-changes-post-executor response 
verbose))))
+          (when (> ssh-deploy-debug 0) (message "File %s is a directory, 
ignoring remote changes check." path-local)))
       (when (> ssh-deploy-debug 0) (message "File %s is not in root or is 
excluded from it." path-local)))))
 
 (defun ssh-deploy-delete (path &optional async async-with-threads)
@@ -906,8 +892,8 @@
         (debug (or debug ssh-deploy-debug))
         (exclude-list (or exclude-list ssh-deploy-exclude-list))
         (async-with-threads (or async async-with-threads)))
-    (if (and (ssh-deploy--file-is-in-path path-local root-local)
-             (ssh-deploy--file-is-included path-local exclude-list))
+    (if (and (ssh-deploy--file-is-in-path-p path-local root-local)
+             (ssh-deploy--file-is-included-p path-local exclude-list))
         (let ((path-remote (expand-file-name (ssh-deploy--get-relative-path 
root-local path-local) root-remote)))
           (ssh-deploy-delete path-local async async-with-threads)
           (ssh-deploy-delete path-remote async async-with-threads))
@@ -922,10 +908,10 @@
         (debug (or debug ssh-deploy-debug))
         (exclude-list (or exclude-list ssh-deploy-exclude-list))
         (async-with-threads (or async-with-threads 
ssh-deploy-async-with-threads)))
-    (if (and (ssh-deploy--file-is-in-path old-path-local root-local)
-             (ssh-deploy--file-is-in-path new-path-local root-local)
-             (ssh-deploy--file-is-included old-path-local exclude-list)
-             (ssh-deploy--file-is-included new-path-local exclude-list))
+    (if (and (ssh-deploy--file-is-in-path-p old-path-local root-local)
+             (ssh-deploy--file-is-in-path-p new-path-local root-local)
+             (ssh-deploy--file-is-included-p old-path-local exclude-list)
+             (ssh-deploy--file-is-included-p new-path-local exclude-list))
         (let ((old-path-remote (expand-file-name 
(ssh-deploy--get-relative-path root-local old-path-local) root-remote))
               (new-path-remote (expand-file-name 
(ssh-deploy--get-relative-path root-local new-path-local) root-remote)))
           (ssh-deploy--mode-line-set-status-and-update 
ssh-deploy--status-renaming)
@@ -946,12 +932,11 @@
                  (ssh-deploy--mode-line-set-status-and-update 
ssh-deploy--status-idle (nth 2 files))
                  (message "Renamed '%s' to '%s'. (asynchronously)" (nth 0 
files) (nth 1 files)))
                async-with-threads)
-            (progn
-              (rename-file old-path-remote new-path-remote t)
-              (ssh-deploy--mode-line-set-status-and-update 
ssh-deploy--status-idle)
-              (message "Renamed '%s' to '%s'. (synchronously)" old-path-remote 
new-path-remote))))
-      (if (> debug 0)
-          (message "Path '%s' or '%s' is not in the root '%s' or is excluded 
from it." old-path-local new-path-local root-local)))))
+            (rename-file old-path-remote new-path-remote t)
+            (ssh-deploy--mode-line-set-status-and-update 
ssh-deploy--status-idle)
+            (message "Renamed '%s' to '%s'. (synchronously)" old-path-remote 
new-path-remote)))
+      (when (> debug 0)
+        (message "Path '%s' or '%s' is not in the root '%s' or is excluded 
from it." old-path-local new-path-local root-local)))))
 
 ;;;###autoload
 (defun ssh-deploy-remote-sql (remote-path &optional type)
@@ -983,11 +968,11 @@
   (let ((root-local (or root-local ssh-deploy-root-local))
         (root-remote (or root-remote ssh-deploy-root-remote))
         (exclude-list (or exclude-list ssh-deploy-exclude-list)))
-    (if (and (ssh-deploy--file-is-in-path path-local root-local)
-             (ssh-deploy--file-is-included path-local exclude-list))
-        (let ((path-remote (expand-file-name (ssh-deploy--get-relative-path 
root-local path-local) root-remote)))
-          (message "Opening '%s' for browsing on remote host.." path-remote)
-          (dired path-remote)))))
+    (when (and (ssh-deploy--file-is-in-path-p path-local root-local)
+               (ssh-deploy--file-is-included-p path-local exclude-list))
+      (let ((path-remote (expand-file-name (ssh-deploy--get-relative-path 
root-local path-local) root-remote)))
+        (message "Opening '%s' for browsing on remote host.." path-remote)
+        (dired path-remote)))))
 
 ;;;###autoload
 (defun ssh-deploy-remote-terminal-eshell (path-local &optional root-local 
root-remote exclude-list)
@@ -995,10 +980,9 @@
   (let ((root-local (or root-local ssh-deploy-root-local))
         (root-remote (or root-remote ssh-deploy-root-remote))
         (exclude-list (or exclude-list ssh-deploy-exclude-list)))
-    (when (and (ssh-deploy--file-is-in-path path-local root-local)
-               (ssh-deploy--file-is-included path-local exclude-list))
+    (when (and (ssh-deploy--file-is-in-path-p path-local root-local)
+               (ssh-deploy--file-is-included-p path-local exclude-list))
       (let ((path-remote (expand-file-name (ssh-deploy--get-relative-path 
root-local path-local) root-remote)))
-        (require 'eshell)
         (message "Opening eshell on '%s'.." path-remote)
         (let ((default-directory path-remote))
           (defvar eshell-buffer-name)
@@ -1011,10 +995,9 @@
   (let ((root-local (or root-local ssh-deploy-root-local))
         (root-remote (or root-remote ssh-deploy-root-remote))
         (exclude-list (or exclude-list ssh-deploy-exclude-list)))
-    (when (and (ssh-deploy--file-is-in-path path-local root-local)
-               (ssh-deploy--file-is-included path-local exclude-list))
+    (when (and (ssh-deploy--file-is-in-path-p path-local root-local)
+               (ssh-deploy--file-is-included-p path-local exclude-list))
       (let ((path-remote (expand-file-name (ssh-deploy--get-relative-path 
root-local path-local) root-remote)))
-        (require 'shell)
         (message "Opening eshell on '%s'.." path-remote)
         (let ((default-directory path-remote)
               (explicit-shell-file-name ssh-deploy-remote-shell-executable))
@@ -1024,11 +1007,11 @@
 ;;;###autoload
 (defun ssh-deploy-store-revision (path &optional root)
   "Store PATH in revision-folder ROOT."
-  (if (not (file-directory-p path))
-      (let* ((root (or root ssh-deploy-revision-folder))
-             (revision-path (ssh-deploy--get-revision-path path root)))
-        (when ssh-deploy-verbose (message "Storing revision of '%s' at '%s'.." 
path revision-path))
-        (copy-file path revision-path t t t t))))
+  (unless (file-directory-p path)
+    (let* ((root (or root ssh-deploy-revision-folder))
+           (revision-path (ssh-deploy--get-revision-path path root)))
+      (when (> ssh-deploy-verbose 0) (message "Storing revision of '%s' at 
'%s'.." path revision-path))
+      (copy-file path revision-path t t t t))))
 
 ;;;###autoload
 (defun ssh-deploy-diff (path-local path-remote &optional root-local debug 
exclude-list async async-with-threads on-explicit-save revision-folder 
remote-changes)
@@ -1042,8 +1025,8 @@
         (on-explicit-save (or on-explicit-save ssh-deploy-on-explicit-save))
         (revision-folder (or revision-folder ssh-deploy-revision-folder))
         (remote-changes (or remote-changes 
ssh-deploy-automatically-detect-remote-changes)))
-    (if (and (ssh-deploy--file-is-in-path path-local root-local)
-             (ssh-deploy--file-is-included path-local exclude-list))
+    (if (and (ssh-deploy--file-is-in-path-p path-local root-local)
+             (ssh-deploy--file-is-included-p path-local exclude-list))
         (if file-or-directory
             (ssh-deploy-diff-files path-local path-remote)
           (ssh-deploy-diff-directories path-local path-remote on-explicit-save 
debug async async-with-threads revision-folder remote-changes exclude-list))
@@ -1051,7 +1034,7 @@
 
 ;;;###autoload
 (defun ssh-deploy-upload (path-local path-remote &optional force async 
revision-folder async-with-threads)
-  "Upload PATH-LOCAL to PATH-REMOTE and ROOT-LOCAL via TRAMP, FORCE uploads 
despite remote change, ASYNC determines if transfer should be asynchronously, 
check version in REVISION-FOLDER.  If you want asynchronous threads pass 
ASYNC-WITH-THREADS above zero."
+  "Upload PATH-LOCAL to PATH-REMOTE and ROOT-LOCAL via Tramp, FORCE uploads 
despite remote change, ASYNC determines if transfer should be asynchronously, 
check version in REVISION-FOLDER.  If you want asynchronous threads pass 
ASYNC-WITH-THREADS above zero."
   (let ((force (or force 0))
         (async (or async ssh-deploy-async))
         (revision-folder (or revision-folder ssh-deploy-revision-folder))
@@ -1062,7 +1045,7 @@
 
 ;;;###autoload
 (defun ssh-deploy-download (path-remote path-local &optional async 
revision-folder async-with-threads)
-  "Download PATH-REMOTE to PATH-LOCAL via TRAMP, ASYNC determines if transfer 
should be asynchrous or not, check for revisions in REVISION-FOLDER.  If you 
want asynchronous threads pass ASYNC-WITH-THREADS above zero."
+  "Download PATH-REMOTE to PATH-LOCAL via Tramp, ASYNC determines if transfer 
should be asynchrous or not, check for revisions in REVISION-FOLDER.  If you 
want asynchronous threads pass ASYNC-WITH-THREADS above zero."
   (let ((async (or async ssh-deploy-async))
         (revision-folder (or revision-folder ssh-deploy-revision-folder))
         (async-with-threads (or async-with-threads 
ssh-deploy-async-with-threads)))
@@ -1081,23 +1064,23 @@
 (defun ssh-deploy-upload-handler (&optional force)
   "Upload current path to remote if it is configured for deployment and if 
remote version hasn't changed or FORCE is specified."
   (interactive)
-  (if (and (ssh-deploy--is-not-empty-string ssh-deploy-root-local)
-           (ssh-deploy--is-not-empty-string ssh-deploy-root-remote))
-      (let ((root-local (file-truename ssh-deploy-root-local))
-            (force (or force 0))
-            path-local)
-        (if (and (ssh-deploy--is-not-empty-string buffer-file-name)
-                 (file-exists-p buffer-file-name))
-            (setq path-local (file-truename buffer-file-name))
-          (if (and (ssh-deploy--is-not-empty-string default-directory)
+  (when (and (ssh-deploy--is-not-empty-string-p ssh-deploy-root-local)
+             (ssh-deploy--is-not-empty-string-p ssh-deploy-root-remote))
+    (let ((root-local (file-truename ssh-deploy-root-local))
+          (force (or force 0))
+          path-local)
+      (if (and (ssh-deploy--is-not-empty-string-p buffer-file-name)
+               (file-exists-p buffer-file-name))
+          (setq path-local (file-truename buffer-file-name))
+        (when (and (ssh-deploy--is-not-empty-string-p default-directory)
                    (file-exists-p default-directory))
-              (setq path-local (file-truename default-directory))))
-        (if (and (ssh-deploy--is-not-empty-string path-local)
-                 (ssh-deploy--file-is-in-path path-local root-local)
-                 (ssh-deploy--file-is-included path-local 
ssh-deploy-exclude-list))
-            (let ((path-remote (expand-file-name 
(ssh-deploy--get-relative-path root-local path-local) ssh-deploy-root-remote)))
-              (ssh-deploy-upload path-local path-remote force ssh-deploy-async 
ssh-deploy-revision-folder ssh-deploy-async-with-threads))
-          (when (> ssh-deploy-debug 0) (message "Ignoring upload, path '%s' is 
empty, not in the root '%s' or is excluded from it." path-local root-local))))))
+          (setq path-local (file-truename default-directory))))
+      (if (and (ssh-deploy--is-not-empty-string-p path-local)
+               (ssh-deploy--file-is-in-path-p path-local root-local)
+               (ssh-deploy--file-is-included-p path-local 
ssh-deploy-exclude-list))
+          (let ((path-remote (expand-file-name (ssh-deploy--get-relative-path 
root-local path-local) ssh-deploy-root-remote)))
+            (ssh-deploy-upload path-local path-remote force ssh-deploy-async 
ssh-deploy-revision-folder ssh-deploy-async-with-threads))
+        (when (> ssh-deploy-debug 0) (message "Ignoring upload, path '%s' is 
empty, not in the root '%s' or is excluded from it." path-local root-local))))))
 
 ;;;###autoload
 (defun ssh-deploy-upload-handler-forced ()
@@ -1109,9 +1092,9 @@
 (defun ssh-deploy-remote-changes-handler()
   "Check if local revision exists or remote file has changed if path is 
configured for deployment."
   (interactive)
-  (if (and (ssh-deploy--is-not-empty-string ssh-deploy-root-local)
-           (ssh-deploy--is-not-empty-string ssh-deploy-root-remote)
-           (ssh-deploy--is-not-empty-string buffer-file-name))
+  (if (and (ssh-deploy--is-not-empty-string-p ssh-deploy-root-local)
+           (ssh-deploy--is-not-empty-string-p ssh-deploy-root-remote)
+           (ssh-deploy--is-not-empty-string-p buffer-file-name))
       (progn
         (when (> ssh-deploy-debug 0) (message "Detecting remote-changes.."))
         (ssh-deploy-remote-changes (file-truename buffer-file-name) 
(file-truename ssh-deploy-root-local) ssh-deploy-root-remote ssh-deploy-async 
ssh-deploy-revision-folder ssh-deploy-exclude-list 
ssh-deploy-async-with-threads))
@@ -1121,174 +1104,174 @@
 (defun ssh-deploy-remote-sql-mysql-handler()
   "Open `sql-mysql' on remote path if path is configured for deployment."
   (interactive)
-  (when (ssh-deploy--is-not-empty-string ssh-deploy-root-remote)
+  (when (ssh-deploy--is-not-empty-string-p ssh-deploy-root-remote)
     (ssh-deploy-remote-sql ssh-deploy-root-remote "mysql")))
 
 ;;;###autoload
 (defun ssh-deploy-remote-sql-postgres-handler()
   "Open `sql-postgres' on remote path if path is configured for deployment."
   (interactive)
-  (when (ssh-deploy--is-not-empty-string ssh-deploy-root-remote)
+  (when (ssh-deploy--is-not-empty-string-p ssh-deploy-root-remote)
     (ssh-deploy-remote-sql ssh-deploy-root-remote "postgres")))
 
 ;;;###autoload
 (defun ssh-deploy-open-remote-file-handler()
   "Check if local revision exists or remote file has changed if path is 
configured for deployment."
   (interactive)
-  (if (and (ssh-deploy--is-not-empty-string ssh-deploy-root-local)
-           (ssh-deploy--is-not-empty-string ssh-deploy-root-remote)
-           (ssh-deploy--is-not-empty-string buffer-file-name))
-      (let* ((root-local (file-truename ssh-deploy-root-local))
-             (path-local (file-truename buffer-file-name))
-             (path-remote (expand-file-name (ssh-deploy--get-relative-path 
root-local path-local) ssh-deploy-root-remote)))
-        (when ssh-deploy-verbose (message "Opening file on remote '%s'" 
path-remote))
-        (find-file path-remote))))
+  (when (and (ssh-deploy--is-not-empty-string-p ssh-deploy-root-local)
+             (ssh-deploy--is-not-empty-string-p ssh-deploy-root-remote)
+             (ssh-deploy--is-not-empty-string-p buffer-file-name))
+    (let* ((root-local (file-truename ssh-deploy-root-local))
+           (path-local (file-truename buffer-file-name))
+           (path-remote (expand-file-name (ssh-deploy--get-relative-path 
root-local path-local) ssh-deploy-root-remote)))
+      (when (> ssh-deploy-verbose 0) (message "Opening file on remote '%s'" 
path-remote))
+      (find-file path-remote))))
 
 ;;;###autoload
 (defun ssh-deploy-download-handler ()
   "Download current path from remote if it is configured for deployment."
   (interactive)
-  (if (and (ssh-deploy--is-not-empty-string ssh-deploy-root-local)
-           (ssh-deploy--is-not-empty-string ssh-deploy-root-remote))
-      (let ((root-local (file-truename ssh-deploy-root-local))
-            path-local)
-        (if (and (ssh-deploy--is-not-empty-string buffer-file-name)
-                 (file-exists-p buffer-file-name))
-            (setq path-local (file-truename buffer-file-name))
-          (if (and (ssh-deploy--is-not-empty-string default-directory)
+  (when (and (ssh-deploy--is-not-empty-string-p ssh-deploy-root-local)
+             (ssh-deploy--is-not-empty-string-p ssh-deploy-root-remote))
+    (let ((root-local (file-truename ssh-deploy-root-local))
+          path-local)
+      (if (and (ssh-deploy--is-not-empty-string-p buffer-file-name)
+               (file-exists-p buffer-file-name))
+          (setq path-local (file-truename buffer-file-name))
+        (when (and (ssh-deploy--is-not-empty-string-p default-directory)
                    (file-exists-p default-directory))
-              (setq path-local (file-truename default-directory))))
-        (if (and (ssh-deploy--is-not-empty-string path-local)
-                 (ssh-deploy--file-is-in-path path-local root-local)
-                 (ssh-deploy--file-is-included path-local 
ssh-deploy-exclude-list))
-            (let ((path-remote (expand-file-name 
(ssh-deploy--get-relative-path root-local path-local) ssh-deploy-root-remote)))
-              (ssh-deploy-download path-remote path-local ssh-deploy-async 
ssh-deploy-revision-folder ssh-deploy-async-with-threads))
-          (when (> ssh-deploy-debug 0) (message "Ignoring upload, path '%s' is 
empty, not in the root '%s' or is excluded from it." path-local root-local))))))
+          (setq path-local (file-truename default-directory))))
+      (if (and (ssh-deploy--is-not-empty-string-p path-local)
+               (ssh-deploy--file-is-in-path-p path-local root-local)
+               (ssh-deploy--file-is-included-p path-local 
ssh-deploy-exclude-list))
+          (let ((path-remote (expand-file-name (ssh-deploy--get-relative-path 
root-local path-local) ssh-deploy-root-remote)))
+            (ssh-deploy-download path-remote path-local ssh-deploy-async 
ssh-deploy-revision-folder ssh-deploy-async-with-threads))
+        (when (> ssh-deploy-debug 0) (message "Ignoring upload, path '%s' is 
empty, not in the root '%s' or is excluded from it." path-local root-local))))))
 
 ;;;###autoload
 (defun ssh-deploy-diff-handler ()
   "Compare current path with remote host if it is configured for deployment."
   (interactive)
-  (if (and (ssh-deploy--is-not-empty-string ssh-deploy-root-local)
-           (ssh-deploy--is-not-empty-string ssh-deploy-root-remote))
-      (if (and (ssh-deploy--is-not-empty-string buffer-file-name)
-               (file-exists-p buffer-file-name))
-          (let* ((path-local (file-truename buffer-file-name))
-                 (root-local (file-truename ssh-deploy-root-local))
-                 (path-remote (expand-file-name (ssh-deploy--get-relative-path 
root-local path-local) ssh-deploy-root-remote)))
-            (ssh-deploy-diff path-local path-remote root-local 
ssh-deploy-debug ssh-deploy-exclude-list ssh-deploy-async 
ssh-deploy-async-with-threads ssh-deploy-on-explicit-save 
ssh-deploy-revision-folder ssh-deploy-automatically-detect-remote-changes))
-        (if (and (ssh-deploy--is-not-empty-string default-directory)
+  (when (and (ssh-deploy--is-not-empty-string-p ssh-deploy-root-local)
+             (ssh-deploy--is-not-empty-string-p ssh-deploy-root-remote))
+    (if (and (ssh-deploy--is-not-empty-string-p buffer-file-name)
+             (file-exists-p buffer-file-name))
+        (let* ((path-local (file-truename buffer-file-name))
+               (root-local (file-truename ssh-deploy-root-local))
+               (path-remote (file-truename (expand-file-name 
(ssh-deploy--get-relative-path root-local path-local) ssh-deploy-root-remote))))
+          (ssh-deploy-diff path-local path-remote root-local ssh-deploy-debug 
ssh-deploy-exclude-list ssh-deploy-async ssh-deploy-async-with-threads 
ssh-deploy-on-explicit-save ssh-deploy-revision-folder 
ssh-deploy-automatically-detect-remote-changes))
+      (when (and (ssh-deploy--is-not-empty-string-p default-directory)
                  (file-exists-p default-directory))
-            (let* ((path-local (file-truename default-directory))
-                   (root-local (file-truename ssh-deploy-root-local))
-                   (path-remote (expand-file-name 
(ssh-deploy--get-relative-path root-local path-local) ssh-deploy-root-remote)))
-              (ssh-deploy-diff path-local path-remote root-local 
ssh-deploy-debug ssh-deploy-exclude-list ssh-deploy-async 
ssh-deploy-async-with-threads ssh-deploy-on-explicit-save 
ssh-deploy-revision-folder ssh-deploy-automatically-detect-remote-changes))))))
+        (let* ((path-local (file-truename default-directory))
+               (root-local (file-truename ssh-deploy-root-local))
+               (path-remote (file-truename (expand-file-name 
(ssh-deploy--get-relative-path root-local path-local) ssh-deploy-root-remote))))
+          (ssh-deploy-diff path-local path-remote root-local ssh-deploy-debug 
ssh-deploy-exclude-list ssh-deploy-async ssh-deploy-async-with-threads 
ssh-deploy-on-explicit-save ssh-deploy-revision-folder 
ssh-deploy-automatically-detect-remote-changes))))))
 
 ;;;###autoload
 (defun ssh-deploy-delete-handler ()
   "Delete current file or directory."
   (interactive)
-  (if (and (ssh-deploy--is-not-empty-string ssh-deploy-root-local)
-           (ssh-deploy--is-not-empty-string ssh-deploy-root-remote))
-      (if (and (ssh-deploy--is-not-empty-string buffer-file-name)
-               (file-exists-p buffer-file-name))
-          (let* ((path-local (file-truename buffer-file-name))
-                 (root-local (file-truename ssh-deploy-root-local))
-                 (yes-no-prompt (read-string (format "Type 'yes' to confirm 
that you want to delete the file '%s': " path-local))))
-            (if (string= yes-no-prompt "yes")
-                (ssh-deploy-delete-both path-local root-local 
ssh-deploy-root-remote ssh-deploy-async ssh-deploy-debug 
ssh-deploy-exclude-list ssh-deploy-async-with-threads)))
-        (if (and (ssh-deploy--is-not-empty-string default-directory)
+  (when (and (ssh-deploy--is-not-empty-string-p ssh-deploy-root-local)
+             (ssh-deploy--is-not-empty-string-p ssh-deploy-root-remote))
+    (if (and (ssh-deploy--is-not-empty-string-p buffer-file-name)
+             (file-exists-p buffer-file-name))
+        (let* ((path-local (file-truename buffer-file-name))
+               (root-local (file-truename ssh-deploy-root-local))
+               (yes-no-prompt (read-string (format "Type 'yes' to confirm that 
you want to delete the file '%s': " path-local))))
+          (when (string= yes-no-prompt "yes")
+            (ssh-deploy-delete-both path-local root-local 
ssh-deploy-root-remote ssh-deploy-async ssh-deploy-debug 
ssh-deploy-exclude-list ssh-deploy-async-with-threads)))
+      (when (and (ssh-deploy--is-not-empty-string-p default-directory)
                  (file-exists-p default-directory))
-            (let* ((path-local (file-truename default-directory))
-                   (root-local (file-truename ssh-deploy-root-local))
-                   (yes-no-prompt (read-string (format "Type 'yes' to confirm 
that you want to delete the directory '%s': " path-local))))
-              (if (string= yes-no-prompt "yes")
-                  (ssh-deploy-delete-both path-local root-local 
ssh-deploy-root-remote ssh-deploy-async ssh-deploy-debug 
ssh-deploy-exclude-list ssh-deploy-async-with-threads)))))))
+        (let* ((path-local (file-truename default-directory))
+               (root-local (file-truename ssh-deploy-root-local))
+               (yes-no-prompt (read-string (format "Type 'yes' to confirm that 
you want to delete the directory '%s': " path-local))))
+          (when (string= yes-no-prompt "yes")
+            (ssh-deploy-delete-both path-local root-local 
ssh-deploy-root-remote ssh-deploy-async ssh-deploy-debug 
ssh-deploy-exclude-list ssh-deploy-async-with-threads)))))))
 
 ;;;###autoload
 (defun ssh-deploy-rename-handler ()
   "Rename current file or directory."
   (interactive)
-  (if (and (ssh-deploy--is-not-empty-string ssh-deploy-root-local)
-           (ssh-deploy--is-not-empty-string ssh-deploy-root-remote))
-      (if (and (ssh-deploy--is-not-empty-string buffer-file-name)
-               (file-exists-p buffer-file-name))
-          (let* ((old-path-local (file-truename buffer-file-name))
-                 (root-local (file-truename ssh-deploy-root-local))
-                 (basename (file-name-nondirectory old-path-local))
-                 (new-path-local-tmp (read-file-name "New file name:" 
(file-name-directory old-path-local) basename nil basename))
-                 (new-path-local (file-truename new-path-local-tmp)))
-            (if (not (string= old-path-local new-path-local))
-                (ssh-deploy-rename old-path-local new-path-local root-local 
ssh-deploy-root-remote ssh-deploy-async ssh-deploy-debug 
ssh-deploy-exclude-list ssh-deploy-async-with-threads)))
-        (if (and (ssh-deploy--is-not-empty-string default-directory)
+  (when (and (ssh-deploy--is-not-empty-string-p ssh-deploy-root-local)
+             (ssh-deploy--is-not-empty-string-p ssh-deploy-root-remote))
+    (if (and (ssh-deploy--is-not-empty-string-p buffer-file-name)
+             (file-exists-p buffer-file-name))
+        (let* ((old-path-local (file-truename buffer-file-name))
+               (root-local (file-truename ssh-deploy-root-local))
+               (basename (file-name-nondirectory old-path-local))
+               (new-path-local-tmp (read-file-name "New file name:" 
(file-name-directory old-path-local) basename nil basename))
+               (new-path-local (file-truename new-path-local-tmp)))
+          (unless (string= old-path-local new-path-local)
+            (ssh-deploy-rename old-path-local new-path-local root-local 
ssh-deploy-root-remote ssh-deploy-async ssh-deploy-debug 
ssh-deploy-exclude-list ssh-deploy-async-with-threads)))
+      (when (and (ssh-deploy--is-not-empty-string-p default-directory)
                  (file-exists-p default-directory))
-            (let* ((old-path-local (file-truename default-directory))
-                   (root-local (file-truename ssh-deploy-root-local))
-                   (basename (file-name-nondirectory old-path-local))
-                   (new-path-local-tmp (read-file-name "New directory name:" 
(file-name-directory old-path-local) basename nil basename))
-                   (new-path-local (file-truename new-path-local-tmp)))
-              (if (not (string= old-path-local new-path-local))
-                  (ssh-deploy-rename old-path-local new-path-local root-local 
ssh-deploy-root-remote ssh-deploy-async ssh-deploy-debug 
ssh-deploy-exclude-list ssh-deploy-async-with-threads)))))))
+        (let* ((old-path-local (file-truename default-directory))
+               (root-local (file-truename ssh-deploy-root-local))
+               (basename (file-name-nondirectory old-path-local))
+               (new-path-local-tmp (read-file-name "New directory name:" 
(file-name-directory old-path-local) basename nil basename))
+               (new-path-local (file-truename new-path-local-tmp)))
+          (unless (string= old-path-local new-path-local)
+            (ssh-deploy-rename old-path-local new-path-local root-local 
ssh-deploy-root-remote ssh-deploy-async ssh-deploy-debug 
ssh-deploy-exclude-list ssh-deploy-async-with-threads)))))))
 
 ;;;###autoload
 (defun ssh-deploy-remote-terminal-eshell-handler ()
   "Open current relative path on remote host in `eshell' but only if it's 
configured for deployment."
   (interactive)
-  (if (and (ssh-deploy--is-not-empty-string ssh-deploy-root-local)
-           (ssh-deploy--is-not-empty-string ssh-deploy-root-remote)
-           (ssh-deploy--is-not-empty-string default-directory))
-      (let ((path-local (file-truename default-directory))
-            (root-local (file-truename ssh-deploy-root-local)))
-        (ssh-deploy-remote-terminal-eshell path-local root-local 
ssh-deploy-root-remote ssh-deploy-exclude-list))))
+  (when (and (ssh-deploy--is-not-empty-string-p ssh-deploy-root-local)
+             (ssh-deploy--is-not-empty-string-p ssh-deploy-root-remote)
+             (ssh-deploy--is-not-empty-string-p default-directory))
+    (let ((path-local (file-truename default-directory))
+          (root-local (file-truename ssh-deploy-root-local)))
+      (ssh-deploy-remote-terminal-eshell path-local root-local 
ssh-deploy-root-remote ssh-deploy-exclude-list))))
 
 ;;;###autoload
 (defun ssh-deploy-remote-terminal-eshell-base-handler ()
   "Open base path on remote host in `eshell' but only if it's configured for 
deployment."
   (interactive)
-  (if (and (ssh-deploy--is-not-empty-string ssh-deploy-root-local)
-           (ssh-deploy--is-not-empty-string ssh-deploy-root-remote))
-      (let ((root-local (file-truename ssh-deploy-root-local)))
-        (ssh-deploy-remote-terminal-eshell root-local root-local 
ssh-deploy-root-remote ssh-deploy-exclude-list))))
+  (when (and (ssh-deploy--is-not-empty-string-p ssh-deploy-root-local)
+             (ssh-deploy--is-not-empty-string-p ssh-deploy-root-remote))
+    (let ((root-local (file-truename ssh-deploy-root-local)))
+      (ssh-deploy-remote-terminal-eshell root-local root-local 
ssh-deploy-root-remote ssh-deploy-exclude-list))))
 
 ;;;###autoload
 (defun ssh-deploy-remote-terminal-shell-handler ()
   "Open current relative path on remote host in `eshell' but only if it's 
configured for deployment."
   (interactive)
-  (if (and (ssh-deploy--is-not-empty-string ssh-deploy-root-local)
-           (ssh-deploy--is-not-empty-string ssh-deploy-root-remote)
-           (ssh-deploy--is-not-empty-string default-directory))
-      (let ((path-local (file-truename default-directory))
-            (root-local (file-truename ssh-deploy-root-local)))
-        (ssh-deploy-remote-terminal-shell path-local root-local 
ssh-deploy-root-remote ssh-deploy-exclude-list))))
+  (when (and (ssh-deploy--is-not-empty-string-p ssh-deploy-root-local)
+             (ssh-deploy--is-not-empty-string-p ssh-deploy-root-remote)
+             (ssh-deploy--is-not-empty-string-p default-directory))
+    (let ((path-local (file-truename default-directory))
+          (root-local (file-truename ssh-deploy-root-local)))
+      (ssh-deploy-remote-terminal-shell path-local root-local 
ssh-deploy-root-remote ssh-deploy-exclude-list))))
 
 ;;;###autoload
 (defun ssh-deploy-remote-terminal-shell-base-handler ()
   "Open base path on remote host in `eshell' but only if it's configured for 
deployment."
   (interactive)
-  (if (and (ssh-deploy--is-not-empty-string ssh-deploy-root-local)
-           (ssh-deploy--is-not-empty-string ssh-deploy-root-remote))
-      (let ((root-local (file-truename ssh-deploy-root-local)))
-        (ssh-deploy-remote-terminal-shell root-local root-local 
ssh-deploy-root-remote ssh-deploy-exclude-list))))
+  (when (and (ssh-deploy--is-not-empty-string-p ssh-deploy-root-local)
+             (ssh-deploy--is-not-empty-string-p ssh-deploy-root-remote))
+    (let ((root-local (file-truename ssh-deploy-root-local)))
+      (ssh-deploy-remote-terminal-shell root-local root-local 
ssh-deploy-root-remote ssh-deploy-exclude-list))))
 
 ;;;###autoload
 (defun ssh-deploy-browse-remote-handler ()
   "Open current relative path on remote host in `dired-mode' if it is 
configured for deployment."
   (interactive)
-  (if (and (ssh-deploy--is-not-empty-string ssh-deploy-root-local)
-           (ssh-deploy--is-not-empty-string ssh-deploy-root-remote)
-           (ssh-deploy--is-not-empty-string default-directory))
-      (let ((path-local (file-truename default-directory))
-            (root-local (file-truename ssh-deploy-root-local)))
-        (ssh-deploy-browse-remote path-local root-local ssh-deploy-root-remote 
ssh-deploy-exclude-list))))
+  (when (and (ssh-deploy--is-not-empty-string-p ssh-deploy-root-local)
+             (ssh-deploy--is-not-empty-string-p ssh-deploy-root-remote)
+             (ssh-deploy--is-not-empty-string-p default-directory))
+    (let ((path-local (file-truename default-directory))
+          (root-local (file-truename ssh-deploy-root-local)))
+      (ssh-deploy-browse-remote path-local root-local ssh-deploy-root-remote 
ssh-deploy-exclude-list))))
 
 ;;;###autoload
 (defun ssh-deploy-browse-remote-base-handler ()
   "Open base path on remote host in `dired-mode' if it is configured for 
deployment."
   (interactive)
-  (if (and (ssh-deploy--is-not-empty-string ssh-deploy-root-local)
-           (ssh-deploy--is-not-empty-string ssh-deploy-root-remote))
-      (let ((root-local (file-truename ssh-deploy-root-local)))
-        (ssh-deploy-browse-remote root-local root-local ssh-deploy-root-remote 
ssh-deploy-exclude-list))))
+  (when (and (ssh-deploy--is-not-empty-string-p ssh-deploy-root-local)
+             (ssh-deploy--is-not-empty-string-p ssh-deploy-root-remote))
+    (let ((root-local (file-truename ssh-deploy-root-local)))
+      (ssh-deploy-browse-remote root-local root-local ssh-deploy-root-remote 
ssh-deploy-exclude-list))))
 
 ;;;###autoload
 (defun ssh-deploy-run-deploy-script-handler ()
@@ -1296,18 +1279,19 @@
   (interactive)
   (if ssh-deploy-script
       (if (> ssh-deploy-async 0)
-          (progn
+          (let ((root-local ssh-deploy-root-local)
+                (root-remote ssh-deploy-root-remote)
+                (script ssh-deploy-script))
             (message "Executing of deployment-script starting... 
(asynchronously)")
             (ssh-deploy--async-process
-             `(lambda() (let ((ssh-deploy-root-local ,ssh-deploy-root-local)
-                              (ssh-deploy-root-remote ,ssh-deploy-root-remote))
-                          (funcall ,ssh-deploy-script)))
+             (lambda() (let ((ssh-deploy-root-local root-local)
+                             (ssh-deploy-root-remote root-remote))
+                         (funcall script)))
              (lambda(result) (message "Completed execution of 
deployment-script. Return: '%s' (asynchronously)" result))
              ssh-deploy-async-with-threads))
-        (progn
-          (message "Executing of deployment-script starting... 
(synchronously)")
-          (let ((ret (funcall ssh-deploy-script)))
-            (message "Completed execution of deployment-script. Return: '%s' 
(synchronously)" ret))))
+        (message "Executing of deployment-script starting... (synchronously)")
+        (let ((ret (funcall ssh-deploy-script)))
+          (message "Completed execution of deployment-script. Return: '%s' 
(synchronously)" ret)))
     (display-warning 'ssh-deploy "ssh-deploy-script lacks definition!" 
:warning)))
 
 
@@ -1363,6 +1347,7 @@
 (define-minor-mode ssh-deploy-line-mode
   "Show SSH Deploy status in mode line"
   :global t
+  :require 'ssh-deploy
   :group 'ssh-deploy
   (add-to-list 'global-mode-string 'ssh-deploy--mode-line-status-text t))
 
@@ -1375,6 +1360,7 @@
 (defun ssh-deploy-after-save () "Logic for automatic uploads."
        (when (and (boundp 'ssh-deploy-on-explicit-save) 
ssh-deploy-on-explicit-save (> ssh-deploy-on-explicit-save 0)) 
(ssh-deploy-upload-handler)))
 
+;;;###autoload
 (defun ssh-deploy-add-after-save-hook () "Add the `after-save-hook'."
        (when (fboundp 'ssh-deploy-after-save)
          (add-hook 'after-save-hook 'ssh-deploy-after-save)))
@@ -1382,43 +1368,10 @@
 (defun ssh-deploy-find-file () "Logic for detecting remote change."
        (when (and (boundp 'ssh-deploy-automatically-detect-remote-changes) 
ssh-deploy-automatically-detect-remote-changes (> 
ssh-deploy-automatically-detect-remote-changes 0)) 
(ssh-deploy-remote-changes-handler)))
 
+;;;###autoload
 (defun ssh-deploy-add-find-file-hook () "Add the `find-file-hook'."
        (when (fboundp 'ssh-deploy-find-file) (add-hook 'find-file-hook 
'ssh-deploy-find-file)))
 
-(when (fboundp 'defhydra)
-  (defhydra ssh-deploy-hydra (:color red :hint nil)
-    "
-    SSH Deploy Menu
-    
-    _u_: Upload                              _f_: Force Upload
-    _d_: Download
-    _D_: Delete
-    _x_: Difference
-    _t_: Eshell Base Terminal                _T_: Eshell Relative Terminal
-    _h_: Shell Base Terminal                 _H_: Shell Relative Terminal
-    _e_: Detect Remote Changes
-    _R_: Rename
-    _b_: Browse Base                         _B_: Browse Relative
-    _o_: Open current file on remote         _m_: Open sql-mysql on remote
-    _s_: Run deploy script
-    "
-    ("f" ssh-deploy-upload-handler-forced)
-    ("u" ssh-deploy-upload-handler)
-    ("d" ssh-deploy-download-handler)
-    ("D" ssh-deploy-delete-handler)
-    ("x" ssh-deploy-diff-handler)
-    ("t" ssh-deploy-remote-terminal-eshell-base-handler)
-    ("T" ssh-deploy-remote-terminal-eshell-handler)
-    ("h" ssh-deploy-remote-terminal-shell-base-handler)
-    ("H" ssh-deploy-remote-terminal-shell-handler)
-    ("e" ssh-deploy-remote-changes-handler)
-    ("R" ssh-deploy-rename-handler)
-    ("b" ssh-deploy-browse-remote-base-handler)
-    ("B" ssh-deploy-browse-remote-handler)
-    ("o" ssh-deploy-open-remote-file-handler)
-    ("m" ssh-deploy-remote-sql-mysql-handler)
-    ("s" ssh-deploy-run-deploy-script-handler)))
-
 (defvar ssh-deploy-prefix-map
   (let ((map (make-sparse-keymap)))
     (define-key map "f" 'ssh-deploy-upload-handler-force)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]