There are very few examples on the internet involving all three of the functions at issue in this question -- i.e., set-process-sentinel
; set-process-filter
; and start-process
.
I've tried a few different methods of fine-tuning the the processes in an effort to force process number 1 (push
) to finish prior to the commencement of process number 2 (push
). In all of my attempts, the second process always runs and finishes before I have finished entering my password for process number 1. Process number 2 has a password stored in the osxkeychain
.
The first method I tried was with Magit, both synchronous and asynchronous processes. The second method I tried was with using the function while . . .
to search the list of remotes in the buffer containing said list. The third attempt is listed below -- it uses a list of remotes that is created at the outset of the function and then mapcar
s down the list to push
with Git.
Any ideas on how to better control process number 1 (push
) so that it successfully finishes prior the commencement of process number 2 (push
) would be greatly appreciated.
It is not the end of the world that process number 2 starts and finishes too early, but it is a matter of learning how to take control over Emacs processes -- rather than the processes taking control of me.
EDIT (April 23, 2014): Added a doc-string. Revised handling of buffer *REMOTES*
-- i.e., kill-local-variable 'git-remote-list
and erase-buffer
now works correctly by using with-current-buffer ...
(defvar git-remote-list nil
"List of remote locations -- e.g., lawlist_remote or github_remote.")
(make-variable-buffer-local 'git-remote-list)
(defvar git-commit-message (format "Committed -- %s" (current-time-string))
"The predetermined Git commit message.")
(make-variable-buffer-local 'git-commit-message)
(defun my-process-filter (proc string)
(when (string-match "password" string)
(process-send-string
proc
(concat (read-passwd "Password: ") "\n"))))
(defun my-process-sentinel (proc string)
(when (= 0 (process-exit-status proc))
(message "Process `%s` has finished." proc)))
(defun stage-commit-push-all ()
"This function does the following:
* Save the current working buffer if it has been modified.
* Gather a list of all remotes associated with working directory Git project.
* Stage all -- `/usr/local/git/bin/git add .`
* Commit all -- `/usr/local/git/bin/git commit -m [git-commit-message]`
* Push to all remotes: `/usr/local/git/bin/git push -v [remote] [current-branch]`
Obtaining the current branch presently requires installation of Magit."
(interactive)
(when (buffer-modified-p)
(save-buffer))
(when (get-buffer "*REMOTES*")
(with-current-buffer (get-buffer "*REMOTES*")
(kill-local-variable 'git-remote-list)
(erase-buffer)))
(set-process-sentinel
(start-process
"list-remotes"
"*REMOTES*"
"/usr/local/git/bin/git"
"remote"
"-v")
(lambda (p e) (when (= 0 (process-exit-status p))
(let* (
beg
end
git-remote-name)
(with-current-buffer (get-buffer "*REMOTES*")
(goto-char (point-max))
(while (re-search-backward "\(push\)" nil t)
(beginning-of-line 1)
(setq beg (point))
(re-search-forward "\t" nil t)
(setq end (- (point) 1))
(setq git-remote-name (buffer-substring-no-properties beg end))
(setq git-remote-list
(append (cons git-remote-name git-remote-list)))) ))
(set-process-sentinel
(start-process
"stage-all"
"*OUTPUT*"
"/usr/local/git/bin/git"
"add"
".")
(lambda (p e) (when (= 0 (process-exit-status p))
(set-process-sentinel
(start-process
"commit-all"
"*OUTPUT*"
"/usr/local/git/bin/git"
"commit"
"-m"
git-commit-message)
(lambda (p e) (when (= 0 (process-exit-status p))
(mapcar (lambda (x)
(let ((proc
(start-process
"push-process"
"*OUTPUT*"
"/usr/local/git/bin/git"
"push"
"-v"
(format "%s" x)
(magit-get-current-branch))))
(set-process-filter proc 'my-process-filter)
(set-process-sentinel proc 'my-process-sentinel) ))
(with-current-buffer (get-buffer "*REMOTES*") git-remote-list)
)))))))))))
The approach that springs to mind is simply to make each call to start-process
dependent on the sentinel for the previous process.
In essence, generate a queue of things you want to do, trigger the processing of the first queue item, and let each sentinel trigger start the process for the next queue item (if any) once its own process has completed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With