Commit f02e16b6 authored by Lev Lamberov's avatar Lev Lamberov

New upstream version 0.4

parent 3a9c37e5
language: emacs-lisp
sudo: required
dist: trusty
cache:
- directories:
- "$HOME/emacs"
matrix:
fast_finish: true
allow_failures:
- env: EMACS_VERSION=snapshot
env:
matrix:
- EMACS_VERSION=25.1
- EMACS_VERSION=25.2
- EMACS_VERSION=25.3
- EMACS_VERSION=snapshot
before_install:
- make setup
install:
- make install
script:
- make test # test uncompiled
- make compile # test compilation
- make test # test compiled
# First, define the environment variables that drive EMake.
EENVS = PACKAGE_FILE="dired-rsync.el"
EENVS += PACKAGE_LISP="dired-rsync.el"
EENVS += PACKAGE_ARCHIVES="gnu melpa-stable"
EENVS += PACKAGE_TEST_DEPS="s dash package-lint"
EENVS += PACKAGE_TEST_ARCHIVES="melpa-stable"
# Then, make it easy to invoke Emacs with EMake loaded.
EMAKE := $(EENVS) emacs -batch -l emake.el --eval "(emake (pop argv))"
# Set up our phony targets so Make doesn't think there are files by
# these names.
.PHONY: clean setup install compile test
# Instruct Make on how to create `emake.el'
emake.el:
wget 'https://raw.githubusercontent.com/vermiculus/emake.el/master/emake.el'
# Instruct Make on how to create `emacs-travis.mk'
emacs-travis.mk:
wget 'https://raw.githubusercontent.com/flycheck/emacs-travis/master/emacs-travis.mk'
# Teach Make that '.elpa/' is created by `(emake "install")'
.elpa/:
$(EMAKE) install
## Phony targets
# Tell Make how to 'clean' this project
clean:
rm -f *.elc # delete compiled files
rm -rf .elpa/ # delete dependencies
rm -rf .elpa.test/
rm -f emacs-travis.mk # delete scripts
rm -f emake.el
# Tell Make how to 'setup' this project (e.g., for Travis). This
# requires both Emacs to be installed and the `emake.el' script to be
# available.
setup: emacs emake.el
# 'install' just means to create the .elpa/ directory (i.e., download dependencies)
install: .elpa/
# We want to clean before we compile.
compile:
rm -f *.elc
$(EMAKE) compile ~error-on-warn
# Testing needs dependencies
# Currently we only do linting and checkdoc
test: test-package-lint test-checkdoc
test-checkdoc: .elpa/
$(EMAKE) test checkdoc
test-package-lint: .elpa/
$(EMAKE) test package-lint
# The following lets you run this Makefile locally without installing
# Emacs over and over again. On Travis (and other CI services), the
# $CI environment variable is available as "true"; take advantage of
# this to provide two different implementations of the `emacs' target.
ifeq ($(CI),true)
emacs: emacs-travis.mk # This is CI. Emacs may not be available, so install it.
export PATH="$(HOME)/bin:$(PATH)"
make -f emacs-travis.mk install_emacs
else
emacs: # This is not CI. Emacs should already be available.
which emacs && emacs --version
endif
v0.4
- convert dired-rsync-[command|options] to defcustom
- added dired-rsync-unmark-on-completion option
- re-factored to keep temp data in lexically let variable
- and tramp path (as defined by tramp-tramp-file-p) will attempt to be converted to remote rsync
- updates to README.org
- A simple Travis base CI has been enabled
v0.3
- clean-up handling of finished tasks
- rationalise the quoting of arguments
......
#+Title: dired-rsync -- asynchronous rsync from dired
[[https://stable.melpa.org/#/dired-rsync][file:https://stable.melpa.org/packages/dired-rsync-badge.svg]]
[[https://melpa.org/#/dired-rsync][file:https://melpa.org/packages/dired-rsync-badge.svg]]
[[https:/travis-ci.org/stsquad/dired-rsync][file:https://travis-ci.org/stsquad/dired-rsync.svg?branch=master]]
* Introduction
This package adds a single command ~dired-rsync~ which allows the user
......@@ -22,7 +28,15 @@ A variable called ~dired-rsync-modeline-status~ is provided for mode
lines that will report the number of active rsync operations in
progress. However by default that value is also set in
~mode-line-process~ which is a common place for things to report
inferior process status.
inferior process status. The variable ~dired-rsync-job-count~ contains
the number of currently active ~dired-rsync~ jobs currently running.
For those that don't like the way ~dired-rsync~ unmarks transferred
files when it completes please see ~dired-rsync-unmark-on-completion~.
The options ~dired-rsync-command~ and ~dired-rsync-options~ are there
to modify the call to rsync but a user is unlikely to need to tweak
these.
* Technical Notes
......@@ -32,11 +46,17 @@ locally as rsync needs working SSH authentication to work. If you can
access a remote machine via tramp/ssh without having to enter a
password (because ssh-agent is working) then rsync should work fine.
The test used by ~dired-rsync~ is ~tramp-tramp-file-p~ which will mean
any tramp path will attempt to be converted to an rsync path with
optional ssh transport. Obviously if your remote target doesn't also
have ssh running and remote rsync binary this will fail. The reporting
could be improved.
There have been several attempts at doing this but I found them
wanting in usability. This attempts to clean up the ideas from:
https://truongtx.me/tmtxt-dired-async.html
https://oremacs.com/2016/02/24/dired-rsync/
https://vxlabs.com/2018/03/30/asynchronous-rsync-with-emacs-dired-and-tramp/
- https://truongtx.me/tmtxt-dired-async.html
- https://oremacs.com/2016/02/24/dired-rsync/
- https://vxlabs.com/2018/03/30/asynchronous-rsync-with-emacs-dired-and-tramp/
in a hopefully cleaner and more idiomatic way.
;;; dired-rsync.el --- Allow rsync from dired buffers
;;; dired-rsync.el --- Allow rsync from dired buffers -*- lexical-binding: t -*-
;;
;; Copyright (C) 2018 Alex Bennée
;;
......@@ -26,35 +26,46 @@
;;; Commentary:
;;
;; dired-rsync is a command that can be run from a dired buffer to
;; copy files using rsync rather than tramps in-built mechanism. This
;; is especially useful for copying large files to/from remote
;; copy files using rsync rather than tramps in-built mechanism.
;; This is especially useful for copying large files to/from remote
;; locations without locking up tramp.
;;
;; To use simply open a dired buffer, mark some files and invoke
;; dired-rsync. After being prompted for a location to copy to an
;; dired-rsync. After being prompted for a location to copy to an
;; inferior rsync process will be spawned.
;;
;; Wherever the files are selected from the rsync will always run from
;; your local machine.
;;
(eval-when-compile (require 'cl)) ; for lexical-let
(require 'tramp) ; for tramp-tramp-file-p
(require 'dired-aux) ; for dired-dwim-target-directory
(require 'dash)
(require 's)
;;; Code:
(defvar dired-rsync-command
"rsync"
"The rsync binary that we are going to use.")
;; Customisation options
(defvar dired-rsync-options
"-avz --progress"
"The default options for the rsync command.")
(defcustom dired-rsync-command "rsync"
"The rsync binary that we are going to use."
:type 'string
:group 'dired-rsync)
(defvar dired-rsync-jobs
'()
"List of current rsync processes.")
(defcustom dired-rsync-options "-avz --progress"
"The default options for the rsync command."
:type 'string
:group 'dired-rsync)
(defcustom dired-rsync-unmark-on-completion t
"Control if dired-rsync should unmark when complete."
:type 'boolean
:group 'dired-rsync)
;; Internal variables
(defvar dired-rsync-job-count 0
"Count of running rsync jobs.")
(defvar dired-rsync-modeline-status
""
......@@ -62,14 +73,9 @@
;; Helpers
(defun dired-rsync--is-remote-tramp-p (file-or-path)
"Return non-nil if FILE-OR-PATH is remote."
(or (string-prefix-p "/scp:" file-or-path)
(string-prefix-p "/ssh:" file-or-path)))
(defun dired-rsync--quote-and-maybe-convert-from-tramp (file-or-path)
"Reformat a tramp FILE-OR-PATH to one usable for rsync."
(if (dired-rsync--is-remote-tramp-p file-or-path)
(if (tramp-tramp-file-p file-or-path)
;; tramp format is /method:remote:path
(let ((parts (s-split ":" file-or-path)))
(format "%s:\"%s\"" (nth 1 parts) (shell-quote-argument (nth 2 parts))))
......@@ -78,16 +84,11 @@
;; Update status with count/speed
(defun dired-rsync--update-modeline ()
"Update the number of current jobs."
(let ((jobs 0)
(total-bandwidth))
(mapc (lambda(job)
(when (process-live-p (car job))
(setq jobs (1+ jobs)))) dired-rsync-jobs)
(setq mode-line-process
(setq mode-line-process
(setq dired-rsync-modeline-status
(if (> jobs 0)
(format " R:%d " jobs)
nil)))))
(if (> dired-rsync-job-count 0)
(format " R:%d " dired-rsync-job-count)
nil))))
;;
;; Running rsync: We need to take care of a couple of things here. We
......@@ -97,30 +98,33 @@
;; is finished so we can inform the user the copy is complete.
;;
(defun dired-rsync--sentinel(proc desc)
(defun dired-rsync--sentinel(proc desc details)
"Process sentinel for rsync processes.
This gets called whenever the inferior `PROC' changes state as
described by `DESC'."
(let ((details (cdr (assoc proc dired-rsync-jobs))))
(when (s-starts-with-p "finished" desc)
;; clean-up finished tasks
(let ((proc-buf (process-buffer proc))
(dired-buf (plist-get details ':dired-buffer)))
(with-current-buffer dired-buf
(dired-unmark-all-marks))
(kill-buffer proc-buf)))
;; clean-up data left from dead/finished processes
(when (not (process-live-p proc))
(setq dired-rsync-jobs
(assq-delete-all proc dired-rsync-jobs))))
(when (s-starts-with-p "finished" desc)
;; clean-up finished tasks
(let ((proc-buf (process-buffer proc))
(dired-buf (plist-get details ':dired-buffer)))
(when dired-rsync-unmark-on-completion
(with-current-buffer dired-buf
(dired-unmark-all-marks)))
(kill-buffer proc-buf)))
;; clean-up data left from dead/finished processes
(when (not (process-live-p proc))
(setq dired-rsync-job-count (1- dired-rsync-job-count)))
(dired-rsync--update-modeline))
(defun dired-rsync--do-run (command details)
"Run rsync COMMAND in a unique buffer, saving DETAILS in job list."
"Run rsync COMMAND in a unique buffer, passing DETAILS to sentinel."
(let* ((buf (format "*rsync @ %s" (current-time-string)))
(proc (start-process-shell-command "*rsync*" buf command)))
(setq dired-rsync-jobs (add-to-list 'dired-rsync-jobs (cons proc details)))
(set-process-sentinel proc #'dired-rsync--sentinel)
(lexical-let ((job-details details))
(set-process-sentinel
proc
#'(lambda (proc desc)
(dired-rsync--sentinel proc desc job-details))))
(setq dired-rsync-job-count (1+ dired-rsync-job-count))
(dired-rsync--update-modeline)))
;;;###autoload
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment