Function: tramp-sh-gio-monitor-process-filter

tramp-sh-gio-monitor-process-filter is a byte-compiled function defined in tramp-sh.el.gz.

Signature

(tramp-sh-gio-monitor-process-filter PROC STRING)

Documentation

Read output from "gio monitor" and add corresponding file-notify events.

Source Code

;; Defined in /usr/src/emacs/lisp/net/tramp-sh.el.gz
(defun tramp-sh-gio-monitor-process-filter (proc string)
  "Read output from \"gio monitor\" and add corresponding `file-notify' events."
  (let ((events (process-get proc 'events))
	(remote-prefix
	 (with-current-buffer (process-buffer proc)
	   (file-remote-p default-directory)))
	(rest-string (process-get proc 'rest-string))
	pos)
    (when rest-string
      (tramp-message proc 10 "Previous string:\n%s" rest-string))
    (tramp-message proc 6 "%S\n%s" proc string)
    (setq string (concat rest-string string)
          ;; Fix action names.
          string (tramp-compat-string-replace
                  "attributes changed" "attribute-changed" string)
          string (tramp-compat-string-replace
                  "changes done" "changes-done-hint" string)
          string (tramp-compat-string-replace
                  "renamed to" "moved" string))

    (catch 'doesnt-work
      ;; https://bugs.launchpad.net/bugs/1742946
      (when
          (string-match-p "Monitoring not supported\\|No locations given" string)
        (delete-process proc)
        (throw 'doesnt-work nil))

      ;; Determine monitor name.
      (unless (tramp-connection-property-p proc "gio-file-monitor")
        (tramp-set-connection-property
         proc "gio-file-monitor"
         (cond
          ;; We have seen this on cygwin gio and on emba.  Let's make
          ;; some assumptions.
          ((string-match
            "Can't find module 'help' specified in GIO_USE_FILE_MONITOR" string)
	   (setq pos (match-end 0))
           (cond
            ((getenv "EMACS_EMBA_CI") 'GInotifyFileMonitor)
            ((eq system-type 'cygwin) 'GPollFileMonitor)
            (t nil)))
          ;; TODO: What happens, if several monitor names are reported?
          ((string-match "\
Supported arguments for GIO_USE_FILE_MONITOR environment variable:
\\s-*\\([[:alpha:]]+\\) - 20" string)
	   (setq pos (match-end 0))
           (intern
	    (format "G%sFileMonitor" (capitalize (match-string 1 string)))))
          (t (setq pos (length string)) nil)))
	(setq string (substring string pos)))

      ;; Delete empty lines.
      (setq string (tramp-compat-string-replace "\n\n" "\n" string))

      (while (string-match
	      (eval-when-compile
                (concat "^[^:]+:"
                        "[[:space:]]\\([^:]+\\):"
                        "[[:space:]]" (regexp-opt tramp-gio-events t)
                        "\\([[:space:]]\\([^:]+\\)\\)?$"))
	      string)

        (let* ((file (match-string 1 string))
	       (file1 (match-string 4 string))
	       (object
                (list
                 proc
                 (list
		  (intern-soft (match-string 2 string)))
                 ;; File names are returned as absolute paths.  We
                 ;; must add the remote prefix.
                 (concat remote-prefix file)
                 (when file1 (concat remote-prefix file1)))))
	  (setq string (replace-match "" nil nil string))
	  ;; Usually, we would add an Emacs event now.  Unfortunately,
	  ;; `unread-command-events' does not accept several events at
	  ;; once.  Therefore, we apply the handler directly.
	  (when (member (cl-caadr object) events)
	    (tramp-compat-funcall
	     (lookup-key special-event-map [file-notify])
	     `(file-notify ,object file-notify-callback))))))

    ;; Save rest of the string.
    (while (string-match "^\n" string)
      (setq string (replace-match "" nil nil string)))
    (when (zerop (length string)) (setq string nil))
    (when string (tramp-message proc 10 "Rest string:\n%s" string))
    (process-put proc 'rest-string string)))