]> code.delx.au - gnu-emacs/blobdiff - lisp/net/tramp-gvfs.el
Add Google Drive support to Tramp
[gnu-emacs] / lisp / net / tramp-gvfs.el
index 0e874d6c5865a1a58dc5ae14873cc6476242638d..8e7ef0f4079aef557af60ff338de9687245ad2c9 100644 (file)
 
 ;; The custom option `tramp-gvfs-methods' contains the list of
 ;; supported connection methods.  Per default, these are "afp", "dav",
-;; "davs", "obex", "sftp" and "synce".  Note that with "obex" it might
-;; be necessary to pair with the other bluetooth device, if it hasn't
-;; been done already.  There might be also some few seconds delay in
-;; discovering available bluetooth devices.
+;; "davs", "gdrive", "obex", "sftp" and "synce".  Note that with
+;; "obex" it might be necessary to pair with the other bluetooth
+;; device, if it hasn't been done already.  There might be also some
+;; few seconds delay in discovering available bluetooth devices.
 
 ;; Other possible connection methods are "ftp" and "smb".  When one of
 ;; these methods is added to the list, the remote access for that
   (require 'custom))
 
 ;;;###tramp-autoload
-(defcustom tramp-gvfs-methods '("afp" "dav" "davs" "obex" "sftp" "synce")
+(defcustom tramp-gvfs-methods
+  '("afp" "dav" "davs" "gdrive" "obex" "sftp" "synce")
   "List of methods for remote files, accessed with GVFS."
   :group 'tramp
-  :version "25.1"
+  :version "25.2"
   :type '(repeat (choice (const "afp")
                         (const "dav")
                         (const "davs")
                         (const "ftp")
+                        (const "gdrive")
                         (const "obex")
                         (const "sftp")
                         (const "smb")
                         (const "synce"))))
 
-;; Add a default for `tramp-default-user-alist'.  Rule: For the SYNCE
-;; method, no user is chosen.
+;; Add defaults for `tramp-default-user-alist' and `tramp-default-host-alist'.
+;;;###tramp-autoload
+(when (string-match "\\(.+\\)@\\(\\(?:gmail\\|googlemail\\)\\.com\\)"
+                   user-mail-address)
+  (add-to-list 'tramp-default-user-alist
+              `("\\`gdrive\\'" nil ,(match-string 1 user-mail-address)))
+  (add-to-list 'tramp-default-host-alist
+              '("\\`gdrive\\'" nil ,(match-string 2 user-mail-address))))
 ;;;###tramp-autoload
 (add-to-list 'tramp-default-user-alist '("\\`synce\\'" nil nil))
 
@@ -408,11 +416,9 @@ Every entry is a list (NAME ADDRESS).")
   "The device interface of the HAL daemon.")
 
 (defconst tramp-gvfs-file-attributes
-  '("type"
+  '("name"
+    "type"
     "standard::display-name"
-    ;; We don't need this one.  It is used as delimiter in case the
-    ;; display name contains spaces, which is hard to parse.
-    "standard::icon"
     "standard::symlink-target"
     "unix::nlink"
     "unix::uid"
@@ -432,9 +438,7 @@ Every entry is a list (NAME ADDRESS).")
   "GVFS file attributes.")
 
 (defconst tramp-gvfs-file-attributes-with-gvfs-ls-regexp
-  (concat "[[:blank:]]"
-         (regexp-opt tramp-gvfs-file-attributes t)
-         "=\\([^[:blank:]]+\\)")
+  (concat "[[:blank:]]" (regexp-opt tramp-gvfs-file-attributes t) "=\\(.+?\\)")
   "Regexp to parse GVFS file attributes with `gvfs-ls'.")
 
 (defconst tramp-gvfs-file-attributes-with-gvfs-info-regexp
@@ -834,25 +838,31 @@ file names."
           v "gvfs-ls" "-h" "-n" "-a"
           (mapconcat 'identity tramp-gvfs-file-attributes ",")
           (tramp-gvfs-url-file-name directory))
-         ;; Parse output ...
+         ;; Parse output.
          (with-current-buffer (tramp-get-connection-buffer v)
            (goto-char (point-min))
-           (while (re-search-forward
+           (while (looking-at
                    (concat "^\\(.+\\)[[:blank:]]"
                            "\\([[:digit:]]+\\)[[:blank:]]"
-                           "(\\(.+\\))[[:blank:]]"
-                           "standard::display-name=\\(.+\\)[[:blank:]]"
-                           "standard::icon=")
-                   (point-at-eol) t)
-             (let ((item (list (cons "standard::display-name" (match-string 4))
-                               (cons "type" (match-string 3))
+                           "(\\(.+?\\))"
+                           tramp-gvfs-file-attributes-with-gvfs-ls-regexp))
+             (let ((item (list (cons "type" (match-string 3))
                                (cons "standard::size" (match-string 2))
-                               (match-string 1))))
-               (while (re-search-forward
-                       tramp-gvfs-file-attributes-with-gvfs-ls-regexp
-                       (point-at-eol) t)
-                 (push (cons (match-string 1) (match-string 2)) item))
-               (push (nreverse item) result))
+                               (cons "name" (match-string 1)))))
+               (goto-char (1+ (match-end 3)))
+               (while (looking-at
+                       (concat
+                        tramp-gvfs-file-attributes-with-gvfs-ls-regexp
+                        "\\(" tramp-gvfs-file-attributes-with-gvfs-ls-regexp
+                        "\\|" "$" "\\)"))
+                 (push (cons (match-string 1) (match-string 2)) item)
+                 (goto-char (match-end 2)))
+               ;; Add display name as head.
+               (push
+                (cons (cdr (or (assoc "standard::display-name" item)
+                               (assoc "name" item)))
+                      (nreverse item))
+                result))
              (forward-line)))
          result)))))
 
@@ -868,7 +878,7 @@ file names."
          ;; Send command.
          (tramp-gvfs-send-command
           v "gvfs-info" (tramp-gvfs-url-file-name filename))
-         ;; Parse output ...
+         ;; Parse output.
          (with-current-buffer (tramp-get-connection-buffer v)
            (goto-char (point-min))
            (while (re-search-forward
@@ -1024,17 +1034,12 @@ file names."
      filename
      (with-parsed-tramp-file-name (expand-file-name directory) nil
        (with-tramp-file-property v localname "file-name-all-completions"
-         (let ((result '("./" "../"))
-              entry)
+         (let ((result '("./" "../")))
            ;; Get a list of directories and files.
           (dolist (item (tramp-gvfs-get-directory-attributes directory) result)
-            (setq entry
-                  (or ;; Use display-name if available (google-drive).
-                   ;(cdr (assoc "standard::display-name" item))
-                   (car item)))
             (if (string-equal (cdr (assoc "type" item)) "directory")
-                (push (file-name-as-directory entry) result)
-              (push entry result)))))))))
+                (push (file-name-as-directory (car item)) result)
+              (push (car item) result)))))))))
 
 (defun tramp-gvfs-handle-file-notify-add-watch (file-name flags _callback)
   "Like `file-notify-add-watch' for Tramp files."
@@ -1220,6 +1225,8 @@ file-notify events."
      (url-recreate-url
       (if (tramp-tramp-file-p filename)
          (with-parsed-tramp-file-name filename nil
+           (when (string-equal "gdrive" method)
+             (setq method "google-drive"))
            (when (and user (string-match tramp-user-with-domain-regexp user))
              (setq user
                    (concat (match-string 2 user) ";" (match-string 1 user))))
@@ -1389,6 +1396,8 @@ ADDRESS can have the form \"xx:xx:xx:xx:xx:xx\" or \"[xx:xx:xx:xx:xx:xx]\"."
          (setq host (tramp-bluez-device host)))
        (when (and (string-equal "dav" method) (string-equal "true" ssl))
          (setq method "davs"))
+       (when (string-equal "google-drive" method)
+         (setq method "gdrive"))
        (unless (zerop (length domain))
          (setq user (concat user tramp-prefix-domain-format domain)))
        (unless (zerop (length port))
@@ -1474,6 +1483,8 @@ ADDRESS can have the form \"xx:xx:xx:xx:xx:xx\" or \"[xx:xx:xx:xx:xx:xx]\"."
           (setq host (tramp-bluez-device host)))
         (when (and (string-equal "dav" method) (string-equal "true" ssl))
           (setq method "davs"))
+        (when (string-equal "google-drive" method)
+          (setq method "gdrive"))
         (when (and (string-equal "synce" method) (zerop (length user)))
           (setq user (or (tramp-file-name-user vec) "")))
         (unless (zerop (length domain))
@@ -1531,6 +1542,9 @@ It was \"a(say)\", but has changed to \"a{sv})\"."
                 (list (tramp-gvfs-mount-spec-entry "type" "afp-volume")
                       (tramp-gvfs-mount-spec-entry "host" host)
                       (tramp-gvfs-mount-spec-entry "volume" share)))
+               ((string-equal "gdrive" method)
+                (list (tramp-gvfs-mount-spec-entry "type" "google-drive")
+                      (tramp-gvfs-mount-spec-entry "host" host)))
                (t
                 (list (tramp-gvfs-mount-spec-entry "type" method)
                       (tramp-gvfs-mount-spec-entry "host" host))))
@@ -1896,8 +1910,9 @@ They are retrieved from the hal daemon."
 
 ;;; TODO:
 
-;; * Host name completion via afp-server, smb-server or smb-network.
-;; * Check how two shares of the same SMB server can be mounted in
+;; * Host name completion for existing mount points (afp-server,
+;;   smb-server) or via smb-network.
+;; * Check, how two shares of the same SMB server can be mounted in
 ;;   parallel.
 ;; * Apply SDP on bluetooth devices, in order to filter out obex
 ;;   capability.