diff options
| author | Kai Großjohann | 2002-06-25 18:15:03 +0000 |
|---|---|---|
| committer | Kai Großjohann | 2002-06-25 18:15:03 +0000 |
| commit | c62c9d08c7aadf65cfc46e7d94ab5d34e48119da (patch) | |
| tree | 5ca2c80db42507fc23beb1b8e5ccde7f23792009 | |
| parent | 04f13f39be4b91818f297b5cca73ba05289ef251 (diff) | |
| download | emacs-c62c9d08c7aadf65cfc46e7d94ab5d34e48119da.tar.gz emacs-c62c9d08c7aadf65cfc46e7d94ab5d34e48119da.zip | |
(tramp-ftp-method): New user option.
(tramp-invoke-ange-ftp): New function to forward calls to
Ange-FTP.
(with-parsed-tramp-file-name): New macro for the usual big `let'
statement to dissect a file-name.
(tramp-handle-make-symbolic-link, tramp-handle-load)
(tramp-handle-file-name-directory)
(tramp-handle-file-name-nondirectory, tramp-handle-file-truename)
(tramp-handle-file-truename, tramp-handle-file-directory-p)
(tramp-handle-file-regular-p, tramp-handle-file-symlink-p)
(tramp-handle-file-writable-p, tramp-handle-file-writable-p):
Use the new macro and forward call to Ange-FTP if applicable.
(tramp-make-ange-ftp-file-name): New helper function to convert a
file name into an Ange-FTP file name, used by
`tramp-invoke-ange-ftp'.
(tramp-default-method-alist): New user option.
(tramp-find-default-method): Use it.
(tramp-sh-extra-args): New variable.
(tramp-find-shell): Use it.
| -rw-r--r-- | lisp/ChangeLog | 28 | ||||
| -rw-r--r-- | lisp/net/tramp.el | 2069 |
2 files changed, 1118 insertions, 979 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 933643649f6..59545cc56dc 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,31 @@ | |||
| 1 | 2002-06-25 Kai Gro,b_(Bjohann <Kai.Grossjohann@CS.Uni-Dortmund.DE> | ||
| 2 | |||
| 3 | * net/tramp.el (tramp-ftp-method): New user option. | ||
| 4 | (tramp-invoke-ange-ftp): New function to forward calls to | ||
| 5 | Ange-FTP. | ||
| 6 | |||
| 7 | (with-parsed-tramp-file-name): New macro for the usual big `let' | ||
| 8 | statement to dissect a file-name. | ||
| 9 | |||
| 10 | (tramp-handle-make-symbolic-link, tramp-handle-load) | ||
| 11 | (tramp-handle-file-name-directory) | ||
| 12 | (tramp-handle-file-name-nondirectory, tramp-handle-file-truename) | ||
| 13 | (tramp-handle-file-truename, tramp-handle-file-directory-p) | ||
| 14 | (tramp-handle-file-regular-p, tramp-handle-file-symlink-p) | ||
| 15 | (tramp-handle-file-writable-p, tramp-handle-file-writable-p): | ||
| 16 | |||
| 17 | Use the new macro and forward call to Ange-FTP if applicable. | ||
| 18 | |||
| 19 | (tramp-make-ange-ftp-file-name): New helper function to convert a | ||
| 20 | file name into an Ange-FTP file name, used by | ||
| 21 | `tramp-invoke-ange-ftp'. | ||
| 22 | |||
| 23 | (tramp-default-method-alist): New user option. | ||
| 24 | (tramp-find-default-method): Use it. | ||
| 25 | |||
| 26 | (tramp-sh-extra-args): New variable. | ||
| 27 | (tramp-find-shell): Use it. | ||
| 28 | |||
| 1 | 2002-06-25 Andreas Schwab <schwab@suse.de> | 29 | 2002-06-25 Andreas Schwab <schwab@suse.de> |
| 2 | 30 | ||
| 3 | * replace.el (occur-1): Avoid invalid message format string. | 31 | * replace.el (occur-1): Avoid invalid message format string. |
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index 585c5d46986..ae487fc81bb 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el | |||
| @@ -52,24 +52,24 @@ | |||
| 52 | ;; the same directory. | 52 | ;; the same directory. |
| 53 | ;; | 53 | ;; |
| 54 | ;; There's a mailing list for this, as well. Its name is: | 54 | ;; There's a mailing list for this, as well. Its name is: |
| 55 | ;; tramp-devel@lists.sourceforge.net | 55 | ;; tramp-devel@mail.freesoftware.fsf.org |
| 56 | ;; Send a mail with `help' in the subject (!) to the administration | 56 | ;; Send a mail with `help' in the subject (!) to the administration |
| 57 | ;; address for instructions on joining the list. The administration | 57 | ;; address for instructions on joining the list. The administration |
| 58 | ;; address is: | 58 | ;; address is: |
| 59 | ;; tramp-devel-request@lists.sourceforge.net | 59 | ;; tramp-devel-request@mail.freesoftware.fsf.org |
| 60 | ;; You can also use the Web to subscribe, under the following URL: | 60 | ;; You can also use the Web to subscribe, under the following URL: |
| 61 | ;; http://lists.sourceforge.net/lists/listinfo/tramp-devel | 61 | ;; http://mail.freesoftware.fsf.org/mailman/listinfo/tramp-devel |
| 62 | ;; | 62 | ;; |
| 63 | ;; For the adventurous, the current development sources are available | 63 | ;; For the adventurous, the current development sources are available |
| 64 | ;; via CVS. You can find instructions about this at the following URL: | 64 | ;; via CVS. You can find instructions about this at the following URL: |
| 65 | ;; http://sourceforge.net/projects/tramp/ | 65 | ;; http://savannah.gnu.org/projects/tramp/ |
| 66 | ;; Click on "CVS" in the navigation bar near the top. | 66 | ;; Click on "CVS" in the navigation bar near the top. |
| 67 | ;; | 67 | ;; |
| 68 | ;; Don't forget to put on your asbestos longjohns, first! | 68 | ;; Don't forget to put on your asbestos longjohns, first! |
| 69 | 69 | ||
| 70 | ;;; Code: | 70 | ;;; Code: |
| 71 | 71 | ||
| 72 | (defconst tramp-version "2.0.0" | 72 | (defconst tramp-version "2.0.1" |
| 73 | "This version of tramp.") | 73 | "This version of tramp.") |
| 74 | (defconst tramp-bug-report-address "tramp-devel@mail.freesoftware.fsf.org" | 74 | (defconst tramp-bug-report-address "tramp-devel@mail.freesoftware.fsf.org" |
| 75 | "Email address to send bug reports to.") | 75 | "Email address to send bug reports to.") |
| @@ -776,7 +776,30 @@ various functions for details." | |||
| 776 | 776 | ||
| 777 | (defcustom tramp-default-method "rcp" | 777 | (defcustom tramp-default-method "rcp" |
| 778 | "*Default method to use for transferring files. | 778 | "*Default method to use for transferring files. |
| 779 | See `tramp-methods' for possibilities." | 779 | See `tramp-methods' for possibilities. |
| 780 | Also see `tramp-default-method-alist'." | ||
| 781 | :group 'tramp | ||
| 782 | :type 'string) | ||
| 783 | |||
| 784 | (defcustom tramp-default-method-alist nil | ||
| 785 | "*Default method to use for specific user/host pairs. | ||
| 786 | This is an alist of items (HOST USER METHOD). The first matching item | ||
| 787 | specifies the method to use for a file name which does not specify a | ||
| 788 | method. HOST and USER are regular expressions or nil, which is | ||
| 789 | interpreted as a regular expression which always matches. If no entry | ||
| 790 | matches, the variable `tramp-default-method' takes effect. | ||
| 791 | |||
| 792 | If the file name does not specify the user, lookup is done using the | ||
| 793 | empty string for the user name. | ||
| 794 | |||
| 795 | See `tramp-methods' for a list of possibilities for METHOD." | ||
| 796 | :group 'tramp | ||
| 797 | :type '(repeat (list (regexp :tag "Host regexp") | ||
| 798 | (regexp :tag "User regexp") | ||
| 799 | (string :tag "Method")))) | ||
| 800 | |||
| 801 | (defcustom tramp-ftp-method "ftp" | ||
| 802 | "*When this method name is used, forward all calls to Ange-FTP." | ||
| 780 | :group 'tramp | 803 | :group 'tramp |
| 781 | :type 'string) | 804 | :type 'string) |
| 782 | 805 | ||
| @@ -840,6 +863,18 @@ Some shells send such garbage upon connection setup." | |||
| 840 | :group 'tramp | 863 | :group 'tramp |
| 841 | :type 'boolean) | 864 | :type 'boolean) |
| 842 | 865 | ||
| 866 | (defcustom tramp-sh-extra-args '(("/bash\\'" . "--norc")) | ||
| 867 | "*Alist specifying extra arguments to pass to the remote shell. | ||
| 868 | Entries are (REGEXP . ARGS) where REGEXP is a regular expression | ||
| 869 | matching the shell file name and ARGS is a string specifying the | ||
| 870 | arguments. | ||
| 871 | |||
| 872 | This variable is only used when Tramp needs to start up another shell | ||
| 873 | for tilde expansion. The extra arguments should typically prevent the | ||
| 874 | shell from reading its init file." | ||
| 875 | :group 'tramp | ||
| 876 | :type '(alist :key-type string :value-type string)) | ||
| 877 | |||
| 843 | ;; File name format. | 878 | ;; File name format. |
| 844 | 879 | ||
| 845 | (defcustom tramp-file-name-structure | 880 | (defcustom tramp-file-name-structure |
| @@ -1313,6 +1348,37 @@ own implementation." | |||
| 1313 | ((fboundp 'point-at-eol) (funcall 'point-at-eol)) | 1348 | ((fboundp 'point-at-eol) (funcall 'point-at-eol)) |
| 1314 | (t (save-excursion (end-of-line) (point))))) | 1349 | (t (save-excursion (end-of-line) (point))))) |
| 1315 | 1350 | ||
| 1351 | (defmacro with-parsed-tramp-file-name (filename var &rest body) | ||
| 1352 | "Parse a Tramp filename and make components available in the body. | ||
| 1353 | |||
| 1354 | First arg FILENAME is evaluated and dissected into its components. | ||
| 1355 | Second arg VAR is a symbol. It is used as a variable name to hold | ||
| 1356 | the filename structure. It is also used as a prefix for the variables | ||
| 1357 | holding the components. For example, if VAR is the symbol `foo', then | ||
| 1358 | `foo' will be bound to the whole structure, `foo-multi-method' will | ||
| 1359 | be bound to the multi-method component, and so on for `foo-method', | ||
| 1360 | `foo-user', `foo-host', `foo-path'. | ||
| 1361 | |||
| 1362 | Remaining args are Lisp expressions to be evaluated (inside an implicit | ||
| 1363 | `progn'). | ||
| 1364 | |||
| 1365 | If VAR is nil, then we bind `v' to the structure and `multi-method', | ||
| 1366 | `method', `user', `host', `path' to the components." | ||
| 1367 | `(let* ((,(or var 'v) (tramp-dissect-file-name ,filename)) | ||
| 1368 | (,(if var (intern (concat (symbol-name var) "-multi-method")) 'multi-method) | ||
| 1369 | (tramp-file-name-multi-method ,(or var 'v))) | ||
| 1370 | (,(if var (intern (concat (symbol-name var) "-method")) 'method) | ||
| 1371 | (tramp-file-name-method ,(or var 'v))) | ||
| 1372 | (,(if var (intern (concat (symbol-name var) "-user")) 'user) | ||
| 1373 | (tramp-file-name-user ,(or var 'v))) | ||
| 1374 | (,(if var (intern (concat (symbol-name var) "-host")) 'host) | ||
| 1375 | (tramp-file-name-host ,(or var 'v))) | ||
| 1376 | (,(if var (intern (concat (symbol-name var) "-path")) 'path) | ||
| 1377 | (tramp-file-name-path ,(or var 'v)))) | ||
| 1378 | ,@body)) | ||
| 1379 | |||
| 1380 | (put 'with-parsed-tramp-file-name 'lisp-indent-function 2) | ||
| 1381 | |||
| 1316 | ;;; File Name Handler Functions: | 1382 | ;;; File Name Handler Functions: |
| 1317 | 1383 | ||
| 1318 | ;; The following file name handler ops are not implemented (yet?). | 1384 | ;; The following file name handler ops are not implemented (yet?). |
| @@ -1320,104 +1386,87 @@ own implementation." | |||
| 1320 | (defun tramp-handle-make-symbolic-link | 1386 | (defun tramp-handle-make-symbolic-link |
| 1321 | (filename linkname &optional ok-if-already-exists) | 1387 | (filename linkname &optional ok-if-already-exists) |
| 1322 | "Like `make-symbolic-link' for tramp files. | 1388 | "Like `make-symbolic-link' for tramp files. |
| 1323 | This function will raise an error if FILENAME and LINKNAME are not | 1389 | The LINKNAME argument should look like \"/path/to/target\" or |
| 1324 | on the same remote host." | 1390 | \"relative-name\",and not like a Tramp filename." |
| 1325 | (unless (or (tramp-tramp-file-p filename) | 1391 | (error "Not implemented yet") |
| 1326 | (tramp-tramp-file-p linkname)) | 1392 | (with-parsed-tramp-file-name linkname l |
| 1327 | (tramp-run-real-handler 'make-symbolic-link | 1393 | (when (tramp-ange-ftp-file-name-p l-multi-method l-method) |
| 1328 | (list filename linkname ok-if-already-exists))) | 1394 | (tramp-invoke-ange-ftp 'make-symbolic-link |
| 1329 | (let* ((file (tramp-dissect-file-name filename)) | 1395 | filename linkname ok-if-already-exists)) |
| 1330 | (link (tramp-dissect-file-name linkname)) | 1396 | (let ((ln (tramp-get-remote-ln l-multi l-method l-user l-host)) |
| 1331 | (multi (tramp-file-name-multi-method file)) | 1397 | (cwd (file-name-directory l-path))) |
| 1332 | (method (tramp-file-name-method file)) | 1398 | (unless ln |
| 1333 | (user (tramp-file-name-user file)) | 1399 | (signal 'file-error |
| 1334 | (host (tramp-file-name-host file)) | 1400 | (list "Making a symbolic link." |
| 1335 | (l-multi (tramp-file-name-multi-method link)) | 1401 | "ln(1) does not exist on the remote host."))) |
| 1336 | (l-meth (tramp-file-name-method link)) | 1402 | |
| 1337 | (l-user (tramp-file-name-user link)) | 1403 | ;; Do the 'confirm if exists' thing. |
| 1338 | (l-host (tramp-file-name-host link)) | 1404 | (when (file-exists-p (expand-file-name filename |
| 1339 | (ln (tramp-get-remote-ln multi method user host)) | 1405 | CCC)) |
| 1340 | (cwd (file-name-directory (tramp-file-name-path file)))) | 1406 | ;; What to do? |
| 1341 | (unless ln | 1407 | (if (or (null ok-if-already-exists) ; not allowed to exist |
| 1342 | (signal 'file-error (list "Making a symbolic link." | 1408 | (and (numberp ok-if-already-exists) |
| 1343 | "ln(1) does not exist on the remote host."))) | 1409 | (not (yes-or-no-p |
| 1344 | 1410 | (format | |
| 1345 | ;; Check that method, user, host are the same. | 1411 | "File %s already exists; make it a link anyway? " |
| 1346 | (unless (equal host l-host) | 1412 | l-path))))) |
| 1347 | (signal 'file-error (list "Can't make symlink across hosts" host l-host))) | 1413 | (signal 'file-already-exists (list "File already exists" l-path)))) |
| 1348 | (unless (equal user l-user) | ||
| 1349 | (signal 'file-error (list "Can't make symlink for different users" | ||
| 1350 | user l-user))) | ||
| 1351 | (unless (and (equal multi l-multi) | ||
| 1352 | (equal method l-meth)) | ||
| 1353 | (signal 'file-error (list "Method must be the same for making symlinks" | ||
| 1354 | multi l-multi method l-meth))) | ||
| 1355 | |||
| 1356 | ;; Do the 'confirm if exists' thing. | ||
| 1357 | (when (file-exists-p (tramp-file-name-path link)) | ||
| 1358 | ;; What to do? | ||
| 1359 | (if (or (null ok-if-already-exists) ; not allowed to exist | ||
| 1360 | (and (numberp ok-if-already-exists) | ||
| 1361 | (not (yes-or-no-p | ||
| 1362 | (format "File %s already exists; make it a link anyway? " | ||
| 1363 | (tramp-file-name-path link)))))) | ||
| 1364 | (signal 'file-already-exists (list "File already exists" | ||
| 1365 | (tramp-file-name-path link))))) | ||
| 1366 | 1414 | ||
| 1367 | ;; Right, they are on the same host, regardless of user, method, etc. | 1415 | ;; Right, they are on the same host, regardless of user, method, etc. |
| 1368 | ;; We now make the link on the remote machine. This will occur as the user | 1416 | ;; We now make the link on the remote machine. This will occur as the user |
| 1369 | ;; that FILENAME belongs to. | 1417 | ;; that FILENAME belongs to. |
| 1370 | (zerop | 1418 | (zerop |
| 1371 | (tramp-send-command-and-check | 1419 | (tramp-send-command-and-check |
| 1372 | multi method user host | 1420 | fn-multi fn-method fn-user fn-host |
| 1373 | (format "cd %s && %s -sf %s %s" | 1421 | (format "cd %s && %s -sf %s %s" |
| 1374 | cwd ln | 1422 | cwd ln |
| 1375 | (tramp-file-name-path file) ; target | 1423 | (tramp-file-name-path file) ; target |
| 1376 | (tramp-file-name-path link)) ; link name | 1424 | (tramp-file-name-path link)) ; link name |
| 1377 | t)))) | 1425 | t))))) |
| 1378 | 1426 | ||
| 1379 | 1427 | ||
| 1380 | (defun tramp-handle-load (file &optional noerror nomessage nosuffix must-suffix) | 1428 | (defun tramp-handle-load (file &optional noerror nomessage nosuffix must-suffix) |
| 1381 | "Like `load' for tramp files. Not implemented!" | 1429 | "Like `load' for tramp files. Not implemented!" |
| 1382 | (unless (file-name-absolute-p file) | 1430 | (unless (file-name-absolute-p file) |
| 1383 | (error "Tramp cannot `load' files without absolute path name")) | 1431 | (error "Tramp cannot `load' files without absolute path name")) |
| 1384 | (unless nosuffix | 1432 | (with-parsed-tramp-file-name file nil |
| 1385 | (cond ((file-exists-p (concat file ".elc")) | 1433 | (when (tramp-ange-ftp-file-name-p multi-method method) |
| 1386 | (setq file (concat file ".elc"))) | 1434 | (tramp-invoke-ange-ftp 'load |
| 1387 | ((file-exists-p (concat file ".el")) | 1435 | file noerror nomessage nosuffix must-suffix)) |
| 1388 | (setq file (concat file ".el"))))) | 1436 | (unless nosuffix |
| 1389 | (when must-suffix | 1437 | (cond ((file-exists-p (concat file ".elc")) |
| 1390 | ;; The first condition is always true for absolute file names. | 1438 | (setq file (concat file ".elc"))) |
| 1391 | ;; Included for safety's sake. | 1439 | ((file-exists-p (concat file ".el")) |
| 1392 | (unless (or (file-name-directory file) | 1440 | (setq file (concat file ".el"))))) |
| 1393 | (string-match "\\.elc?\\'" file)) | 1441 | (when must-suffix |
| 1394 | (error "File `%s' does not include a `.el' or `.elc' suffix" | 1442 | ;; The first condition is always true for absolute file names. |
| 1395 | file))) | 1443 | ;; Included for safety's sake. |
| 1396 | (unless noerror | 1444 | (unless (or (file-name-directory file) |
| 1397 | (when (not (file-exists-p file)) | 1445 | (string-match "\\.elc?\\'" file)) |
| 1398 | (error "Cannot load nonexistant file `%s'" file))) | 1446 | (error "File `%s' does not include a `.el' or `.elc' suffix" |
| 1399 | (if (not (file-exists-p file)) | 1447 | file))) |
| 1400 | nil | 1448 | (unless noerror |
| 1401 | (unless nomessage | 1449 | (when (not (file-exists-p file)) |
| 1402 | (message "Loading %s..." file)) | 1450 | (error "Cannot load nonexistant file `%s'" file))) |
| 1403 | (let ((local-copy (file-local-copy file))) | 1451 | (if (not (file-exists-p file)) |
| 1404 | ;; MUST-SUFFIX doesn't exist on XEmacs, so let it default to nil. | 1452 | nil |
| 1405 | (load local-copy noerror t t) | 1453 | (unless nomessage |
| 1406 | (delete-file local-copy)) | 1454 | (message "Loading %s..." file)) |
| 1407 | (unless nomessage | 1455 | (let ((local-copy (file-local-copy file))) |
| 1408 | (message "Loading %s...done" file)) | 1456 | ;; MUST-SUFFIX doesn't exist on XEmacs, so let it default to nil. |
| 1409 | t)) | 1457 | (load local-copy noerror t t) |
| 1458 | (delete-file local-copy)) | ||
| 1459 | (unless nomessage | ||
| 1460 | (message "Loading %s...done" file)) | ||
| 1461 | t))) | ||
| 1410 | 1462 | ||
| 1411 | ;; Path manipulation functions that grok TRAMP paths... | 1463 | ;; Path manipulation functions that grok TRAMP paths... |
| 1412 | (defun tramp-handle-file-name-directory (file) | 1464 | (defun tramp-handle-file-name-directory (file) |
| 1413 | "Like `file-name-directory' but aware of TRAMP files." | 1465 | "Like `file-name-directory' but aware of TRAMP files." |
| 1414 | ;; everything except the last filename thing is the directory | 1466 | ;; everything except the last filename thing is the directory |
| 1415 | (let* ((v (tramp-dissect-file-name file)) | 1467 | (with-parsed-tramp-file-name file nil |
| 1416 | (multi-method (tramp-file-name-multi-method v)) | 1468 | (when (tramp-ange-ftp-file-name-p multi-method method) |
| 1417 | (method (tramp-file-name-method v)) | 1469 | (tramp-invoke-ange-ftp 'file-name-directory file)) |
| 1418 | (user (tramp-file-name-user v)) | ||
| 1419 | (host (tramp-file-name-host v)) | ||
| 1420 | (path (tramp-file-name-path v))) | ||
| 1421 | (if (or (string= path "") (string= path "/")) | 1470 | (if (or (string= path "") (string= path "/")) |
| 1422 | ;; For a filename like "/[foo]", we return "/". The `else' | 1471 | ;; For a filename like "/[foo]", we return "/". The `else' |
| 1423 | ;; case would return "/[foo]" unchanged. But if we do that, | 1472 | ;; case would return "/[foo]" unchanged. But if we do that, |
| @@ -1434,98 +1483,95 @@ on the same remote host." | |||
| 1434 | 1483 | ||
| 1435 | (defun tramp-handle-file-name-nondirectory (file) | 1484 | (defun tramp-handle-file-name-nondirectory (file) |
| 1436 | "Like `file-name-nondirectory' but aware of TRAMP files." | 1485 | "Like `file-name-nondirectory' but aware of TRAMP files." |
| 1437 | (let ((v (tramp-dissect-file-name file))) | 1486 | (with-parsed-tramp-file-name file nil |
| 1438 | (file-name-nondirectory (tramp-file-name-path v)))) | 1487 | (when (tramp-ange-ftp-file-name-p multi-method method) |
| 1488 | (tramp-invoke-ange-ftp 'file-name-nondirectory file)) | ||
| 1489 | (file-name-nondirectory path))) | ||
| 1439 | 1490 | ||
| 1440 | (defun tramp-handle-file-truename (filename &optional counter prev-dirs) | 1491 | (defun tramp-handle-file-truename (filename &optional counter prev-dirs) |
| 1441 | "Like `file-truename' for tramp files." | 1492 | "Like `file-truename' for tramp files." |
| 1442 | (let* ((v (tramp-dissect-file-name (tramp-handle-expand-file-name filename))) | 1493 | (with-parsed-tramp-file-name filename nil |
| 1443 | (multi-method (tramp-file-name-multi-method v)) | 1494 | ;; Ange-FTP does not support truename processing. It returns the |
| 1444 | (method (tramp-file-name-method v)) | 1495 | ;; file name as-is. So that's what we do, too. |
| 1445 | (user (tramp-file-name-user v)) | 1496 | (when (tramp-ange-ftp-file-name-p multi-method method) |
| 1446 | (host (tramp-file-name-host v)) | 1497 | filename) |
| 1447 | (path (tramp-file-name-path v)) | 1498 | (let* ((steps (tramp-split-string path "/")) |
| 1448 | (steps (tramp-split-string path "/")) | 1499 | (pathdir (let ((directory-sep-char ?/)) |
| 1449 | (pathdir (let ((directory-sep-char ?/)) | 1500 | (file-name-as-directory path))) |
| 1450 | (file-name-as-directory path))) | 1501 | (is-dir (string= path pathdir)) |
| 1451 | (is-dir (string= path pathdir)) | 1502 | (thisstep nil) |
| 1452 | (thisstep nil) | 1503 | (numchase 0) |
| 1453 | (numchase 0) | 1504 | ;; Don't make the following value larger than necessary. |
| 1454 | ;; Don't make the following value larger than necessary. | 1505 | ;; People expect an error message in a timely fashion when |
| 1455 | ;; People expect an error message in a timely fashion when | 1506 | ;; something is wrong; otherwise they might think that Emacs |
| 1456 | ;; something is wrong; otherwise they might think that Emacs | 1507 | ;; is hung. Of course, correctness has to come first. |
| 1457 | ;; is hung. Of course, correctness has to come first. | 1508 | (numchase-limit 20) |
| 1458 | (numchase-limit 20) | 1509 | (result nil) ;result steps in reverse order |
| 1459 | (result nil) ;result steps in reverse order | 1510 | (curstri "") |
| 1460 | (curstri "") | 1511 | symlink-target) |
| 1461 | symlink-target) | ||
| 1462 | (tramp-message-for-buffer | ||
| 1463 | multi-method method user host | ||
| 1464 | 10 "Finding true name for `%s'" filename) | ||
| 1465 | (while (and steps (< numchase numchase-limit)) | ||
| 1466 | (setq thisstep (pop steps)) | ||
| 1467 | (tramp-message-for-buffer | 1512 | (tramp-message-for-buffer |
| 1468 | multi-method method user host | 1513 | multi-method method user host |
| 1469 | 10 "Check %s" | 1514 | 10 "Finding true name for `%s'" filename) |
| 1470 | (mapconcat 'identity | 1515 | (while (and steps (< numchase numchase-limit)) |
| 1471 | (append '("") (reverse result) (list thisstep)) | 1516 | (setq thisstep (pop steps)) |
| 1472 | "/")) | 1517 | (tramp-message-for-buffer |
| 1473 | (setq symlink-target | 1518 | multi-method method user host |
| 1474 | (nth 0 (tramp-handle-file-attributes | 1519 | 10 "Check %s" |
| 1475 | (tramp-make-tramp-file-name | 1520 | (mapconcat 'identity |
| 1476 | multi-method method user host | 1521 | (append '("") (reverse result) (list thisstep)) |
| 1477 | (mapconcat 'identity | 1522 | "/")) |
| 1478 | (append '("") (reverse result) (list thisstep)) | 1523 | (setq symlink-target |
| 1479 | "/"))))) | 1524 | (nth 0 (tramp-handle-file-attributes |
| 1480 | (cond ((string= "." thisstep) | 1525 | (tramp-make-tramp-file-name |
| 1481 | (tramp-message-for-buffer multi-method method user host | 1526 | multi-method method user host |
| 1482 | 10 "Ignoring step `.'")) | 1527 | (mapconcat 'identity |
| 1483 | ((string= ".." thisstep) | 1528 | (append '("") (reverse result) (list thisstep)) |
| 1484 | (tramp-message-for-buffer multi-method method user host | 1529 | "/"))))) |
| 1485 | 10 "Processing step `..'") | 1530 | (cond ((string= "." thisstep) |
| 1486 | (pop result)) | 1531 | (tramp-message-for-buffer multi-method method user host |
| 1487 | ((stringp symlink-target) | 1532 | 10 "Ignoring step `.'")) |
| 1488 | ;; It's a symlink, follow it. | 1533 | ((string= ".." thisstep) |
| 1489 | (tramp-message-for-buffer | 1534 | (tramp-message-for-buffer multi-method method user host |
| 1490 | multi-method method user host | 1535 | 10 "Processing step `..'") |
| 1491 | 10 "Follow symlink to %s" symlink-target) | 1536 | (pop result)) |
| 1492 | (setq numchase (1+ numchase)) | 1537 | ((stringp symlink-target) |
| 1493 | (when (file-name-absolute-p symlink-target) | 1538 | ;; It's a symlink, follow it. |
| 1494 | (setq result nil)) | 1539 | (tramp-message-for-buffer |
| 1495 | (setq steps | 1540 | multi-method method user host |
| 1496 | (append (tramp-split-string symlink-target "/") steps))) | 1541 | 10 "Follow symlink to %s" symlink-target) |
| 1497 | (t | 1542 | (setq numchase (1+ numchase)) |
| 1498 | ;; It's a file. | 1543 | (when (file-name-absolute-p symlink-target) |
| 1499 | (setq result (cons thisstep result))))) | 1544 | (setq result nil)) |
| 1500 | (when (>= numchase numchase-limit) | 1545 | (setq steps |
| 1501 | (error "Maximum number (%d) of symlinks exceeded" numchase-limit)) | 1546 | (append (tramp-split-string symlink-target "/") steps))) |
| 1502 | (setq result (reverse result)) | 1547 | (t |
| 1503 | (tramp-message-for-buffer | 1548 | ;; It's a file. |
| 1504 | multi-method method user host | 1549 | (setq result (cons thisstep result))))) |
| 1505 | 10 "True name of `%s' is `%s'" | 1550 | (when (>= numchase numchase-limit) |
| 1506 | filename (mapconcat 'identity (cons "" result) "/")) | 1551 | (error "Maximum number (%d) of symlinks exceeded" numchase-limit)) |
| 1507 | (tramp-make-tramp-file-name | 1552 | (setq result (reverse result)) |
| 1508 | multi-method method user host | 1553 | (tramp-message-for-buffer |
| 1509 | (concat (mapconcat 'identity (cons "" result) "/") | 1554 | multi-method method user host |
| 1510 | (if is-dir "/" ""))))) | 1555 | 10 "True name of `%s' is `%s'" |
| 1556 | filename (mapconcat 'identity (cons "" result) "/")) | ||
| 1557 | (tramp-make-tramp-file-name | ||
| 1558 | multi-method method user host | ||
| 1559 | (concat (mapconcat 'identity (cons "" result) "/") | ||
| 1560 | (if is-dir "/" "")))))) | ||
| 1511 | 1561 | ||
| 1512 | ;; Basic functions. | 1562 | ;; Basic functions. |
| 1513 | 1563 | ||
| 1514 | (defun tramp-handle-file-exists-p (filename) | 1564 | (defun tramp-handle-file-exists-p (filename) |
| 1515 | "Like `file-exists-p' for tramp files." | 1565 | "Like `file-exists-p' for tramp files." |
| 1516 | (let ((v (tramp-dissect-file-name (tramp-handle-expand-file-name filename))) | 1566 | (with-parsed-tramp-file-name filename nil |
| 1517 | multi-method method user host path) | 1567 | (when (tramp-ange-ftp-file-name-p multi-method method) |
| 1518 | (setq multi-method (tramp-file-name-multi-method v)) | 1568 | (tramp-invoke-ange-ftp 'file-exists-p filename)) |
| 1519 | (setq method (tramp-file-name-method v)) | ||
| 1520 | (setq user (tramp-file-name-user v)) | ||
| 1521 | (setq host (tramp-file-name-host v)) | ||
| 1522 | (setq path (tramp-file-name-path v)) | ||
| 1523 | (save-excursion | 1569 | (save-excursion |
| 1524 | (zerop (tramp-send-command-and-check | 1570 | (zerop (tramp-send-command-and-check |
| 1525 | multi-method method user host | 1571 | multi-method method user host |
| 1526 | (format | 1572 | (format |
| 1527 | (tramp-get-file-exists-command multi-method method user host) | 1573 | (tramp-get-file-exists-command multi-method method user host) |
| 1528 | (tramp-shell-quote-argument path))))))) | 1574 | (tramp-shell-quote-argument path))))))) |
| 1529 | 1575 | ||
| 1530 | ;; CCC: This should check for an error condition and signal failure | 1576 | ;; CCC: This should check for an error condition and signal failure |
| 1531 | ;; when something goes wrong. | 1577 | ;; when something goes wrong. |
| @@ -1537,15 +1583,14 @@ rather than as numbers." | |||
| 1537 | (if (tramp-handle-file-exists-p filename) | 1583 | (if (tramp-handle-file-exists-p filename) |
| 1538 | ;; file exists, find out stuff | 1584 | ;; file exists, find out stuff |
| 1539 | (save-excursion | 1585 | (save-excursion |
| 1540 | (let* ((v (tramp-dissect-file-name (tramp-handle-expand-file-name filename))) | 1586 | (with-parsed-tramp-file-name filename nil |
| 1541 | (multi-method (tramp-file-name-multi-method v)) | 1587 | (when (tramp-ange-ftp-file-name-p multi-method method) |
| 1542 | (method (tramp-file-name-method v)) | 1588 | (tramp-invoke-ange-ftp 'file-attributes file)) |
| 1543 | (user (tramp-file-name-user v)) | ||
| 1544 | (host (tramp-file-name-host v)) | ||
| 1545 | (path (tramp-file-name-path v))) | ||
| 1546 | (if (tramp-get-remote-perl multi-method method user host) | 1589 | (if (tramp-get-remote-perl multi-method method user host) |
| 1547 | (tramp-handle-file-attributes-with-perl multi-method method user host path nonnumeric) | 1590 | (tramp-handle-file-attributes-with-perl |
| 1548 | (tramp-handle-file-attributes-with-ls multi-method method user host path nonnumeric)))) | 1591 | multi-method method user host path nonnumeric) |
| 1592 | (tramp-handle-file-attributes-with-ls | ||
| 1593 | multi-method method user host path nonnumeric)))) | ||
| 1549 | nil)) ; no file | 1594 | nil)) ; no file |
| 1550 | 1595 | ||
| 1551 | 1596 | ||
| @@ -1653,56 +1698,22 @@ is initially created and is kept cached by the remote shell." | |||
| 1653 | (buffer-name))) | 1698 | (buffer-name))) |
| 1654 | (when time-list | 1699 | (when time-list |
| 1655 | (tramp-run-real-handler 'set-visited-file-modtime (list time-list))) | 1700 | (tramp-run-real-handler 'set-visited-file-modtime (list time-list))) |
| 1656 | (let* ((coding-system-used nil) | 1701 | (let ((f (buffer-file-name)) |
| 1657 | (f (buffer-file-name)) | 1702 | (coding-system-used nil)) |
| 1658 | (v (tramp-dissect-file-name f)) | 1703 | (with-parsed-tramp-file-name f nil |
| 1659 | (multi-method (tramp-file-name-multi-method v)) | 1704 | ;; This operation is not handled by Ange-FTP! |
| 1660 | (method (tramp-file-name-method v)) | 1705 | (when (tramp-ange-ftp-file-name-p multi-method method) |
| 1661 | (user (tramp-file-name-user v)) | 1706 | (throw 'tramp-forward-to-ange-ftp |
| 1662 | (host (tramp-file-name-host v)) | 1707 | (tramp-run-real-handler 'set-visited-file-modtime |
| 1663 | (path (tramp-file-name-path v)) | 1708 | (list time-list)))) |
| 1664 | (attr (file-attributes f)) | 1709 | (let* ((attr (file-attributes f)) |
| 1665 | (modtime (nth 5 attr))) | 1710 | (modtime (nth 5 attr))) |
| 1666 | ;; We use '(0 0) as a don't-know value. See also | 1711 | ;; We use '(0 0) as a don't-know value. See also |
| 1667 | ;; `tramp-handle-file-attributes-with-ls'. | 1712 | ;; `tramp-handle-file-attributes-with-ls'. |
| 1668 | (when (boundp 'last-coding-system-used) | 1713 | (when (boundp 'last-coding-system-used) |
| 1669 | (setq coding-system-used last-coding-system-used)) | 1714 | (setq coding-system-used last-coding-system-used)) |
| 1670 | (if (not (equal modtime '(0 0))) | ||
| 1671 | (tramp-run-real-handler 'set-visited-file-modtime (list modtime)) | ||
| 1672 | (save-excursion | ||
| 1673 | (tramp-send-command | ||
| 1674 | multi-method method user host | ||
| 1675 | (format "%s -ild %s" | ||
| 1676 | (tramp-get-ls-command multi-method method user host) | ||
| 1677 | (tramp-shell-quote-argument path))) | ||
| 1678 | (tramp-wait-for-output) | ||
| 1679 | (setq attr (buffer-substring (point) | ||
| 1680 | (progn (end-of-line) (point))))) | ||
| 1681 | (setq tramp-buffer-file-attributes attr)) | ||
| 1682 | (when (boundp 'last-coding-system-used) | ||
| 1683 | (setq last-coding-system-used coding-system-used)) | ||
| 1684 | nil)) | ||
| 1685 | |||
| 1686 | ;; This function makes the same assumption as | ||
| 1687 | ;; `tramp-handle-set-visited-file-modtime'. | ||
| 1688 | (defun tramp-handle-verify-visited-file-modtime (buf) | ||
| 1689 | "Like `verify-visited-file-modtime' for tramp files." | ||
| 1690 | (with-current-buffer buf | ||
| 1691 | (let* ((f (buffer-file-name)) | ||
| 1692 | (v (tramp-dissect-file-name f)) | ||
| 1693 | (multi-method (tramp-file-name-multi-method v)) | ||
| 1694 | (method (tramp-file-name-method v)) | ||
| 1695 | (user (tramp-file-name-user v)) | ||
| 1696 | (host (tramp-file-name-host v)) | ||
| 1697 | (path (tramp-file-name-path v)) | ||
| 1698 | (attr (file-attributes f)) | ||
| 1699 | (modtime (nth 5 attr))) | ||
| 1700 | (if attr | ||
| 1701 | (if (not (equal modtime '(0 0))) | 1715 | (if (not (equal modtime '(0 0))) |
| 1702 | ;; Why does `file-attributes' return a list (HIGH LOW), but | 1716 | (tramp-run-real-handler 'set-visited-file-modtime (list modtime)) |
| 1703 | ;; `visited-file-modtime' returns a cons (HIGH . LOW)? | ||
| 1704 | (let ((mt (visited-file-modtime))) | ||
| 1705 | (< (abs (tramp-time-diff modtime (list (car mt) (cdr mt)))) 2)) | ||
| 1706 | (save-excursion | 1717 | (save-excursion |
| 1707 | (tramp-send-command | 1718 | (tramp-send-command |
| 1708 | multi-method method user host | 1719 | multi-method method user host |
| @@ -1712,10 +1723,50 @@ is initially created and is kept cached by the remote shell." | |||
| 1712 | (tramp-wait-for-output) | 1723 | (tramp-wait-for-output) |
| 1713 | (setq attr (buffer-substring (point) | 1724 | (setq attr (buffer-substring (point) |
| 1714 | (progn (end-of-line) (point))))) | 1725 | (progn (end-of-line) (point))))) |
| 1715 | (equal tramp-buffer-file-attributes attr)) | 1726 | (setq tramp-buffer-file-attributes attr)) |
| 1716 | ;; If file does not exist, say it is not modified. | 1727 | (when (boundp 'last-coding-system-used) |
| 1728 | (setq last-coding-system-used coding-system-used)) | ||
| 1717 | nil)))) | 1729 | nil)))) |
| 1718 | 1730 | ||
| 1731 | ;; CCC continue here | ||
| 1732 | |||
| 1733 | ;; This function makes the same assumption as | ||
| 1734 | ;; `tramp-handle-set-visited-file-modtime'. | ||
| 1735 | (defun tramp-handle-verify-visited-file-modtime (buf) | ||
| 1736 | "Like `verify-visited-file-modtime' for tramp files." | ||
| 1737 | (with-current-buffer buf | ||
| 1738 | (let ((f (buffer-file-name))) | ||
| 1739 | (with-parsed-tramp-file-name f nil | ||
| 1740 | (when (tramp-ange-ftp-file-name-p f) | ||
| 1741 | ;; This one requires a hack since the file name is not passed | ||
| 1742 | ;; on the arg list. | ||
| 1743 | (let ((buffer-file-name (tramp-make-ange-ftp-file-name | ||
| 1744 | user host path))) | ||
| 1745 | (tramp-invoke-ange-ftp 'verify-visited-file-modtime buf))) | ||
| 1746 | (let* ((attr (file-attributes f)) | ||
| 1747 | (modtime (nth 5 attr))) | ||
| 1748 | (cond ((and attr (not (equal modtime '(0 0)))) | ||
| 1749 | ;; Why does `file-attributes' return a list (HIGH | ||
| 1750 | ;; LOW), but `visited-file-modtime' returns a cons | ||
| 1751 | ;; (HIGH . LOW)? | ||
| 1752 | (let ((mt (visited-file-modtime))) | ||
| 1753 | (< (abs (tramp-time-diff | ||
| 1754 | modtime (list (car mt) (cdr mt)))) 2))) | ||
| 1755 | (attr | ||
| 1756 | (save-excursion | ||
| 1757 | (tramp-send-command | ||
| 1758 | multi-method method user host | ||
| 1759 | (format "%s -ild %s" | ||
| 1760 | (tramp-get-ls-command multi-method method | ||
| 1761 | user host) | ||
| 1762 | (tramp-shell-quote-argument path))) | ||
| 1763 | (tramp-wait-for-output) | ||
| 1764 | (setq attr (buffer-substring | ||
| 1765 | (point) (progn (end-of-line) (point))))) | ||
| 1766 | (equal tramp-buffer-file-attributes attr)) | ||
| 1767 | ;; If file does not exist, say it is not modified. | ||
| 1768 | nil)))))) | ||
| 1769 | |||
| 1719 | (defadvice clear-visited-file-modtime (after tramp activate) | 1770 | (defadvice clear-visited-file-modtime (after tramp activate) |
| 1720 | "Set `tramp-buffer-file-attributes' back to nil. | 1771 | "Set `tramp-buffer-file-attributes' back to nil. |
| 1721 | Tramp uses this variable as an emulation for the actual modtime of the file, | 1772 | Tramp uses this variable as an emulation for the actual modtime of the file, |
| @@ -1724,17 +1775,15 @@ if the remote host can't provide the modtime." | |||
| 1724 | 1775 | ||
| 1725 | (defun tramp-handle-set-file-modes (filename mode) | 1776 | (defun tramp-handle-set-file-modes (filename mode) |
| 1726 | "Like `set-file-modes' for tramp files." | 1777 | "Like `set-file-modes' for tramp files." |
| 1727 | (let ((v (tramp-dissect-file-name filename))) | 1778 | (with-parsed-tramp-file-name filename nil |
| 1779 | (when (tramp-ange-ftp-file-name-p multi-method method) | ||
| 1780 | (tramp-invoke-ange-ftp 'set-file-modes filename mode)) | ||
| 1728 | (save-excursion | 1781 | (save-excursion |
| 1729 | (unless (zerop (tramp-send-command-and-check | 1782 | (unless (zerop (tramp-send-command-and-check |
| 1730 | (tramp-file-name-multi-method v) | 1783 | multi-method method user host |
| 1731 | (tramp-file-name-method v) | 1784 | (format "chmod %s %s" |
| 1732 | (tramp-file-name-user v) | 1785 | (tramp-decimal-to-octal mode) |
| 1733 | (tramp-file-name-host v) | 1786 | (tramp-shell-quote-argument path)))) |
| 1734 | (format "chmod %s %s" | ||
| 1735 | (tramp-decimal-to-octal mode) | ||
| 1736 | (tramp-shell-quote-argument | ||
| 1737 | (tramp-file-name-path v))))) | ||
| 1738 | (signal 'file-error | 1787 | (signal 'file-error |
| 1739 | (list "Doing chmod" | 1788 | (list "Doing chmod" |
| 1740 | ;; FIXME: extract the proper text from chmod's stderr. | 1789 | ;; FIXME: extract the proper text from chmod's stderr. |
| @@ -1745,17 +1794,26 @@ if the remote host can't provide the modtime." | |||
| 1745 | 1794 | ||
| 1746 | (defun tramp-handle-file-executable-p (filename) | 1795 | (defun tramp-handle-file-executable-p (filename) |
| 1747 | "Like `file-executable-p' for tramp files." | 1796 | "Like `file-executable-p' for tramp files." |
| 1748 | (zerop (tramp-run-test "-x" filename))) | 1797 | (with-parsed-tramp-file-name filename nil |
| 1798 | (when (tramp-ange-ftp-file-name-p multi-method method) | ||
| 1799 | (tramp-invoke-ange-ftp 'file-executable-p filename)) | ||
| 1800 | (zerop (tramp-run-test "-x" filename)))) | ||
| 1749 | 1801 | ||
| 1750 | (defun tramp-handle-file-readable-p (filename) | 1802 | (defun tramp-handle-file-readable-p (filename) |
| 1751 | "Like `file-readable-p' for tramp files." | 1803 | "Like `file-readable-p' for tramp files." |
| 1752 | (zerop (tramp-run-test "-r" filename))) | 1804 | (with-parsed-tramp-file-name filename nil |
| 1805 | (when (tramp-ange-ftp-file-name-p multi-method method) | ||
| 1806 | (tramp-invoke-ange-ftp 'file-readable-p filename)) | ||
| 1807 | (zerop (tramp-run-test "-r" filename)))) | ||
| 1753 | 1808 | ||
| 1754 | (defun tramp-handle-file-accessible-directory-p (filename) | 1809 | (defun tramp-handle-file-accessible-directory-p (filename) |
| 1755 | "Like `file-accessible-directory-p' for tramp files." | 1810 | "Like `file-accessible-directory-p' for tramp files." |
| 1756 | (and (zerop (tramp-run-test "-d" filename)) | 1811 | (with-parsed-tramp-file-name filename nil |
| 1757 | (zerop (tramp-run-test "-r" filename)) | 1812 | (when (tramp-ange-ftp-file-name-p multi-method method) |
| 1758 | (zerop (tramp-run-test "-x" filename)))) | 1813 | (tramp-invoke-ange-ftp 'file-accessible-directory-p filename)) |
| 1814 | (and (zerop (tramp-run-test "-d" filename)) | ||
| 1815 | (zerop (tramp-run-test "-r" filename)) | ||
| 1816 | (zerop (tramp-run-test "-x" filename))))) | ||
| 1759 | 1817 | ||
| 1760 | ;; When the remote shell is started, it looks for a shell which groks | 1818 | ;; When the remote shell is started, it looks for a shell which groks |
| 1761 | ;; tilde expansion. Here, we assume that all shells which grok tilde | 1819 | ;; tilde expansion. Here, we assume that all shells which grok tilde |
| @@ -1768,42 +1826,44 @@ if the remote host can't provide the modtime." | |||
| 1768 | nil) | 1826 | nil) |
| 1769 | ((not (file-exists-p file2)) | 1827 | ((not (file-exists-p file2)) |
| 1770 | t) | 1828 | t) |
| 1771 | ;; We are sure both files exist at this point. | 1829 | ;; We are sure both files exist at this point. We assume that |
| 1830 | ;; both files are Tramp files, otherwise we issue an error | ||
| 1831 | ;; message. Todo: make a better error message. | ||
| 1772 | (t | 1832 | (t |
| 1773 | (save-excursion | 1833 | (save-excursion |
| 1774 | (let* ((v1 (tramp-dissect-file-name file1)) | 1834 | (with-parsed-tramp-file-name file1 v1 |
| 1775 | (mm1 (tramp-file-name-multi-method v1)) | 1835 | (with-parsed-tramp-file-name file2 v2 |
| 1776 | (m1 (tramp-file-name-method v1)) | 1836 | (when (and (tramp-ange-ftp-file-name-p v1-multi-method v1-method) |
| 1777 | (u1 (tramp-file-name-user v1)) | 1837 | (tramp-ange-ftp-file-name-p v2-multi-method v2-method)) |
| 1778 | (h1 (tramp-file-name-host v1)) | 1838 | (tramp-invoke-ange-ftp 'file-newer-than-file-p |
| 1779 | (v2 (tramp-dissect-file-name file2)) | 1839 | file1 file2)) |
| 1780 | (mm2 (tramp-file-name-multi-method v2)) | 1840 | (unless (and (equal v1-multi-method v2-multi-method) |
| 1781 | (m2 (tramp-file-name-method v2)) | 1841 | (equal v1-method v2-method) |
| 1782 | (u2 (tramp-file-name-user v2)) | 1842 | (equal v1-user v2-user) |
| 1783 | (h2 (tramp-file-name-host v2))) | 1843 | (equal v1-host v2-host)) |
| 1784 | (unless (and (equal mm1 mm2) | 1844 | (signal 'file-error |
| 1785 | (equal m1 m2) | 1845 | (list "Files must have same method, user, host" |
| 1786 | (equal u1 u2) | 1846 | file1 file2))) |
| 1787 | (equal h1 h2)) | 1847 | (unless (and (tramp-tramp-file-p file1) |
| 1788 | (signal 'file-error | 1848 | (tramp-tramp-file-p file2)) |
| 1789 | (list "Files must have same method, user, host" | 1849 | (signal 'file-error |
| 1790 | file1 file2))) | 1850 | (list "Files must be tramp files on same host" |
| 1791 | (unless (and (tramp-tramp-file-p file1) | 1851 | file1 file2))) |
| 1792 | (tramp-tramp-file-p file2)) | 1852 | (if (tramp-get-test-groks-nt |
| 1793 | (signal 'file-error | 1853 | v1-multi-method v1-method v1-user v1-host) |
| 1794 | (list "Files must be tramp files on same host" | 1854 | (zerop (tramp-run-test2 "test" file1 file2 "-nt")) |
| 1795 | file1 file2))) | 1855 | (zerop (tramp-run-test2 "tramp_test_nt" file1 file2))))))))) |
| 1796 | (if (tramp-get-test-groks-nt mm1 m1 u1 h1) | ||
| 1797 | (zerop (tramp-run-test2 "test" file1 file2 "-nt")) | ||
| 1798 | (zerop (tramp-run-test2 "tramp_test_nt" file1 file2)))))))) | ||
| 1799 | 1856 | ||
| 1800 | ;; Functions implemented using the basic functions above. | 1857 | ;; Functions implemented using the basic functions above. |
| 1801 | 1858 | ||
| 1802 | (defun tramp-handle-file-modes (filename) | 1859 | (defun tramp-handle-file-modes (filename) |
| 1803 | "Like `file-modes' for tramp files." | 1860 | "Like `file-modes' for tramp files." |
| 1804 | (when (file-exists-p filename) | 1861 | (with-parsed-tramp-file-name filename nil |
| 1805 | (tramp-mode-string-to-int | 1862 | (when (tramp-ange-ftp-file-name-p multi-method method) |
| 1806 | (nth 8 (tramp-handle-file-attributes filename))))) | 1863 | (tramp-invoke-ange-ftp 'file-modes filename)) |
| 1864 | (when (file-exists-p filename) | ||
| 1865 | (tramp-mode-string-to-int | ||
| 1866 | (nth 8 (tramp-handle-file-attributes filename)))))) | ||
| 1807 | 1867 | ||
| 1808 | (defun tramp-handle-file-directory-p (filename) | 1868 | (defun tramp-handle-file-directory-p (filename) |
| 1809 | "Like `file-directory-p' for tramp files." | 1869 | "Like `file-directory-p' for tramp files." |
| @@ -1815,40 +1875,55 @@ if the remote host can't provide the modtime." | |||
| 1815 | ;; we? | 1875 | ;; we? |
| 1816 | ;; | 1876 | ;; |
| 1817 | ;; Alternatives: `cd %s', `test -d %s' | 1877 | ;; Alternatives: `cd %s', `test -d %s' |
| 1818 | (save-excursion | 1878 | (with-parsed-tramp-file-name filename nil |
| 1819 | (let ((v (tramp-dissect-file-name filename))) | 1879 | (when (tramp-ange-ftp-file-name-p multi-method method) |
| 1880 | (tramp-invoke-ange-ftp 'file-directory-p filename)) | ||
| 1881 | (save-excursion | ||
| 1820 | (zerop | 1882 | (zerop |
| 1821 | (tramp-send-command-and-check | 1883 | (tramp-send-command-and-check |
| 1822 | (tramp-file-name-multi-method v) (tramp-file-name-method v) | 1884 | multi-method method user host |
| 1823 | (tramp-file-name-user v) (tramp-file-name-host v) | 1885 | (format "test -d %s" |
| 1824 | (format "test -d %s" | 1886 | (tramp-shell-quote-argument path)) |
| 1825 | (tramp-shell-quote-argument (tramp-file-name-path v))) | 1887 | t))))) ;run command in subshell |
| 1826 | t))))) ;run command in subshell | ||
| 1827 | 1888 | ||
| 1828 | (defun tramp-handle-file-regular-p (filename) | 1889 | (defun tramp-handle-file-regular-p (filename) |
| 1829 | "Like `file-regular-p' for tramp files." | 1890 | "Like `file-regular-p' for tramp files." |
| 1830 | (and (tramp-handle-file-exists-p filename) | 1891 | (with-parsed-tramp-file-name filename nil |
| 1831 | (eq ?- (aref (nth 8 (tramp-handle-file-attributes filename)) 0)))) | 1892 | (when (tramp-ange-ftp-file-name-p multi-method method) |
| 1893 | (tramp-invoke-ange-ftp 'file-regular-p filename)) | ||
| 1894 | (and (tramp-handle-file-exists-p filename) | ||
| 1895 | (eq ?- (aref (nth 8 (tramp-handle-file-attributes filename)) 0))))) | ||
| 1832 | 1896 | ||
| 1833 | (defun tramp-handle-file-symlink-p (filename) | 1897 | (defun tramp-handle-file-symlink-p (filename) |
| 1834 | "Like `file-symlink-p' for tramp files." | 1898 | "Like `file-symlink-p' for tramp files." |
| 1835 | (let ((x (car (tramp-handle-file-attributes filename)))) | 1899 | (with-parsed-tramp-file-name filename nil |
| 1836 | (when (stringp x) x))) | 1900 | (when (tramp-ange-ftp-file-name-p multi-method method) |
| 1901 | (tramp-invoke-ange-ftp 'file-symlink-p filename)) | ||
| 1902 | (let ((x (car (tramp-handle-file-attributes filename)))) | ||
| 1903 | (when (stringp x) x)))) | ||
| 1837 | 1904 | ||
| 1838 | (defun tramp-handle-file-writable-p (filename) | 1905 | (defun tramp-handle-file-writable-p (filename) |
| 1839 | "Like `file-writable-p' for tramp files." | 1906 | "Like `file-writable-p' for tramp files." |
| 1840 | (if (tramp-handle-file-exists-p filename) | 1907 | (with-parsed-tramp-file-name filename nil |
| 1841 | ;; Existing files must be writable. | 1908 | (when (tramp-ange-ftp-file-name-p multi-method method) |
| 1842 | (zerop (tramp-run-test "-w" filename)) | 1909 | (tramp-invoke-ange-ftp 'file-writable-p filename)) |
| 1843 | ;; If file doesn't exist, check if directory is writable. | 1910 | (if (tramp-handle-file-exists-p filename) |
| 1844 | (and (zerop (tramp-run-test "-d" (tramp-handle-file-name-directory filename))) | 1911 | ;; Existing files must be writable. |
| 1845 | (zerop (tramp-run-test "-w" (tramp-handle-file-name-directory filename)))))) | 1912 | (zerop (tramp-run-test "-w" filename)) |
| 1913 | ;; If file doesn't exist, check if directory is writable. | ||
| 1914 | (and (zerop (tramp-run-test | ||
| 1915 | "-d" (tramp-handle-file-name-directory filename))) | ||
| 1916 | (zerop (tramp-run-test | ||
| 1917 | "-w" (tramp-handle-file-name-directory filename))))))) | ||
| 1846 | 1918 | ||
| 1847 | (defun tramp-handle-file-ownership-preserved-p (filename) | 1919 | (defun tramp-handle-file-ownership-preserved-p (filename) |
| 1848 | "Like `file-ownership-preserved-p' for tramp files." | 1920 | "Like `file-ownership-preserved-p' for tramp files." |
| 1849 | (or (not (tramp-handle-file-exists-p filename)) | 1921 | (with-parsed-tramp-file-name filename nil |
| 1850 | ;; Existing files must be writable. | 1922 | (when (tramp-ange-ftp-file-name-p multi-method method) |
| 1851 | (zerop (tramp-run-test "-O" filename)))) | 1923 | (tramp-invoke-ange-ftp 'file-ownership-preserved-p filename)) |
| 1924 | (or (not (tramp-handle-file-exists-p filename)) | ||
| 1925 | ;; Existing files must be writable. | ||
| 1926 | (zerop (tramp-run-test "-O" filename))))) | ||
| 1852 | 1927 | ||
| 1853 | ;; Other file name ops. | 1928 | ;; Other file name ops. |
| 1854 | 1929 | ||
| @@ -1863,102 +1938,103 @@ if the remote host can't provide the modtime." | |||
| 1863 | ;; Philippe Troin <phil@fifi.org> | 1938 | ;; Philippe Troin <phil@fifi.org> |
| 1864 | (defun tramp-handle-directory-file-name (directory) | 1939 | (defun tramp-handle-directory-file-name (directory) |
| 1865 | "Like `directory-file-name' for tramp files." | 1940 | "Like `directory-file-name' for tramp files." |
| 1866 | (let ((directory-length-1 (1- (length directory)))) | 1941 | (with-parsed-tramp-file-name directory nil |
| 1867 | (save-match-data | 1942 | (when (tramp-ange-ftp-file-name-p multi-method method) |
| 1868 | (if (and (eq (aref directory directory-length-1) ?/) | 1943 | (tramp-invoke-ange-ftp 'directory-file-name directory)) |
| 1869 | (eq (string-match tramp-file-name-regexp directory) 0) | 1944 | (let ((directory-length-1 (1- (length directory)))) |
| 1870 | (/= (match-end 0) directory-length-1)) | 1945 | (save-match-data |
| 1871 | (substring directory 0 directory-length-1) | 1946 | (if (and (eq (aref directory directory-length-1) ?/) |
| 1872 | directory)))) | 1947 | (eq (string-match tramp-file-name-regexp directory) 0) |
| 1948 | (/= (match-end 0) directory-length-1)) | ||
| 1949 | (substring directory 0 directory-length-1) | ||
| 1950 | directory))))) | ||
| 1873 | 1951 | ||
| 1874 | ;; Directory listings. | 1952 | ;; Directory listings. |
| 1875 | 1953 | ||
| 1876 | (defun tramp-handle-directory-files (directory &optional full match nosort) | 1954 | (defun tramp-handle-directory-files (directory &optional full match nosort) |
| 1877 | "Like `directory-files' for tramp files." | 1955 | "Like `directory-files' for tramp files." |
| 1878 | (let ((v (tramp-dissect-file-name (tramp-handle-expand-file-name directory))) | 1956 | (with-parsed-tramp-file-name directory nil |
| 1879 | multi-method method user host path result x) | 1957 | (when (tramp-ange-ftp-file-name-p multi-method method) |
| 1880 | (setq multi-method (tramp-file-name-multi-method v)) | 1958 | (tramp-invoke-ange-ftp 'directory-files |
| 1881 | (setq method (tramp-file-name-method v)) | 1959 | directory full match nosort)) |
| 1882 | (setq user (tramp-file-name-user v)) | 1960 | (let (result x) |
| 1883 | (setq host (tramp-file-name-host v)) | ||
| 1884 | (setq path (tramp-file-name-path v)) | ||
| 1885 | (save-excursion | ||
| 1886 | (tramp-barf-unless-okay multi-method method user host | ||
| 1887 | (concat "cd " (tramp-shell-quote-argument path)) | ||
| 1888 | nil | ||
| 1889 | 'file-error | ||
| 1890 | "tramp-handle-directory-files: couldn't `cd %s'" | ||
| 1891 | (tramp-shell-quote-argument path)) | ||
| 1892 | (tramp-send-command | ||
| 1893 | multi-method method user host | ||
| 1894 | (concat (tramp-get-ls-command multi-method method user host) | ||
| 1895 | " -a | cat")) | ||
| 1896 | (tramp-wait-for-output) | ||
| 1897 | (goto-char (point-max)) | ||
| 1898 | (while (zerop (forward-line -1)) | ||
| 1899 | (setq x (buffer-substring (point) | ||
| 1900 | (tramp-line-end-position))) | ||
| 1901 | (when (or (not match) (string-match match x)) | ||
| 1902 | (if full | ||
| 1903 | (push (concat (file-name-as-directory directory) | ||
| 1904 | x) | ||
| 1905 | result) | ||
| 1906 | (push x result)))) | ||
| 1907 | (tramp-send-command multi-method method user host "cd") | ||
| 1908 | (tramp-wait-for-output)) | ||
| 1909 | result)) | ||
| 1910 | |||
| 1911 | ;; This function should return "foo/" for directories and "bar" for | ||
| 1912 | ;; files. We use `ls -ad' to get a list of files (including | ||
| 1913 | ;; directories), and `find . -type d \! -name . -prune' to get a list | ||
| 1914 | ;; of directories. | ||
| 1915 | (defun tramp-handle-file-name-all-completions (filename directory) | ||
| 1916 | "Like `file-name-all-completions' for tramp files." | ||
| 1917 | (unless (save-match-data (string-match "/" filename)) | ||
| 1918 | (let* ((v (tramp-dissect-file-name directory)) | ||
| 1919 | (multi-method (tramp-file-name-multi-method v)) | ||
| 1920 | (method (tramp-file-name-method v)) | ||
| 1921 | (user (tramp-file-name-user v)) | ||
| 1922 | (host (tramp-file-name-host v)) | ||
| 1923 | (path (tramp-file-name-path v)) | ||
| 1924 | (nowild tramp-completion-without-shell-p) | ||
| 1925 | result) | ||
| 1926 | (save-excursion | 1961 | (save-excursion |
| 1927 | (tramp-barf-unless-okay | 1962 | (tramp-barf-unless-okay |
| 1928 | multi-method method user host | 1963 | multi-method method user host |
| 1929 | (format "cd %s" (tramp-shell-quote-argument path)) | 1964 | (concat "cd " (tramp-shell-quote-argument path)) |
| 1930 | nil 'file-error | 1965 | nil |
| 1931 | "tramp-handle-file-name-all-completions: Couldn't `cd %s'" | 1966 | 'file-error |
| 1967 | "tramp-handle-directory-files: couldn't `cd %s'" | ||
| 1932 | (tramp-shell-quote-argument path)) | 1968 | (tramp-shell-quote-argument path)) |
| 1933 | |||
| 1934 | ;; Get a list of directories and files, including reliably | ||
| 1935 | ;; tagging the directories with a trailing '/'. Because I | ||
| 1936 | ;; rock. --daniel@danann.net | ||
| 1937 | (tramp-send-command | 1969 | (tramp-send-command |
| 1938 | multi-method method user host | 1970 | multi-method method user host |
| 1939 | (format (concat "%s -a %s 2>/dev/null | while read f; do " | 1971 | (concat (tramp-get-ls-command multi-method method user host) |
| 1940 | "if test -d \"$f\" 2>/dev/null; " | 1972 | " -a | cat")) |
| 1941 | "then echo \"$f/\"; else echo \"$f\"; fi; done") | ||
| 1942 | (tramp-get-ls-command multi-method method user host) | ||
| 1943 | (if (or nowild (zerop (length filename))) | ||
| 1944 | "" | ||
| 1945 | (format "-d %s*" (tramp-shell-quote-argument filename))))) | ||
| 1946 | |||
| 1947 | ;; Now grab the output. | ||
| 1948 | (tramp-wait-for-output) | 1973 | (tramp-wait-for-output) |
| 1949 | (goto-char (point-max)) | 1974 | (goto-char (point-max)) |
| 1950 | (while (zerop (forward-line -1)) | 1975 | (while (zerop (forward-line -1)) |
| 1951 | (push (buffer-substring (point) | 1976 | (setq x (buffer-substring (point) |
| 1952 | (tramp-line-end-position)) | 1977 | (tramp-line-end-position))) |
| 1953 | result)) | 1978 | (when (or (not match) (string-match match x)) |
| 1954 | 1979 | (if full | |
| 1980 | (push (concat (file-name-as-directory directory) | ||
| 1981 | x) | ||
| 1982 | result) | ||
| 1983 | (push x result)))) | ||
| 1955 | (tramp-send-command multi-method method user host "cd") | 1984 | (tramp-send-command multi-method method user host "cd") |
| 1956 | (tramp-wait-for-output) | 1985 | (tramp-wait-for-output)) |
| 1986 | result))) | ||
| 1987 | |||
| 1988 | ;; This function should return "foo/" for directories and "bar" for | ||
| 1989 | ;; files. We use `ls -ad' to get a list of files (including | ||
| 1990 | ;; directories), and `find . -type d \! -name . -prune' to get a list | ||
| 1991 | ;; of directories. | ||
| 1992 | (defun tramp-handle-file-name-all-completions (filename directory) | ||
| 1993 | "Like `file-name-all-completions' for tramp files." | ||
| 1994 | (with-parsed-tramp-file-name directory nil | ||
| 1995 | (when (tramp-ange-ftp-file-name-p multi-method method) | ||
| 1996 | (tramp-invoke-ange-ftp 'file-name-all-completions | ||
| 1997 | filename directory)) | ||
| 1998 | (unless (save-match-data (string-match "/" filename)) | ||
| 1999 | (let* ((nowild tramp-completion-without-shell-p) | ||
| 2000 | result) | ||
| 2001 | (save-excursion | ||
| 2002 | (tramp-barf-unless-okay | ||
| 2003 | multi-method method user host | ||
| 2004 | (format "cd %s" (tramp-shell-quote-argument path)) | ||
| 2005 | nil 'file-error | ||
| 2006 | "tramp-handle-file-name-all-completions: Couldn't `cd %s'" | ||
| 2007 | (tramp-shell-quote-argument path)) | ||
| 2008 | |||
| 2009 | ;; Get a list of directories and files, including reliably | ||
| 2010 | ;; tagging the directories with a trailing '/'. Because I | ||
| 2011 | ;; rock. --daniel@danann.net | ||
| 2012 | (tramp-send-command | ||
| 2013 | multi-method method user host | ||
| 2014 | (format (concat "%s -a %s 2>/dev/null | while read f; do " | ||
| 2015 | "if test -d \"$f\" 2>/dev/null; " | ||
| 2016 | "then echo \"$f/\"; else echo \"$f\"; fi; done") | ||
| 2017 | (tramp-get-ls-command multi-method method user host) | ||
| 2018 | (if (or nowild (zerop (length filename))) | ||
| 2019 | "" | ||
| 2020 | (format "-d %s*" | ||
| 2021 | (tramp-shell-quote-argument filename))))) | ||
| 2022 | |||
| 2023 | ;; Now grab the output. | ||
| 2024 | (tramp-wait-for-output) | ||
| 2025 | (goto-char (point-max)) | ||
| 2026 | (while (zerop (forward-line -1)) | ||
| 2027 | (push (buffer-substring (point) | ||
| 2028 | (tramp-line-end-position)) | ||
| 2029 | result)) | ||
| 2030 | |||
| 2031 | (tramp-send-command multi-method method user host "cd") | ||
| 2032 | (tramp-wait-for-output) | ||
| 1957 | 2033 | ||
| 1958 | ;; Return the list. | 2034 | ;; Return the list. |
| 1959 | (if nowild | 2035 | (if nowild |
| 1960 | (all-completions filename (mapcar 'list result)) | 2036 | (all-completions filename (mapcar 'list result)) |
| 1961 | result))))) | 2037 | result)))))) |
| 1962 | 2038 | ||
| 1963 | 2039 | ||
| 1964 | ;; The following isn't needed for Emacs 20 but for 19.34? | 2040 | ;; The following isn't needed for Emacs 20 but for 19.34? |
| @@ -1968,54 +2044,56 @@ if the remote host can't provide the modtime." | |||
| 1968 | (error | 2044 | (error |
| 1969 | "tramp-handle-file-name-completion invoked on non-tramp directory `%s'" | 2045 | "tramp-handle-file-name-completion invoked on non-tramp directory `%s'" |
| 1970 | directory)) | 2046 | directory)) |
| 1971 | ;(setq directory (tramp-handle-expand-file-name directory)) | 2047 | (with-parsed-tramp-file-name directory nil |
| 1972 | (try-completion | 2048 | (when (tramp-ange-ftp-file-name-p multi-method method) |
| 1973 | filename | 2049 | (tramp-invoke-ange-ftp 'file-name-completion |
| 1974 | (mapcar (lambda (x) (cons x nil)) | 2050 | filename directory)) |
| 1975 | (tramp-handle-file-name-all-completions filename directory)))) | 2051 | (try-completion |
| 2052 | filename | ||
| 2053 | (mapcar (lambda (x) (cons x nil)) | ||
| 2054 | (tramp-handle-file-name-all-completions filename directory))))) | ||
| 1976 | 2055 | ||
| 1977 | ;; cp, mv and ln | 2056 | ;; cp, mv and ln |
| 1978 | 2057 | ||
| 1979 | (defun tramp-handle-add-name-to-file | 2058 | (defun tramp-handle-add-name-to-file |
| 1980 | (filename newname &optional ok-if-already-exists) | 2059 | (filename newname &optional ok-if-already-exists) |
| 1981 | "Like `add-name-to-file' for tramp files." | 2060 | "Like `add-name-to-file' for tramp files." |
| 1982 | (let* ((v1 (when (tramp-tramp-file-p filename) | 2061 | (with-parsed-tramp-file-name filename v1 |
| 1983 | (tramp-dissect-file-name (tramp-handle-expand-file-name filename)))) | 2062 | (with-parsed-tramp-file-name newname v2 |
| 1984 | (v2 (when (tramp-tramp-file-p newname) | 2063 | (let ((ln (when v1 (tramp-get-remote-ln |
| 1985 | (tramp-dissect-file-name (tramp-handle-expand-file-name newname)))) | 2064 | v1-multi-method v1-method v1-user v1-host)))) |
| 1986 | (mmeth1 (when v1 (tramp-file-name-multi-method v1))) | 2065 | (unless (and v1-method v2-method v1-user v2-user v1-host v2-host |
| 1987 | (mmeth2 (when v2 (tramp-file-name-multi-method v2))) | 2066 | (equal v1-multi-method v2-multi-method) |
| 1988 | (meth1 (when v1 (tramp-file-name-method v1))) | 2067 | (equal v1-method v2-method) |
| 1989 | (meth2 (when v2 (tramp-file-name-method v2))) | 2068 | (equal v1-user v2-user) |
| 1990 | (user1 (when v1 (tramp-file-name-user v1))) | 2069 | (equal v1-host v2-host)) |
| 1991 | (user2 (when v2 (tramp-file-name-user v2))) | 2070 | (error "add-name-to-file: %s" |
| 1992 | (host1 (when v1 (tramp-file-name-host v1))) | 2071 | "only implemented for same method, same user, same host")) |
| 1993 | (host2 (when v2 (tramp-file-name-host v2))) | 2072 | (when (and (tramp-ange-ftp-file-name-p v1-multi-method v1-method) |
| 1994 | (path1 (when v1 (tramp-file-name-path v1))) | 2073 | (tramp-ange-ftp-file-name-p v2-multi-method v2-method)) |
| 1995 | (path2 (when v2 (tramp-file-name-path v2))) | 2074 | (tramp-invoke-ange-ftp 'add-name-to-file |
| 1996 | (ln (when v1 (tramp-get-remote-ln mmeth1 meth1 user1 host1)))) | 2075 | filename newname ok-if-already-exists)) |
| 1997 | (unless (and meth1 meth2 user1 user2 host1 host2 | 2076 | (when (tramp-ange-ftp-file-name-p v1-multi-method v1-method) |
| 1998 | (equal mmeth1 mmeth2) | 2077 | (tramp-invoke-ange-ftp 'add-name-to-file |
| 1999 | (equal meth1 meth2) | 2078 | filename newname ok-if-already-exists)) |
| 2000 | (equal user1 user2) | 2079 | (when (tramp-ange-ftp-file-name-p v2-multi-method v2-method) |
| 2001 | (equal host1 host2)) | 2080 | (tramp-invoke-ange-ftp 'add-name-to-file |
| 2002 | (error "add-name-to-file: %s" | 2081 | filename newname ok-if-already-exists)) |
| 2003 | "only implemented for same method, same user, same host")) | 2082 | (when (and (not ok-if-already-exists) |
| 2004 | (when (and (not ok-if-already-exists) | 2083 | (file-exists-p newname) |
| 2005 | (file-exists-p newname) | 2084 | (not (numberp ok-if-already-exists)) |
| 2006 | (not (numberp ok-if-already-exists)) | 2085 | (y-or-n-p |
| 2007 | (y-or-n-p | 2086 | (format |
| 2008 | (format | 2087 | "File %s already exists; make it a new name anyway? " |
| 2009 | "File %s already exists; make it a new name anyway? " | 2088 | newname))) |
| 2010 | newname))) | 2089 | (error "add-name-to-file: file %s already exists" newname)) |
| 2011 | (error "add-name-to-file: file %s already exists" newname)) | 2090 | (tramp-barf-unless-okay |
| 2012 | (tramp-barf-unless-okay | 2091 | v1-multi-method v1-method v1-user v1-host |
| 2013 | mmeth1 meth1 user1 host1 | 2092 | (format "%s %s %s" ln (tramp-shell-quote-argument v1-path) |
| 2014 | (format "%s %s %s" ln (tramp-shell-quote-argument path1) | 2093 | (tramp-shell-quote-argument v2-path)) |
| 2015 | (tramp-shell-quote-argument path2)) | 2094 | nil 'file-error |
| 2016 | nil 'file-error | 2095 | "error with add-name-to-file, see buffer `%s' for details" |
| 2017 | "error with add-name-to-file, see buffer `%s' for details" | 2096 | (buffer-name)))))) |
| 2018 | (buffer-name)))) | ||
| 2019 | 2097 | ||
| 2020 | (defun tramp-handle-copy-file | 2098 | (defun tramp-handle-copy-file |
| 2021 | (filename newname &optional ok-if-already-exists keep-date) | 2099 | (filename newname &optional ok-if-already-exists keep-date) |
| @@ -2067,84 +2145,80 @@ and `rename'. FILENAME and NEWNAME must be absolute file names." | |||
| 2067 | (when (file-exists-p newname) | 2145 | (when (file-exists-p newname) |
| 2068 | (signal 'file-already-exists | 2146 | (signal 'file-already-exists |
| 2069 | (list newname)))) | 2147 | (list newname)))) |
| 2070 | (let* ((v1 (when (tramp-tramp-file-p filename) | 2148 | (with-parsed-tramp-file-name filename v1 |
| 2071 | (tramp-dissect-file-name (tramp-handle-expand-file-name filename)))) | 2149 | (with-parsed-tramp-file-name newname v2 |
| 2072 | (v2 (when (tramp-tramp-file-p newname) | 2150 | (when (and (tramp-ange-ftp-file-name-p v1-multi-method v1-method) |
| 2073 | (tramp-dissect-file-name (tramp-handle-expand-file-name newname)))) | 2151 | (tramp-ange-ftp-file-name-p v2-multi-method v2-method)) |
| 2074 | (mmeth1 (when v1 (tramp-file-name-multi-method v1))) | 2152 | (tramp-invoke-ange-ftp |
| 2075 | (mmeth2 (when v2 (tramp-file-name-multi-method v2))) | 2153 | (if (eq op 'copy) 'copy-file 'rename-file) |
| 2076 | (meth1 (when v1 (tramp-file-name-method v1))) | 2154 | filename newname ok-if-already-exists keep-date)) |
| 2077 | (meth2 (when v2 (tramp-file-name-method v2))) | 2155 | (let* ((mmeth (tramp-file-name-multi-method (or v1 v2))) |
| 2078 | (mmeth (tramp-file-name-multi-method (or v1 v2))) | 2156 | (meth (tramp-file-name-method (or v1 v2))) |
| 2079 | (meth (tramp-file-name-method (or v1 v2))) | 2157 | (rcp-program (tramp-get-rcp-program mmeth meth)) |
| 2080 | (rcp-program (tramp-get-rcp-program mmeth meth)) | 2158 | (rcp-args (tramp-get-rcp-args mmeth meth)) |
| 2081 | (rcp-args (tramp-get-rcp-args mmeth meth)) | 2159 | (trampbuf (get-buffer-create "*tramp output*"))) |
| 2082 | (trampbuf (get-buffer-create "*tramp output*"))) | 2160 | ;; Check if we can use a shortcut. |
| 2083 | ;; Check if we can use a shortcut. | 2161 | (if (and v1-method v2-method |
| 2084 | (if (and meth1 meth2 (equal mmeth1 mmeth2) (equal meth1 meth2) | 2162 | (equal v1-multi-method v2-multi-method) |
| 2085 | (equal (tramp-file-name-host v1) | 2163 | (equal v1-method v2-method) |
| 2086 | (tramp-file-name-host v2)) | 2164 | (equal v1-host v2-host) |
| 2087 | (equal (tramp-file-name-user v1) | 2165 | (equal v1-user v2-user)) |
| 2088 | (tramp-file-name-user v2))) | 2166 | ;; Shortcut: if method, host, user are the same for both |
| 2089 | ;; Shortcut: if method, host, user are the same for both | 2167 | ;; files, we invoke `cp' or `mv' on the remote host directly. |
| 2090 | ;; files, we invoke `cp' or `mv' on the remote host directly. | 2168 | (tramp-do-copy-or-rename-file-directly |
| 2091 | (tramp-do-copy-or-rename-file-directly | 2169 | op |
| 2092 | op | 2170 | v1-multi-method v1-method v1-user v1-host v1-path v2-path |
| 2093 | (tramp-file-name-multi-method v1) | 2171 | keep-date) |
| 2094 | (tramp-file-name-method v1) | 2172 | ;; New algorithm: copy file first. Then, if operation is |
| 2095 | (tramp-file-name-user v1) | 2173 | ;; `rename', go back and delete the original file if the copy |
| 2096 | (tramp-file-name-host v1) | 2174 | ;; was successful. |
| 2097 | (tramp-file-name-path v1) (tramp-file-name-path v2) | 2175 | (if rcp-program |
| 2098 | keep-date) | 2176 | ;; The following code uses a tramp program to copy the file. |
| 2099 | ;; New algorithm: copy file first. Then, if operation is | 2177 | (let ((f1 (if (not v1) |
| 2100 | ;; `rename', go back and delete the original file if the copy | 2178 | filename |
| 2101 | ;; was successful. | 2179 | (tramp-make-rcp-program-file-name |
| 2102 | (if rcp-program | 2180 | v1-user v1-host |
| 2103 | ;; The following code uses a tramp program to copy the file. | 2181 | (tramp-shell-quote-argument v1-path)))) |
| 2104 | (let ((f1 (if (not v1) | 2182 | (f2 (if (not v2) |
| 2105 | filename | 2183 | newname |
| 2106 | (tramp-make-rcp-program-file-name | 2184 | (tramp-make-rcp-program-file-name |
| 2107 | (tramp-file-name-user v1) | 2185 | v2-user v2-host |
| 2108 | (tramp-file-name-host v1) | 2186 | (tramp-shell-quote-argument v2-path)))) |
| 2109 | (tramp-shell-quote-argument (tramp-file-name-path v1))))) | 2187 | (default-directory |
| 2110 | (f2 (if (not v2) | 2188 | (if (tramp-tramp-file-p default-directory) |
| 2111 | newname | 2189 | (tramp-temporary-file-directory) |
| 2112 | (tramp-make-rcp-program-file-name | 2190 | default-directory))) |
| 2113 | (tramp-file-name-user v2) | 2191 | (when keep-date |
| 2114 | (tramp-file-name-host v2) | 2192 | (add-to-list 'rcp-args |
| 2115 | (tramp-shell-quote-argument (tramp-file-name-path v2))))) | 2193 | (tramp-get-rcp-keep-date-arg mmeth meth))) |
| 2116 | (default-directory | 2194 | (save-excursion (set-buffer trampbuf) (erase-buffer)) |
| 2117 | (if (tramp-tramp-file-p default-directory) | 2195 | (unless (equal 0 (apply #'call-process |
| 2118 | (tramp-temporary-file-directory) | 2196 | (tramp-get-rcp-program mmeth meth) |
| 2119 | default-directory))) | 2197 | nil trampbuf nil |
| 2120 | (when keep-date | 2198 | (append rcp-args (list f1 f2)))) |
| 2121 | (add-to-list 'rcp-args (tramp-get-rcp-keep-date-arg mmeth meth))) | 2199 | (pop-to-buffer trampbuf) |
| 2122 | (save-excursion (set-buffer trampbuf) (erase-buffer)) | 2200 | (error (concat "tramp-do-copy-or-rename-file: %s" |
| 2123 | (unless | 2201 | " didn't work, see buffer `%s' for details") |
| 2124 | (equal 0 (apply #'call-process (tramp-get-rcp-program mmeth meth) | 2202 | (tramp-get-rcp-program mmeth meth) trampbuf))) |
| 2125 | nil trampbuf nil (append rcp-args (list f1 f2)))) | 2203 | ;; The following code uses an inline method for copying. |
| 2126 | (pop-to-buffer trampbuf) | 2204 | ;; Let's start with a simple-minded approach: we create a new |
| 2127 | (error (concat "tramp-do-copy-or-rename-file: %s" | 2205 | ;; buffer, insert the contents of the source file into it, |
| 2128 | " didn't work, see buffer `%s' for details") | 2206 | ;; then write out the buffer. This should work fine, whether |
| 2129 | (tramp-get-rcp-program mmeth meth) trampbuf))) | 2207 | ;; the source or the target files are tramp files. |
| 2130 | ;; The following code uses an inline method for copying. | 2208 | ;; CCC TODO: error checking |
| 2131 | ;; Let's start with a simple-minded approach: we create a new | 2209 | (when keep-date |
| 2132 | ;; buffer, insert the contents of the source file into it, | 2210 | (tramp-message |
| 2133 | ;; then write out the buffer. This should work fine, whether | 2211 | 1 (concat "Warning: cannot preserve file time stamp" |
| 2134 | ;; the source or the target files are tramp files. | 2212 | " with inline copying across machines"))) |
| 2135 | ;; CCC TODO: error checking | 2213 | (save-excursion |
| 2136 | (when keep-date | 2214 | (set-buffer trampbuf) (erase-buffer) |
| 2137 | (tramp-message 1 (concat "Warning: cannot preserve file time stamp" | 2215 | (insert-file-contents-literally filename) |
| 2138 | " with inline copying across machines"))) | 2216 | (let ((coding-system-for-write 'no-conversion)) |
| 2139 | (save-excursion | 2217 | (write-region (point-min) (point-max) newname)))) |
| 2140 | (set-buffer trampbuf) (erase-buffer) | 2218 | |
| 2141 | (insert-file-contents-literally filename) | 2219 | ;; If the operation was `rename', delete the original file. |
| 2142 | (let ((coding-system-for-write 'no-conversion)) | 2220 | (unless (eq op 'copy) |
| 2143 | (write-region (point-min) (point-max) newname)))) | 2221 | (delete-file filename))))))) |
| 2144 | |||
| 2145 | ;; If the operation was `rename', delete the original file. | ||
| 2146 | (unless (eq op 'copy) | ||
| 2147 | (delete-file filename))))) | ||
| 2148 | 2222 | ||
| 2149 | (defun tramp-do-copy-or-rename-file-directly | 2223 | (defun tramp-do-copy-or-rename-file-directly |
| 2150 | (op multi-method method user host path1 path2 keep-date) | 2224 | (op multi-method method user host path1 path2 keep-date) |
| @@ -2174,41 +2248,41 @@ If KEEP-DATE is non-nil, preserve the time stamp when copying." | |||
| 2174 | ;; mkdir | 2248 | ;; mkdir |
| 2175 | (defun tramp-handle-make-directory (dir &optional parents) | 2249 | (defun tramp-handle-make-directory (dir &optional parents) |
| 2176 | "Like `make-directory' for tramp files." | 2250 | "Like `make-directory' for tramp files." |
| 2177 | (let ((v (tramp-dissect-file-name (tramp-handle-expand-file-name dir)))) | 2251 | (with-parsed-tramp-file-name dir nil |
| 2252 | (when (tramp-ange-ftp-file-name-p multi-method method) | ||
| 2253 | (tramp-invoke-ange-ftp 'make-directory dir parents)) | ||
| 2178 | (tramp-barf-unless-okay | 2254 | (tramp-barf-unless-okay |
| 2179 | (tramp-file-name-multi-method v) (tramp-file-name-method v) | 2255 | multi-method method user host |
| 2180 | (tramp-file-name-user v) (tramp-file-name-host v) | ||
| 2181 | (format " %s %s" | 2256 | (format " %s %s" |
| 2182 | (if parents "mkdir -p" "mkdir") | 2257 | (if parents "mkdir -p" "mkdir") |
| 2183 | (tramp-shell-quote-argument (tramp-file-name-path v))) | 2258 | (tramp-shell-quote-argument path)) |
| 2184 | nil 'file-error | 2259 | nil 'file-error |
| 2185 | "Couldn't make directory %s" dir))) | 2260 | "Couldn't make directory %s" dir))) |
| 2186 | 2261 | ||
| 2187 | ;; CCC error checking? | 2262 | ;; CCC error checking? |
| 2188 | (defun tramp-handle-delete-directory (directory) | 2263 | (defun tramp-handle-delete-directory (directory) |
| 2189 | "Like `delete-directory' for tramp files." | 2264 | "Like `delete-directory' for tramp files." |
| 2190 | (let ((v (tramp-dissect-file-name (tramp-handle-expand-file-name directory)))) | 2265 | (with-parsed-tramp-file-name directory nil |
| 2266 | (when (tramp-ange-ftp-file-name-p multi-method method) | ||
| 2267 | (tramp-invoke-ange-ftp 'delete-directory directory)) | ||
| 2191 | (save-excursion | 2268 | (save-excursion |
| 2192 | (tramp-send-command | 2269 | (tramp-send-command |
| 2193 | (tramp-file-name-multi-method v) (tramp-file-name-method v) | 2270 | multi-method method user host |
| 2194 | (tramp-file-name-user v) (tramp-file-name-host v) | ||
| 2195 | (format "rmdir %s ; echo ok" | 2271 | (format "rmdir %s ; echo ok" |
| 2196 | (tramp-shell-quote-argument (tramp-file-name-path v)))) | 2272 | (tramp-shell-quote-argument path))) |
| 2197 | (tramp-wait-for-output)))) | 2273 | (tramp-wait-for-output)))) |
| 2198 | 2274 | ||
| 2199 | (defun tramp-handle-delete-file (filename) | 2275 | (defun tramp-handle-delete-file (filename) |
| 2200 | "Like `delete-file' for tramp files." | 2276 | "Like `delete-file' for tramp files." |
| 2201 | (let ((v (tramp-dissect-file-name (tramp-handle-expand-file-name filename)))) | 2277 | (with-parsed-tramp-file-name filename nil |
| 2202 | (save-excursion | 2278 | (with-tramp-calling-ange-ftp |
| 2203 | (unless (zerop (tramp-send-command-and-check | 2279 | nil 'delete-file (list filename) |
| 2204 | (tramp-file-name-multi-method v) | 2280 | (save-excursion |
| 2205 | (tramp-file-name-method v) | 2281 | (unless (zerop (tramp-send-command-and-check |
| 2206 | (tramp-file-name-user v) | 2282 | multi-method method user host |
| 2207 | (tramp-file-name-host v) | 2283 | (format "rm -f %s" |
| 2208 | (format "rm -f %s" | 2284 | (tramp-shell-quote-argument path)))) |
| 2209 | (tramp-shell-quote-argument | 2285 | (signal 'file-error "Couldn't delete Tramp file")))))) |
| 2210 | (tramp-file-name-path v))))) | ||
| 2211 | (signal 'file-error "Couldn't delete Tramp file"))))) | ||
| 2212 | 2286 | ||
| 2213 | ;; Dired. | 2287 | ;; Dired. |
| 2214 | 2288 | ||
| @@ -2217,12 +2291,10 @@ If KEEP-DATE is non-nil, preserve the time stamp when copying." | |||
| 2217 | (defun tramp-handle-dired-recursive-delete-directory (filename) | 2291 | (defun tramp-handle-dired-recursive-delete-directory (filename) |
| 2218 | "Recursively delete the directory given. | 2292 | "Recursively delete the directory given. |
| 2219 | This is like `dired-recursive-delete-directory' for tramp files." | 2293 | This is like `dired-recursive-delete-directory' for tramp files." |
| 2220 | (let* ((v (tramp-dissect-file-name (tramp-handle-expand-file-name filename))) | 2294 | (with-parsed-tramp-file-name filename nil |
| 2221 | (multi-method (tramp-file-name-multi-method v)) | 2295 | (when (tramp-ange-ftp-file-name-p multi-method method) |
| 2222 | (method (tramp-file-name-method v)) | 2296 | (tramp-invoke-ange-ftp 'dired-recursive-delete-directory |
| 2223 | (user (tramp-file-name-user v)) | 2297 | filename)) |
| 2224 | (host (tramp-file-name-host v)) | ||
| 2225 | (path (tramp-file-name-path v))) | ||
| 2226 | ;; run a shell command 'rm -r <path>' | 2298 | ;; run a shell command 'rm -r <path>' |
| 2227 | ;; Code shamelessly stolen for the dired implementation and, um, hacked :) | 2299 | ;; Code shamelessly stolen for the dired implementation and, um, hacked :) |
| 2228 | (or (tramp-handle-file-exists-p filename) | 2300 | (or (tramp-handle-file-exists-p filename) |
| @@ -2231,7 +2303,7 @@ This is like `dired-recursive-delete-directory' for tramp files." | |||
| 2231 | (list "Removing old file name" "no such directory" filename))) | 2303 | (list "Removing old file name" "no such directory" filename))) |
| 2232 | ;; Which is better, -r or -R? (-r works for me <daniel@danann.net>) | 2304 | ;; Which is better, -r or -R? (-r works for me <daniel@danann.net>) |
| 2233 | (tramp-send-command multi-method method user host | 2305 | (tramp-send-command multi-method method user host |
| 2234 | (format "rm -r %s" (tramp-shell-quote-argument path))) | 2306 | (format "rm -r %s" (tramp-shell-quote-argument path))) |
| 2235 | ;; Wait for the remote system to return to us... | 2307 | ;; Wait for the remote system to return to us... |
| 2236 | ;; This might take a while, allow it plenty of time. | 2308 | ;; This might take a while, allow it plenty of time. |
| 2237 | (tramp-wait-for-output 120) | 2309 | (tramp-wait-for-output 120) |
| @@ -2242,14 +2314,12 @@ This is like `dired-recursive-delete-directory' for tramp files." | |||
| 2242 | 2314 | ||
| 2243 | (defun tramp-handle-dired-call-process (program discard &rest arguments) | 2315 | (defun tramp-handle-dired-call-process (program discard &rest arguments) |
| 2244 | "Like `dired-call-process' for tramp files." | 2316 | "Like `dired-call-process' for tramp files." |
| 2245 | (let ((v (tramp-dissect-file-name | 2317 | (with-parsed-tramp-file-name default-directory nil |
| 2246 | (tramp-handle-expand-file-name default-directory))) | 2318 | (when (tramp-ange-ftp-file-name-p multi-method method) |
| 2247 | multi-method method user host path) | 2319 | (let ((default-directory |
| 2248 | (setq multi-method (tramp-file-name-multi-method v)) | 2320 | (tramp-make-ange-ftp-file-name user host path))) |
| 2249 | (setq method (tramp-file-name-method v)) | 2321 | (tramp-invoke-ange-ftp 'dired-call-process |
| 2250 | (setq user (tramp-file-name-user v)) | 2322 | program discard arguments))) |
| 2251 | (setq host (tramp-file-name-host v)) | ||
| 2252 | (setq path (tramp-file-name-path v)) | ||
| 2253 | (save-excursion | 2323 | (save-excursion |
| 2254 | (tramp-barf-unless-okay | 2324 | (tramp-barf-unless-okay |
| 2255 | multi-method method user host | 2325 | multi-method method user host |
| @@ -2285,13 +2355,10 @@ This is like `dired-recursive-delete-directory' for tramp files." | |||
| 2285 | (defun tramp-handle-insert-directory | 2355 | (defun tramp-handle-insert-directory |
| 2286 | (filename switches &optional wildcard full-directory-p) | 2356 | (filename switches &optional wildcard full-directory-p) |
| 2287 | "Like `insert-directory' for tramp files." | 2357 | "Like `insert-directory' for tramp files." |
| 2288 | (let ((v (tramp-dissect-file-name (tramp-handle-expand-file-name filename))) | 2358 | (with-parsed-tramp-file-name filename nil |
| 2289 | multi-method method user host path) | 2359 | (when (tramp-ange-ftp-file-name-p multi-method method) |
| 2290 | (setq multi-method (tramp-file-name-multi-method v)) | 2360 | (tramp-invoke-ange-ftp 'insert-directory |
| 2291 | (setq method (tramp-file-name-method v)) | 2361 | filename switches wildcard full-directory-p)) |
| 2292 | (setq user (tramp-file-name-user v)) | ||
| 2293 | (setq host (tramp-file-name-host v)) | ||
| 2294 | (setq path (tramp-file-name-path v)) | ||
| 2295 | (tramp-message-for-buffer | 2362 | (tramp-message-for-buffer |
| 2296 | multi-method method user host 10 | 2363 | multi-method method user host 10 |
| 2297 | "Inserting directory `ls %s %s', wildcard %s, fulldir %s" | 2364 | "Inserting directory `ls %s %s', wildcard %s, fulldir %s" |
| @@ -2310,33 +2377,33 @@ This is like `dired-recursive-delete-directory' for tramp files." | |||
| 2310 | ;; If `full-directory-p', we just say `ls -l FILENAME'. | 2377 | ;; If `full-directory-p', we just say `ls -l FILENAME'. |
| 2311 | ;; Else we chdir to the parent directory, then say `ls -ld BASENAME'. | 2378 | ;; Else we chdir to the parent directory, then say `ls -ld BASENAME'. |
| 2312 | (if full-directory-p | 2379 | (if full-directory-p |
| 2313 | (tramp-send-command | 2380 | (tramp-send-command |
| 2314 | multi-method method user host | 2381 | multi-method method user host |
| 2315 | (format "%s %s %s" | 2382 | (format "%s %s %s" |
| 2316 | (tramp-get-ls-command multi-method method user host) | 2383 | (tramp-get-ls-command multi-method method user host) |
| 2317 | switches | 2384 | switches |
| 2318 | (if wildcard | 2385 | (if wildcard |
| 2319 | path | 2386 | path |
| 2320 | (tramp-shell-quote-argument (concat path "."))))) | 2387 | (tramp-shell-quote-argument (concat path "."))))) |
| 2321 | (tramp-barf-unless-okay | 2388 | (tramp-barf-unless-okay |
| 2322 | multi-method method user host | 2389 | multi-method method user host |
| 2323 | (format "cd %s" (tramp-shell-quote-argument | 2390 | (format "cd %s" (tramp-shell-quote-argument |
| 2324 | (file-name-directory path))) | 2391 | (file-name-directory path))) |
| 2325 | nil 'file-error | 2392 | nil 'file-error |
| 2326 | "Couldn't `cd %s'" | 2393 | "Couldn't `cd %s'" |
| 2327 | (tramp-shell-quote-argument (file-name-directory path))) | 2394 | (tramp-shell-quote-argument (file-name-directory path))) |
| 2328 | (tramp-send-command | 2395 | (tramp-send-command |
| 2329 | multi-method method user host | 2396 | multi-method method user host |
| 2330 | (format "%s %s %s" | 2397 | (format "%s %s %s" |
| 2331 | (tramp-get-ls-command multi-method method user host) | 2398 | (tramp-get-ls-command multi-method method user host) |
| 2332 | switches | 2399 | switches |
| 2333 | (if full-directory-p | 2400 | (if full-directory-p |
| 2334 | ;; Add "/." to make sure we got complete dir | 2401 | ;; Add "/." to make sure we got complete dir |
| 2335 | ;; listing for symlinks, too. | 2402 | ;; listing for symlinks, too. |
| 2336 | (concat (file-name-as-directory | 2403 | (concat (file-name-as-directory |
| 2337 | (file-name-nondirectory path)) ".") | 2404 | (file-name-nondirectory path)) ".") |
| 2338 | (file-name-nondirectory path))))) | 2405 | (file-name-nondirectory path))))) |
| 2339 | (sit-for 1) ;needed for rsh but not ssh? | 2406 | (sit-for 1) ;needed for rsh but not ssh? |
| 2340 | (tramp-wait-for-output)) | 2407 | (tramp-wait-for-output)) |
| 2341 | (insert-buffer (tramp-get-buffer multi-method method user host)) | 2408 | (insert-buffer (tramp-get-buffer multi-method method user host)) |
| 2342 | ;; On XEmacs, we want to call (exchange-point-and-mark t), but | 2409 | ;; On XEmacs, we want to call (exchange-point-and-mark t), but |
| @@ -2351,10 +2418,10 @@ This is like `dired-recursive-delete-directory' for tramp files." | |||
| 2351 | ;; Another XEmacs specialty follows. What's the right way to do | 2418 | ;; Another XEmacs specialty follows. What's the right way to do |
| 2352 | ;; it? | 2419 | ;; it? |
| 2353 | (when (and (featurep 'xemacs) | 2420 | (when (and (featurep 'xemacs) |
| 2354 | (eq major-mode 'dired-mode)) | 2421 | (eq major-mode 'dired-mode)) |
| 2355 | (save-excursion | 2422 | (save-excursion |
| 2356 | (require 'dired) | 2423 | (require 'dired) |
| 2357 | (dired-insert-set-properties (point) (mark t)))))) | 2424 | (dired-insert-set-properties (point) (mark t)))))) |
| 2358 | 2425 | ||
| 2359 | ;; Continuation of kluge to pacify byte-compiler. | 2426 | ;; Continuation of kluge to pacify byte-compiler. |
| 2360 | ;;(eval-when-compile | 2427 | ;;(eval-when-compile |
| @@ -2364,7 +2431,11 @@ This is like `dired-recursive-delete-directory' for tramp files." | |||
| 2364 | ;; CCC is this the right thing to do? | 2431 | ;; CCC is this the right thing to do? |
| 2365 | (defun tramp-handle-unhandled-file-name-directory (filename) | 2432 | (defun tramp-handle-unhandled-file-name-directory (filename) |
| 2366 | "Like `unhandled-file-name-directory' for tramp files." | 2433 | "Like `unhandled-file-name-directory' for tramp files." |
| 2367 | (expand-file-name "~/")) | 2434 | (with-parsed-tramp-file-name filename nil |
| 2435 | (when (tramp-ange-ftp-file-name-p multi-method method) | ||
| 2436 | (tramp-invoke-ange-ftp 'unhandled-file-name-directory | ||
| 2437 | filename)) | ||
| 2438 | (expand-file-name "~/"))) | ||
| 2368 | 2439 | ||
| 2369 | ;; Canonicalization of file names. | 2440 | ;; Canonicalization of file names. |
| 2370 | 2441 | ||
| @@ -2396,12 +2467,9 @@ Doesn't do anything if the NAME does not start with a drive letter." | |||
| 2396 | (tramp-run-real-handler 'expand-file-name | 2467 | (tramp-run-real-handler 'expand-file-name |
| 2397 | (list name nil)) | 2468 | (list name nil)) |
| 2398 | ;; Dissect NAME. | 2469 | ;; Dissect NAME. |
| 2399 | (let* ((v (tramp-dissect-file-name name)) | 2470 | (with-parsed-tramp-file-name name nil |
| 2400 | (multi-method (tramp-file-name-multi-method v)) | 2471 | (when (tramp-ange-ftp-file-name-p multi-method method) |
| 2401 | (method (tramp-file-name-method v)) | 2472 | (tramp-invoke-ange-ftp 'expand-file-name name nil)) |
| 2402 | (user (tramp-file-name-user v)) | ||
| 2403 | (host (tramp-file-name-host v)) | ||
| 2404 | (path (tramp-file-name-path v))) | ||
| 2405 | (unless (file-name-absolute-p path) | 2473 | (unless (file-name-absolute-p path) |
| 2406 | (setq path (concat "~/" path))) | 2474 | (setq path (concat "~/" path))) |
| 2407 | (save-excursion | 2475 | (save-excursion |
| @@ -2441,59 +2509,59 @@ Doesn't do anything if the NAME does not start with a drive letter." | |||
| 2441 | This will break if COMMAND prints a newline, followed by the value of | 2509 | This will break if COMMAND prints a newline, followed by the value of |
| 2442 | `tramp-end-of-output', followed by another newline." | 2510 | `tramp-end-of-output', followed by another newline." |
| 2443 | (if (tramp-tramp-file-p default-directory) | 2511 | (if (tramp-tramp-file-p default-directory) |
| 2444 | (let* ((v (tramp-dissect-file-name | 2512 | (with-parsed-tramp-file-name default-directory nil |
| 2445 | (tramp-handle-expand-file-name default-directory))) | 2513 | (when (tramp-ange-ftp-file-name-p multi-method method) |
| 2446 | (multi-method (tramp-file-name-multi-method v)) | 2514 | (let ((default-directory (tramp-make-ange-ftp-file-name |
| 2447 | (method (tramp-file-name-method v)) | 2515 | user host path))) |
| 2448 | (user (tramp-file-name-user v)) | 2516 | (tramp-invoke-ange-ftp 'shell-command |
| 2449 | (host (tramp-file-name-host v)) | 2517 | command output-buffer error-buffer))) |
| 2450 | (path (tramp-file-name-path v)) | 2518 | (let (status) |
| 2451 | status) | 2519 | (when (string-match "&[ \t]*\\'" command) |
| 2452 | (when (string-match "&[ \t]*\\'" command) | 2520 | (error "Tramp doesn't grok asynchronous shell commands, yet")) |
| 2453 | (error "Tramp doesn't grok asynchronous shell commands, yet")) | 2521 | (when error-buffer |
| 2454 | (when error-buffer | 2522 | (error "Tramp doesn't grok optional third arg ERROR-BUFFER, yet")) |
| 2455 | (error "Tramp doesn't grok optional third arg ERROR-BUFFER, yet")) | 2523 | (save-excursion |
| 2456 | (save-excursion | 2524 | (tramp-barf-unless-okay |
| 2457 | (tramp-barf-unless-okay | 2525 | multi-method method user host |
| 2458 | multi-method method user host | 2526 | (format "cd %s" (tramp-shell-quote-argument path)) |
| 2459 | (format "cd %s" (tramp-shell-quote-argument path)) | 2527 | nil 'file-error |
| 2460 | nil 'file-error | 2528 | "tramp-handle-shell-command: Couldn't `cd %s'" |
| 2461 | "tramp-handle-shell-command: Couldn't `cd %s'" | 2529 | (tramp-shell-quote-argument path)) |
| 2462 | (tramp-shell-quote-argument path)) | 2530 | (tramp-send-command multi-method method user host |
| 2463 | (tramp-send-command multi-method method user host | 2531 | (concat command "; tramp_old_status=$?")) |
| 2464 | (concat command "; tramp_old_status=$?")) | 2532 | ;; This will break if the shell command prints "/////" |
| 2465 | ;; This will break if the shell command prints "/////" | 2533 | ;; somewhere. Let's just hope for the best... |
| 2466 | ;; somewhere. Let's just hope for the best... | 2534 | (tramp-wait-for-output)) |
| 2467 | (tramp-wait-for-output)) | 2535 | (unless output-buffer |
| 2468 | (unless output-buffer | 2536 | (setq output-buffer (get-buffer-create "*Shell Command Output*")) |
| 2469 | (setq output-buffer (get-buffer-create "*Shell Command Output*")) | 2537 | (set-buffer output-buffer) |
| 2470 | (set-buffer output-buffer) | 2538 | (erase-buffer)) |
| 2471 | (erase-buffer)) | 2539 | (unless (bufferp output-buffer) |
| 2472 | (unless (bufferp output-buffer) | 2540 | (setq output-buffer (current-buffer))) |
| 2473 | (setq output-buffer (current-buffer))) | 2541 | (set-buffer output-buffer) |
| 2474 | (set-buffer output-buffer) | 2542 | (insert-buffer (tramp-get-buffer multi-method method user host)) |
| 2475 | (insert-buffer (tramp-get-buffer multi-method method user host)) | 2543 | (save-excursion |
| 2476 | (save-excursion | 2544 | (tramp-send-command multi-method method user host "cd") |
| 2477 | (tramp-send-command multi-method method user host "cd") | 2545 | (tramp-wait-for-output) |
| 2478 | (tramp-wait-for-output) | 2546 | (tramp-send-command |
| 2479 | (tramp-send-command | 2547 | multi-method method user host |
| 2480 | multi-method method user host | 2548 | (concat "tramp_set_exit_status $tramp_old_status;" |
| 2481 | "tramp_set_exit_status $tramp_old_status; echo tramp_exit_status $?") | 2549 | " echo tramp_exit_status $?")) |
| 2482 | (tramp-wait-for-output) | 2550 | (tramp-wait-for-output) |
| 2483 | (goto-char (point-max)) | 2551 | (goto-char (point-max)) |
| 2484 | (unless (search-backward "tramp_exit_status " nil t) | 2552 | (unless (search-backward "tramp_exit_status " nil t) |
| 2485 | (error "Couldn't find exit status of `%s'" command)) | 2553 | (error "Couldn't find exit status of `%s'" command)) |
| 2486 | (skip-chars-forward "^ ") | 2554 | (skip-chars-forward "^ ") |
| 2487 | (setq status (read (current-buffer)))) | 2555 | (setq status (read (current-buffer)))) |
| 2488 | (unless (zerop (buffer-size)) | 2556 | (unless (zerop (buffer-size)) |
| 2489 | (pop-to-buffer output-buffer)) | 2557 | (pop-to-buffer output-buffer)) |
| 2490 | status) | 2558 | status))) |
| 2491 | ;; The following is only executed if something strange was | 2559 | ;; The following is only executed if something strange was |
| 2492 | ;; happening. Emit a helpful message and do it anyway. | 2560 | ;; happening. Emit a helpful message and do it anyway. |
| 2493 | (message "tramp-handle-shell-command called with non-tramp directory: `%s'" | 2561 | (message "tramp-handle-shell-command called with non-tramp directory: `%s'" |
| 2494 | default-directory) | 2562 | default-directory) |
| 2495 | (tramp-run-real-handler 'shell-command | 2563 | (tramp-run-real-handler 'shell-command |
| 2496 | (list command output-buffer error-buffer)))) | 2564 | (list command output-buffer error-buffer))) |
| 2497 | 2565 | ||
| 2498 | ;; File Editing. | 2566 | ;; File Editing. |
| 2499 | 2567 | ||
| @@ -2504,104 +2572,106 @@ This will break if COMMAND prints a newline, followed by the value of | |||
| 2504 | 2572 | ||
| 2505 | (defun tramp-handle-file-local-copy (filename) | 2573 | (defun tramp-handle-file-local-copy (filename) |
| 2506 | "Like `file-local-copy' for tramp files." | 2574 | "Like `file-local-copy' for tramp files." |
| 2507 | (let* ((v (tramp-dissect-file-name (tramp-handle-expand-file-name filename))) | 2575 | (with-parsed-tramp-file-name filename nil |
| 2508 | (multi-method (tramp-file-name-multi-method v)) | 2576 | (when (tramp-ange-ftp-file-name-p multi-method method) |
| 2509 | (method (tramp-file-name-method v)) | 2577 | (tramp-invoke-ange-ftp 'file-local-copy filename)) |
| 2510 | (user (tramp-file-name-user v)) | 2578 | (let ((trampbuf (get-buffer-create "*tramp output*")) |
| 2511 | (host (tramp-file-name-host v)) | 2579 | tmpfil) |
| 2512 | (path (tramp-file-name-path v)) | 2580 | (unless (file-exists-p filename) |
| 2513 | (trampbuf (get-buffer-create "*tramp output*")) | 2581 | (error "Cannot make local copy of non-existing file `%s'" |
| 2514 | tmpfil) | 2582 | filename)) |
| 2515 | (unless (file-exists-p filename) | 2583 | (setq tmpfil (tramp-make-temp-file)) |
| 2516 | (error "Cannot make local copy of non-existing file `%s'" | 2584 | (cond ((tramp-get-rcp-program multi-method method) |
| 2517 | filename)) | 2585 | ;; Use tramp-like program for file transfer. |
| 2518 | (setq tmpfil (tramp-make-temp-file)) | 2586 | (tramp-message-for-buffer |
| 2519 | (cond ((tramp-get-rcp-program multi-method method) | 2587 | multi-method method user host |
| 2520 | ;; Use tramp-like program for file transfer. | 2588 | 5 "Fetching %s to tmp file %s..." filename tmpfil) |
| 2521 | (tramp-message-for-buffer | 2589 | (save-excursion (set-buffer trampbuf) (erase-buffer)) |
| 2522 | multi-method method user host | 2590 | (unless (equal |
| 2523 | 5 "Fetching %s to tmp file %s..." filename tmpfil) | 2591 | 0 |
| 2524 | (save-excursion (set-buffer trampbuf) (erase-buffer)) | 2592 | (apply #'call-process |
| 2525 | (unless (equal 0 | 2593 | (tramp-get-rcp-program multi-method method) |
| 2526 | (apply #'call-process | 2594 | nil trampbuf nil |
| 2527 | (tramp-get-rcp-program multi-method method) | 2595 | (append (tramp-get-rcp-args multi-method method) |
| 2528 | nil trampbuf nil | 2596 | (list |
| 2529 | (append (tramp-get-rcp-args multi-method method) | 2597 | (tramp-make-rcp-program-file-name |
| 2530 | (list | 2598 | user host |
| 2531 | (tramp-make-rcp-program-file-name | 2599 | (tramp-shell-quote-argument path)) |
| 2532 | user host | 2600 | tmpfil)))) |
| 2533 | (tramp-shell-quote-argument path)) | 2601 | (pop-to-buffer trampbuf) |
| 2534 | tmpfil)))) | 2602 | (error |
| 2535 | (pop-to-buffer trampbuf) | 2603 | (concat "tramp-handle-file-local-copy: `%s' didn't work, " |
| 2536 | (error (concat "tramp-handle-file-local-copy: `%s' didn't work, " | 2604 | "see buffer `%s' for details") |
| 2537 | "see buffer `%s' for details") | 2605 | (tramp-get-rcp-program multi-method method) trampbuf)) |
| 2538 | (tramp-get-rcp-program multi-method method) trampbuf)) | 2606 | (tramp-message-for-buffer |
| 2539 | (tramp-message-for-buffer | 2607 | multi-method method user host |
| 2540 | multi-method method user host | 2608 | 5 "Fetching %s to tmp file %s...done" filename tmpfil)) |
| 2541 | 5 "Fetching %s to tmp file %s...done" filename tmpfil)) | 2609 | ((and (tramp-get-encoding-command multi-method method) |
| 2542 | ((and (tramp-get-encoding-command multi-method method) | ||
| 2543 | (tramp-get-decoding-command multi-method method)) | ||
| 2544 | ;; Use inline encoding for file transfer. | ||
| 2545 | (save-excursion | ||
| 2546 | ;; Following line for setting tramp-current-method, | ||
| 2547 | ;; tramp-current-user, tramp-current-host. | ||
| 2548 | (set-buffer (tramp-get-buffer multi-method method user host)) | ||
| 2549 | (tramp-message 5 "Encoding remote file %s..." filename) | ||
| 2550 | (tramp-barf-unless-okay | ||
| 2551 | multi-method method user host | ||
| 2552 | (concat (tramp-get-encoding-command multi-method method) | ||
| 2553 | " < " (tramp-shell-quote-argument path)) | ||
| 2554 | nil 'file-error | ||
| 2555 | "Encoding remote file failed, see buffer `%s' for details" | ||
| 2556 | (tramp-get-buffer multi-method method user host)) | ||
| 2557 | ;; Remove trailing status code | ||
| 2558 | (goto-char (point-max)) | ||
| 2559 | (delete-region (point) (progn (forward-line -1) (point))) | ||
| 2560 | |||
| 2561 | (tramp-message 5 "Decoding remote file %s..." filename) | ||
| 2562 | (if (and (tramp-get-decoding-function multi-method method) | ||
| 2563 | (fboundp (tramp-get-decoding-function multi-method method))) | ||
| 2564 | ;; If tramp-decoding-function is defined for this | ||
| 2565 | ;; method, we call it. | ||
| 2566 | (let ((tmpbuf (get-buffer-create " *tramp tmp*"))) | ||
| 2567 | (set-buffer tmpbuf) | ||
| 2568 | (erase-buffer) | ||
| 2569 | (insert-buffer (tramp-get-buffer multi-method method | ||
| 2570 | user host)) | ||
| 2571 | (tramp-message-for-buffer | ||
| 2572 | multi-method method user host | ||
| 2573 | 6 "Decoding remote file %s with function %s..." | ||
| 2574 | filename | ||
| 2575 | (tramp-get-decoding-function multi-method method)) | ||
| 2576 | (set-buffer tmpbuf) | ||
| 2577 | (let ((coding-system-for-write 'no-conversion)) | ||
| 2578 | (funcall (tramp-get-decoding-function multi-method method) | ||
| 2579 | (point-min) | ||
| 2580 | (point-max)) | ||
| 2581 | (write-region (point-min) (point-max) tmpfil)) | ||
| 2582 | (kill-buffer tmpbuf)) | ||
| 2583 | ;; If tramp-decoding-function is not defined for this | ||
| 2584 | ;; method, we invoke tramp-decoding-command instead. | ||
| 2585 | (let ((tmpfil2 (tramp-make-temp-file))) | ||
| 2586 | (write-region (point-min) (point-max) tmpfil2) | ||
| 2587 | (tramp-message | ||
| 2588 | 6 "Decoding remote file %s with command %s..." | ||
| 2589 | filename | ||
| 2590 | (tramp-get-decoding-command multi-method method)) | 2610 | (tramp-get-decoding-command multi-method method)) |
| 2591 | (call-process | 2611 | ;; Use inline encoding for file transfer. |
| 2592 | tramp-sh-program | 2612 | (save-excursion |
| 2593 | tmpfil2 ;input | 2613 | ;; Following line for setting tramp-current-method, |
| 2594 | nil ;output | 2614 | ;; tramp-current-user, tramp-current-host. |
| 2595 | nil ;display | 2615 | (set-buffer (tramp-get-buffer multi-method method user host)) |
| 2596 | "-c" (concat (tramp-get-decoding-command multi-method method) | 2616 | (tramp-message 5 "Encoding remote file %s..." filename) |
| 2597 | " > " tmpfil)) | 2617 | (tramp-barf-unless-okay |
| 2598 | (delete-file tmpfil2))) | 2618 | multi-method method user host |
| 2599 | (tramp-message-for-buffer | 2619 | (concat (tramp-get-encoding-command multi-method method) |
| 2600 | multi-method method user host | 2620 | " < " (tramp-shell-quote-argument path)) |
| 2601 | 5 "Decoding remote file %s...done" filename))) | 2621 | nil 'file-error |
| 2602 | 2622 | "Encoding remote file failed, see buffer `%s' for details" | |
| 2603 | (t (error "Wrong method specification for `%s'" method))) | 2623 | (tramp-get-buffer multi-method method user host)) |
| 2604 | tmpfil)) | 2624 | ;; Remove trailing status code |
| 2625 | (goto-char (point-max)) | ||
| 2626 | (delete-region (point) (progn (forward-line -1) (point))) | ||
| 2627 | |||
| 2628 | (tramp-message 5 "Decoding remote file %s..." filename) | ||
| 2629 | (if (and (tramp-get-decoding-function multi-method method) | ||
| 2630 | (fboundp (tramp-get-decoding-function | ||
| 2631 | multi-method method))) | ||
| 2632 | ;; If tramp-decoding-function is defined for this | ||
| 2633 | ;; method, we call it. | ||
| 2634 | (let ((tmpbuf (get-buffer-create " *tramp tmp*"))) | ||
| 2635 | (set-buffer tmpbuf) | ||
| 2636 | (erase-buffer) | ||
| 2637 | (insert-buffer (tramp-get-buffer multi-method method | ||
| 2638 | user host)) | ||
| 2639 | (tramp-message-for-buffer | ||
| 2640 | multi-method method user host | ||
| 2641 | 6 "Decoding remote file %s with function %s..." | ||
| 2642 | filename | ||
| 2643 | (tramp-get-decoding-function multi-method method)) | ||
| 2644 | (set-buffer tmpbuf) | ||
| 2645 | (let ((coding-system-for-write 'no-conversion)) | ||
| 2646 | (funcall (tramp-get-decoding-function | ||
| 2647 | multi-method method) | ||
| 2648 | (point-min) | ||
| 2649 | (point-max)) | ||
| 2650 | (write-region (point-min) (point-max) tmpfil)) | ||
| 2651 | (kill-buffer tmpbuf)) | ||
| 2652 | ;; If tramp-decoding-function is not defined for this | ||
| 2653 | ;; method, we invoke tramp-decoding-command instead. | ||
| 2654 | (let ((tmpfil2 (tramp-make-temp-file))) | ||
| 2655 | (write-region (point-min) (point-max) tmpfil2) | ||
| 2656 | (tramp-message | ||
| 2657 | 6 "Decoding remote file %s with command %s..." | ||
| 2658 | filename | ||
| 2659 | (tramp-get-decoding-command multi-method method)) | ||
| 2660 | (call-process | ||
| 2661 | tramp-sh-program | ||
| 2662 | tmpfil2 ;input | ||
| 2663 | nil ;output | ||
| 2664 | nil ;display | ||
| 2665 | "-c" (concat (tramp-get-decoding-command | ||
| 2666 | multi-method method) | ||
| 2667 | " > " tmpfil)) | ||
| 2668 | (delete-file tmpfil2))) | ||
| 2669 | (tramp-message-for-buffer | ||
| 2670 | multi-method method user host | ||
| 2671 | 5 "Decoding remote file %s...done" filename))) | ||
| 2672 | |||
| 2673 | (t (error "Wrong method specification for `%s'" method))) | ||
| 2674 | tmpfil))) | ||
| 2605 | 2675 | ||
| 2606 | 2676 | ||
| 2607 | (defun tramp-handle-insert-file-contents | 2677 | (defun tramp-handle-insert-file-contents |
| @@ -2609,12 +2679,10 @@ This will break if COMMAND prints a newline, followed by the value of | |||
| 2609 | "Like `insert-file-contents' for tramp files." | 2679 | "Like `insert-file-contents' for tramp files." |
| 2610 | (barf-if-buffer-read-only) | 2680 | (barf-if-buffer-read-only) |
| 2611 | (setq filename (expand-file-name filename)) | 2681 | (setq filename (expand-file-name filename)) |
| 2612 | (let* ((v (tramp-dissect-file-name (tramp-handle-expand-file-name filename))) | 2682 | (with-parsed-tramp-file-name filename nil |
| 2613 | (multi-method (tramp-file-name-multi-method v)) | 2683 | (when (tramp-ange-ftp-file-name-p multi-method method) |
| 2614 | (method (tramp-file-name-method v)) | 2684 | (tramp-invoke-ange-ftp 'insert-file-contents |
| 2615 | (user (tramp-file-name-user v)) | 2685 | filename visit beg end replace)) |
| 2616 | (host (tramp-file-name-host v)) | ||
| 2617 | (path (tramp-file-name-path v))) | ||
| 2618 | (if (not (tramp-handle-file-exists-p filename)) | 2686 | (if (not (tramp-handle-file-exists-p filename)) |
| 2619 | (progn | 2687 | (progn |
| 2620 | (when visit | 2688 | (when visit |
| @@ -2654,189 +2722,194 @@ This will break if COMMAND prints a newline, followed by the value of | |||
| 2654 | (unless (eq append nil) | 2722 | (unless (eq append nil) |
| 2655 | (error "Cannot append to file using tramp (`%s')" filename)) | 2723 | (error "Cannot append to file using tramp (`%s')" filename)) |
| 2656 | (setq filename (expand-file-name filename)) | 2724 | (setq filename (expand-file-name filename)) |
| 2657 | ;; Following part commented out because we don't know what to do about | 2725 | ;; Following part commented out because we don't know what to do about |
| 2658 | ;; file locking, and it does not appear to be a problem to ignore it. | 2726 | ;; file locking, and it does not appear to be a problem to ignore it. |
| 2659 | ;; Ange-ftp ignores it, too. | 2727 | ;; Ange-ftp ignores it, too. |
| 2660 | ; (when (and lockname (stringp lockname)) | 2728 | ;; (when (and lockname (stringp lockname)) |
| 2661 | ; (setq lockname (expand-file-name lockname))) | 2729 | ;; (setq lockname (expand-file-name lockname))) |
| 2662 | ; (unless (or (eq lockname nil) | 2730 | ;; (unless (or (eq lockname nil) |
| 2663 | ; (string= lockname filename)) | 2731 | ;; (string= lockname filename)) |
| 2664 | ; (error "tramp-handle-write-region: LOCKNAME must be nil or equal FILENAME")) | 2732 | ;; (error |
| 2733 | ;; "tramp-handle-write-region: LOCKNAME must be nil or equal FILENAME")) | ||
| 2665 | ;; XEmacs takes a coding system as the sevent argument, not `confirm' | 2734 | ;; XEmacs takes a coding system as the sevent argument, not `confirm' |
| 2666 | (when (and (not (featurep 'xemacs)) | 2735 | (when (and (not (featurep 'xemacs)) |
| 2667 | confirm (file-exists-p filename)) | 2736 | confirm (file-exists-p filename)) |
| 2668 | (unless (y-or-n-p (format "File %s exists; overwrite anyway? " | 2737 | (unless (y-or-n-p (format "File %s exists; overwrite anyway? " |
| 2669 | filename)) | 2738 | filename)) |
| 2670 | (error "File not overwritten"))) | 2739 | (error "File not overwritten"))) |
| 2671 | (let* ((curbuf (current-buffer)) | 2740 | (with-parsed-tramp-file-name filename nil |
| 2672 | (v (tramp-dissect-file-name filename)) | 2741 | (when (tramp-ange-ftp-file-name-p multi-method method) |
| 2673 | (multi-method (tramp-file-name-multi-method v)) | 2742 | (tramp-invoke-ange-ftp 'write-region |
| 2674 | (method (tramp-file-name-method v)) | 2743 | start end filename append visit lockname confirm)) |
| 2675 | (user (tramp-file-name-user v)) | 2744 | (let ((curbuf (current-buffer)) |
| 2676 | (host (tramp-file-name-host v)) | 2745 | (rcp-program (tramp-get-rcp-program multi-method method)) |
| 2677 | (path (tramp-file-name-path v)) | 2746 | (rcp-args (tramp-get-rcp-args multi-method method)) |
| 2678 | (rcp-program (tramp-get-rcp-program multi-method method)) | 2747 | (encoding-command (tramp-get-encoding-command multi-method method)) |
| 2679 | (rcp-args (tramp-get-rcp-args multi-method method)) | 2748 | (encoding-function |
| 2680 | (encoding-command (tramp-get-encoding-command multi-method method)) | 2749 | (tramp-get-encoding-function multi-method method)) |
| 2681 | (encoding-function (tramp-get-encoding-function multi-method method)) | 2750 | (decoding-command (tramp-get-decoding-command multi-method method)) |
| 2682 | (decoding-command (tramp-get-decoding-command multi-method method)) | 2751 | (trampbuf (get-buffer-create "*tramp output*")) |
| 2683 | (trampbuf (get-buffer-create "*tramp output*")) | 2752 | ;; We use this to save the value of `last-coding-system-used' |
| 2684 | ;; We use this to save the value of `last-coding-system-used' | 2753 | ;; after writing the tmp file. At the end of the function, |
| 2685 | ;; after writing the tmp file. At the end of the function, | 2754 | ;; we set `last-coding-system-used' to this saved value. |
| 2686 | ;; we set `last-coding-system-used' to this saved value. | 2755 | ;; This way, any intermediary coding systems used while |
| 2687 | ;; This way, any intermediary coding systems used while | 2756 | ;; talking to the remote shell or suchlike won't hose this |
| 2688 | ;; talking to the remote shell or suchlike won't hose this | 2757 | ;; variable. This approach was snarfed from ange-ftp.el. |
| 2689 | ;; variable. This approach was snarfed from ange-ftp.el. | 2758 | coding-system-used |
| 2690 | coding-system-used | 2759 | tmpfil) |
| 2691 | tmpfil) | 2760 | ;; Write region into a tmp file. This isn't really needed if we |
| 2692 | ;; Write region into a tmp file. This isn't really needed if we | 2761 | ;; use an encoding function, but currently we use it always |
| 2693 | ;; use an encoding function, but currently we use it always | 2762 | ;; because this makes the logic simpler. |
| 2694 | ;; because this makes the logic simpler. | 2763 | (setq tmpfil (tramp-make-temp-file)) |
| 2695 | (setq tmpfil (tramp-make-temp-file)) | 2764 | ;; We say `no-message' here because we don't want the visited file |
| 2696 | ;; We say `no-message' here because we don't want the visited file | 2765 | ;; modtime data to be clobbered from the temp file. We call |
| 2697 | ;; modtime data to be clobbered from the temp file. We call | 2766 | ;; `set-visited-file-modtime' ourselves later on. |
| 2698 | ;; `set-visited-file-modtime' ourselves later on. | 2767 | (tramp-run-real-handler |
| 2699 | (tramp-run-real-handler | 2768 | 'write-region |
| 2700 | 'write-region | 2769 | (if confirm ; don't pass this arg unless defined for backward compat. |
| 2701 | (if confirm ; don't pass this arg unless defined for backward compat. | 2770 | (list start end tmpfil append 'no-message lockname confirm) |
| 2702 | (list start end tmpfil append 'no-message lockname confirm) | 2771 | (list start end tmpfil append 'no-message lockname))) |
| 2703 | (list start end tmpfil append 'no-message lockname))) | 2772 | ;; Now, `last-coding-system-used' has the right value. Remember it. |
| 2704 | ;; Now, `last-coding-system-used' has the right value. Remember it. | 2773 | (when (boundp 'last-coding-system-used) |
| 2705 | (when (boundp 'last-coding-system-used) | 2774 | (setq coding-system-used last-coding-system-used)) |
| 2706 | (setq coding-system-used last-coding-system-used)) | 2775 | ;; This is a bit lengthy due to the different methods possible for |
| 2707 | ;; This is a bit lengthy due to the different methods possible for | 2776 | ;; file transfer. First, we check whether the method uses an rcp |
| 2708 | ;; file transfer. First, we check whether the method uses an rcp | 2777 | ;; program. If so, we call it. Otherwise, both encoding and |
| 2709 | ;; program. If so, we call it. Otherwise, both encoding and | 2778 | ;; decoding command must be specified. However, if the method |
| 2710 | ;; decoding command must be specified. However, if the method | 2779 | ;; _also_ specifies an encoding function, then that is used for |
| 2711 | ;; _also_ specifies an encoding function, then that is used for | 2780 | ;; encoding the contents of the tmp file. |
| 2712 | ;; encoding the contents of the tmp file. | 2781 | (cond (rcp-program |
| 2713 | (cond (rcp-program | 2782 | ;; use rcp-like program for file transfer |
| 2714 | ;; use rcp-like program for file transfer | 2783 | (let ((argl (append rcp-args |
| 2715 | (let ((argl (append rcp-args | 2784 | (list |
| 2716 | (list | 2785 | tmpfil |
| 2717 | tmpfil | 2786 | (tramp-make-rcp-program-file-name |
| 2718 | (tramp-make-rcp-program-file-name | 2787 | user host |
| 2719 | user host | 2788 | (tramp-shell-quote-argument path)))))) |
| 2720 | (tramp-shell-quote-argument path)))))) | 2789 | (tramp-message-for-buffer |
| 2721 | (tramp-message-for-buffer | 2790 | multi-method method user host |
| 2722 | multi-method method user host | 2791 | 6 "Writing tmp file using `%s'..." rcp-program) |
| 2723 | 6 "Writing tmp file using `%s'..." rcp-program) | 2792 | (save-excursion (set-buffer trampbuf) (erase-buffer)) |
| 2724 | (save-excursion (set-buffer trampbuf) (erase-buffer)) | 2793 | (when tramp-debug-buffer |
| 2725 | (when tramp-debug-buffer | 2794 | (save-excursion |
| 2726 | (save-excursion | 2795 | (set-buffer (tramp-get-debug-buffer multi-method |
| 2727 | (set-buffer (tramp-get-debug-buffer multi-method | 2796 | method user host)) |
| 2728 | method user host)) | 2797 | (goto-char (point-max)) |
| 2729 | (goto-char (point-max)) | 2798 | (tramp-insert-with-face |
| 2730 | (tramp-insert-with-face | 2799 | 'bold (format "$ %s %s\n" rcp-program |
| 2731 | 'bold (format "$ %s %s\n" rcp-program | 2800 | (mapconcat 'identity argl " "))))) |
| 2732 | (mapconcat 'identity argl " "))))) | 2801 | (unless (equal 0 |
| 2733 | (unless (equal 0 | 2802 | (apply #'call-process |
| 2734 | (apply #'call-process | 2803 | rcp-program nil trampbuf nil argl)) |
| 2735 | rcp-program nil trampbuf nil argl)) | 2804 | (pop-to-buffer trampbuf) |
| 2736 | (pop-to-buffer trampbuf) | 2805 | (error |
| 2737 | (error "Cannot write region to file `%s', command `%s' failed" | 2806 | "Cannot write region to file `%s', command `%s' failed" |
| 2738 | filename rcp-program)) | 2807 | filename rcp-program)) |
| 2739 | (tramp-message-for-buffer multi-method method user host | 2808 | (tramp-message-for-buffer |
| 2740 | 6 "Transferring file using `%s'...done" | 2809 | multi-method method user host |
| 2741 | rcp-program))) | 2810 | 6 "Transferring file using `%s'...done" |
| 2742 | ((and encoding-command decoding-command) | 2811 | rcp-program))) |
| 2743 | ;; Use inline file transfer | 2812 | ((and encoding-command decoding-command) |
| 2744 | (let ((tmpbuf (get-buffer-create " *tramp file transfer*"))) | 2813 | ;; Use inline file transfer |
| 2745 | (save-excursion | 2814 | (let ((tmpbuf (get-buffer-create " *tramp file transfer*"))) |
| 2746 | ;; Encode tmpfil into tmpbuf | 2815 | (save-excursion |
| 2747 | (tramp-message-for-buffer multi-method method user host | 2816 | ;; Encode tmpfil into tmpbuf |
| 2748 | 5 "Encoding region...") | 2817 | (tramp-message-for-buffer multi-method method user host |
| 2749 | (set-buffer tmpbuf) | 2818 | 5 "Encoding region...") |
| 2750 | (erase-buffer) | 2819 | (set-buffer tmpbuf) |
| 2751 | ;; Use encoding function or command. | 2820 | (erase-buffer) |
| 2752 | (if (and encoding-function | 2821 | ;; Use encoding function or command. |
| 2753 | (fboundp encoding-function)) | 2822 | (if (and encoding-function |
| 2754 | (progn | 2823 | (fboundp encoding-function)) |
| 2755 | (tramp-message-for-buffer | 2824 | (progn |
| 2756 | multi-method method user host | 2825 | (tramp-message-for-buffer |
| 2757 | 6 "Encoding region using function...") | 2826 | multi-method method user host |
| 2758 | (insert-file-contents-literally tmpfil) | 2827 | 6 "Encoding region using function...") |
| 2759 | ;; CCC. The following `let' is a workaround for | 2828 | (insert-file-contents-literally tmpfil) |
| 2760 | ;; the base64.el that comes with pgnus-0.84. If | 2829 | ;; CCC. The following `let' is a workaround for |
| 2761 | ;; both of the following conditions are | 2830 | ;; the base64.el that comes with pgnus-0.84. If |
| 2762 | ;; satisfied, it tries to write to a local file | 2831 | ;; both of the following conditions are |
| 2763 | ;; in default-directory, but at this point, | 2832 | ;; satisfied, it tries to write to a local file |
| 2764 | ;; default-directory is remote. | 2833 | ;; in default-directory, but at this point, |
| 2765 | ;; (CALL-PROCESS-REGION can't write to remote | 2834 | ;; default-directory is remote. |
| 2766 | ;; files, it seems.) The file in question is a | 2835 | ;; (CALL-PROCESS-REGION can't write to remote |
| 2767 | ;; tmp file anyway. | 2836 | ;; files, it seems.) The file in question is a |
| 2768 | (let ((default-directory (tramp-temporary-file-directory))) | 2837 | ;; tmp file anyway. |
| 2769 | (funcall encoding-function (point-min) (point-max))) | 2838 | (let ((default-directory |
| 2770 | (goto-char (point-max)) | 2839 | (tramp-temporary-file-directory))) |
| 2771 | (unless (bolp) | 2840 | (funcall encoding-function (point-min) (point-max))) |
| 2772 | (newline))) | 2841 | (goto-char (point-max)) |
| 2773 | (tramp-message-for-buffer multi-method method user host | 2842 | (unless (bolp) |
| 2774 | 6 "Encoding region using command...") | 2843 | (newline))) |
| 2775 | (unless (equal 0 | 2844 | (tramp-message-for-buffer |
| 2776 | (call-process | 2845 | multi-method method user host |
| 2777 | tramp-sh-program | 2846 | 6 "Encoding region using command...") |
| 2778 | tmpfil ;input = local tmp file | 2847 | (unless (equal 0 |
| 2779 | t ;output is current buffer | 2848 | (call-process |
| 2780 | nil ;don't redisplay | 2849 | tramp-sh-program |
| 2781 | "-c" | 2850 | tmpfil ;input = local tmp file |
| 2782 | encoding-command)) | 2851 | t ;output is current buffer |
| 2783 | (pop-to-buffer trampbuf) | 2852 | nil ;don't redisplay |
| 2784 | (error (concat "Cannot write to `%s', local encoding" | 2853 | "-c" |
| 2785 | " command `%s' failed") | 2854 | encoding-command)) |
| 2786 | filename encoding-command))) | 2855 | (pop-to-buffer trampbuf) |
| 2787 | ;; Send tmpbuf into remote decoding command which | 2856 | (error (concat "Cannot write to `%s', local encoding" |
| 2788 | ;; writes to remote file. Because this happens on the | 2857 | " command `%s' failed") |
| 2789 | ;; remote host, we cannot use the function. | 2858 | filename encoding-command))) |
| 2790 | (tramp-message-for-buffer | 2859 | ;; Send tmpbuf into remote decoding command which |
| 2791 | multi-method method user host | 2860 | ;; writes to remote file. Because this happens on the |
| 2792 | 5 "Decoding region into remote file %s..." filename) | 2861 | ;; remote host, we cannot use the function. |
| 2793 | (tramp-send-command | 2862 | (tramp-message-for-buffer |
| 2794 | multi-method method user host | 2863 | multi-method method user host |
| 2795 | (format "%s >%s <<'EOF'" | 2864 | 5 "Decoding region into remote file %s..." filename) |
| 2796 | decoding-command | 2865 | (tramp-send-command |
| 2797 | (tramp-shell-quote-argument path))) | 2866 | multi-method method user host |
| 2798 | (set-buffer tmpbuf) | 2867 | (format "%s >%s <<'EOF'" |
| 2799 | (tramp-message-for-buffer | 2868 | decoding-command |
| 2800 | multi-method method user host | 2869 | (tramp-shell-quote-argument path))) |
| 2801 | 6 "Sending data to remote host...") | 2870 | (set-buffer tmpbuf) |
| 2802 | (tramp-send-region multi-method method user host | 2871 | (tramp-message-for-buffer |
| 2803 | (point-min) (point-max)) | 2872 | multi-method method user host |
| 2804 | ;; wait for remote decoding to complete | 2873 | 6 "Sending data to remote host...") |
| 2805 | (tramp-message-for-buffer | 2874 | (tramp-send-region multi-method method user host |
| 2806 | multi-method method user host 6 "Sending end of data token...") | 2875 | (point-min) (point-max)) |
| 2807 | (tramp-send-command | 2876 | ;; wait for remote decoding to complete |
| 2808 | multi-method method user host "EOF") | 2877 | (tramp-message-for-buffer |
| 2809 | (tramp-message-for-buffer | 2878 | multi-method method user host |
| 2810 | multi-method method user host 6 | 2879 | 6 "Sending end of data token...") |
| 2811 | "Waiting for remote host to process data...") | 2880 | (tramp-send-command |
| 2812 | (set-buffer (tramp-get-buffer multi-method method user host)) | 2881 | multi-method method user host "EOF") |
| 2813 | (tramp-wait-for-output) | 2882 | (tramp-message-for-buffer |
| 2814 | (tramp-barf-unless-okay | 2883 | multi-method method user host 6 |
| 2815 | multi-method method user host nil nil 'file-error | 2884 | "Waiting for remote host to process data...") |
| 2816 | (concat "Couldn't write region to `%s'," | 2885 | (set-buffer (tramp-get-buffer multi-method method user host)) |
| 2817 | " decode using `%s' failed") | 2886 | (tramp-wait-for-output) |
| 2818 | filename decoding-command) | 2887 | (tramp-barf-unless-okay |
| 2819 | (tramp-message 5 "Decoding region into remote file %s...done" | 2888 | multi-method method user host nil nil 'file-error |
| 2820 | filename) | 2889 | (concat "Couldn't write region to `%s'," |
| 2821 | (kill-buffer tmpbuf)))) | 2890 | " decode using `%s' failed") |
| 2822 | (t | 2891 | filename decoding-command) |
| 2823 | (error | 2892 | (tramp-message 5 "Decoding region into remote file %s...done" |
| 2824 | (concat "Method `%s' should specify both encoding and " | 2893 | filename) |
| 2825 | "decoding command or an rcp program") | 2894 | (kill-buffer tmpbuf)))) |
| 2826 | method))) | 2895 | (t |
| 2827 | (delete-file tmpfil) | 2896 | (error |
| 2828 | (unless (equal curbuf (current-buffer)) | 2897 | (concat "Method `%s' should specify both encoding and " |
| 2829 | (error "Buffer has changed from `%s' to `%s'" | 2898 | "decoding command or an rcp program") |
| 2830 | curbuf (current-buffer))) | 2899 | method))) |
| 2831 | (when (eq visit t) | 2900 | (delete-file tmpfil) |
| 2832 | (set-visited-file-modtime)) | 2901 | (unless (equal curbuf (current-buffer)) |
| 2833 | ;; Make `last-coding-system-used' have the right value. | 2902 | (error "Buffer has changed from `%s' to `%s'" |
| 2834 | (when (boundp 'last-coding-system-used) | 2903 | curbuf (current-buffer))) |
| 2835 | (setq last-coding-system-used coding-system-used)) | 2904 | (when (eq visit t) |
| 2836 | (when (or (eq visit t) | 2905 | (set-visited-file-modtime)) |
| 2837 | (eq visit nil) | 2906 | ;; Make `last-coding-system-used' have the right value. |
| 2838 | (stringp visit)) | 2907 | (when (boundp 'last-coding-system-used) |
| 2839 | (message "Wrote %s" filename)))) | 2908 | (setq last-coding-system-used coding-system-used)) |
| 2909 | (when (or (eq visit t) | ||
| 2910 | (eq visit nil) | ||
| 2911 | (stringp visit)) | ||
| 2912 | (message "Wrote %s" filename))))) | ||
| 2840 | 2913 | ||
| 2841 | ;; Call down to the real handler. | 2914 | ;; Call down to the real handler. |
| 2842 | ;; Because EFS does not play nicely with TRAMP (both systems match an | 2915 | ;; Because EFS does not play nicely with TRAMP (both systems match an |
| @@ -2871,8 +2944,8 @@ This will break if COMMAND prints a newline, followed by the value of | |||
| 2871 | 2944 | ||
| 2872 | (defun tramp-run-real-handler (operation args) | 2945 | (defun tramp-run-real-handler (operation args) |
| 2873 | "Invoke normal file name handler for OPERATION. | 2946 | "Invoke normal file name handler for OPERATION. |
| 2874 | First arg specifies the OPERATION, remaining ARGS are passed to the | 2947 | First arg specifies the OPERATION, second arg is a list of arguments to |
| 2875 | OPERATION." | 2948 | pass to the OPERATION." |
| 2876 | (let ((inhibit-file-name-handlers | 2949 | (let ((inhibit-file-name-handlers |
| 2877 | (list 'tramp-file-name-handler | 2950 | (list 'tramp-file-name-handler |
| 2878 | (and (eq inhibit-file-name-operation operation) | 2951 | (and (eq inhibit-file-name-operation operation) |
| @@ -2880,17 +2953,15 @@ OPERATION." | |||
| 2880 | (inhibit-file-name-operation operation)) | 2953 | (inhibit-file-name-operation operation)) |
| 2881 | (apply operation args))) | 2954 | (apply operation args))) |
| 2882 | 2955 | ||
| 2883 | |||
| 2884 | ;; Main function. | 2956 | ;; Main function. |
| 2885 | ;;;###autoload | 2957 | ;;;###autoload |
| 2886 | (defun tramp-file-name-handler (operation &rest args) | 2958 | (defun tramp-file-name-handler (operation &rest args) |
| 2887 | "Invoke tramp file name handler. | 2959 | "Invoke tramp file name handler. |
| 2888 | Falls back to normal file name handler if no tramp file name handler exists." | 2960 | Falls back to normal file name handler if no tramp file name handler exists." |
| 2889 | (let ((fn (assoc operation tramp-file-name-handler-alist))) | 2961 | (let ((fn (assoc operation tramp-file-name-handler-alist))) |
| 2890 | ;(message "Handling %s using %s" operation fn) | ||
| 2891 | (if fn | 2962 | (if fn |
| 2892 | (save-match-data | 2963 | (catch 'tramp-forward-to-ange-ftp |
| 2893 | (apply (cdr fn) args)) | 2964 | (save-match-data (apply (cdr fn) args))) |
| 2894 | (tramp-run-real-handler operation args)))) | 2965 | (tramp-run-real-handler operation args)))) |
| 2895 | 2966 | ||
| 2896 | ;; Register in file name handler alist | 2967 | ;; Register in file name handler alist |
| @@ -2906,6 +2977,21 @@ Falls back to normal file name handler if no tramp file name handler exists." | |||
| 2906 | (setq file-name-handler-alist | 2977 | (setq file-name-handler-alist |
| 2907 | (cons jka (delete jka file-name-handler-alist))))) | 2978 | (cons jka (delete jka file-name-handler-alist))))) |
| 2908 | 2979 | ||
| 2980 | (defun tramp-invoke-ange-ftp (operation &rest args) | ||
| 2981 | "Invoke the Ange-FTP handler function and throw." | ||
| 2982 | (let ((ange-ftp-name-format | ||
| 2983 | (list (nth 0 tramp-file-name-structure) | ||
| 2984 | (nth 3 tramp-file-name-structure) | ||
| 2985 | (nth 2 tramp-file-name-structure) | ||
| 2986 | (nth 4 tramp-file-name-structure)))) | ||
| 2987 | (throw 'tramp-forward-to-ange-ftp | ||
| 2988 | (apply 'ange-ftp-hook-function operation args)))) | ||
| 2989 | |||
| 2990 | (defun tramp-ange-ftp-file-name-p (multi-method method) | ||
| 2991 | "Check if it's a filename that should be forwarded to Ange-FTP." | ||
| 2992 | (and (null multi-method) (string= method tramp-ftp-method))) | ||
| 2993 | |||
| 2994 | |||
| 2909 | ;;; Interactions with other packages: | 2995 | ;;; Interactions with other packages: |
| 2910 | 2996 | ||
| 2911 | ;; -- complete.el -- | 2997 | ;; -- complete.el -- |
| @@ -2913,52 +2999,52 @@ Falls back to normal file name handler if no tramp file name handler exists." | |||
| 2913 | ;; This function contributed by Ed Sabol | 2999 | ;; This function contributed by Ed Sabol |
| 2914 | (defun tramp-handle-expand-many-files (name) | 3000 | (defun tramp-handle-expand-many-files (name) |
| 2915 | "Like `PC-expand-many-files' for tramp files." | 3001 | "Like `PC-expand-many-files' for tramp files." |
| 2916 | (save-match-data | 3002 | (with-parsed-tramp-file-name name nil |
| 2917 | (if (or (string-match "\\*" name) | 3003 | (when (tramp-ange-ftp-file-name-p multi-method method) |
| 2918 | (string-match "\\?" name) | 3004 | (tramp-invoke-ange-ftp 'expand-many-files name)) |
| 2919 | (string-match "\\[.*\\]" name)) | 3005 | (save-match-data |
| 2920 | (save-excursion | 3006 | (if (or (string-match "\\*" name) |
| 2921 | ;; Dissect NAME. | 3007 | (string-match "\\?" name) |
| 2922 | (let* ((v (tramp-dissect-file-name name)) | 3008 | (string-match "\\[.*\\]" name)) |
| 2923 | (multi-method (tramp-file-name-multi-method v)) | 3009 | (save-excursion |
| 2924 | (method (tramp-file-name-method v)) | 3010 | ;; Dissect NAME. |
| 2925 | (user (tramp-file-name-user v)) | 3011 | (let (bufstr) |
| 2926 | (host (tramp-file-name-host v)) | 3012 | ;; Perhaps invoke Ange-FTP. |
| 2927 | (path (tramp-file-name-path v)) | 3013 | (when (string= method tramp-ftp-method) |
| 2928 | bufstr) | 3014 | (signal 'tramp-run-ange-ftp (list 0))) |
| 2929 | ;; CCC: To do it right, we should quote certain characters | 3015 | ;; CCC: To do it right, we should quote certain characters |
| 2930 | ;; in the file name, but since the echo command is going to | 3016 | ;; in the file name, but since the echo command is going to |
| 2931 | ;; break anyway when there are spaces in the file names, we | 3017 | ;; break anyway when there are spaces in the file names, we |
| 2932 | ;; don't bother. | 3018 | ;; don't bother. |
| 2933 | ;;-(let ((comint-file-name-quote-list | 3019 | ;;-(let ((comint-file-name-quote-list |
| 2934 | ;;- (set-difference tramp-file-name-quote-list | 3020 | ;;- (set-difference tramp-file-name-quote-list |
| 2935 | ;;- '(?\* ?\? ?[ ?])))) | 3021 | ;;- '(?\* ?\? ?[ ?])))) |
| 2936 | ;;- (tramp-send-command | 3022 | ;;- (tramp-send-command |
| 2937 | ;;- multi-method method user host | 3023 | ;;- multi-method method user host |
| 2938 | ;;- (format "echo %s" (comint-quote-filename path))) | 3024 | ;;- (format "echo %s" (comint-quote-filename path))) |
| 2939 | ;;- (tramp-wait-for-output)) | 3025 | ;;- (tramp-wait-for-output)) |
| 2940 | (tramp-send-command multi-method method user host | 3026 | (tramp-send-command multi-method method user host |
| 2941 | (format "echo %s" path)) | 3027 | (format "echo %s" path)) |
| 2942 | (tramp-wait-for-output) | 3028 | (tramp-wait-for-output) |
| 2943 | (setq bufstr (buffer-substring (point-min) | 3029 | (setq bufstr (buffer-substring (point-min) |
| 2944 | (tramp-line-end-position))) | 3030 | (tramp-line-end-position))) |
| 2945 | (goto-char (point-min)) | 3031 | (goto-char (point-min)) |
| 2946 | (if (string-equal path bufstr) | 3032 | (if (string-equal path bufstr) |
| 2947 | nil | 3033 | nil |
| 2948 | (insert "(\"") | 3034 | (insert "(\"") |
| 2949 | (while (search-forward " " nil t) | 3035 | (while (search-forward " " nil t) |
| 2950 | (delete-backward-char 1) | 3036 | (delete-backward-char 1) |
| 2951 | (insert "\" \"")) | 3037 | (insert "\" \"")) |
| 2952 | (goto-char (point-max)) | 3038 | (goto-char (point-max)) |
| 2953 | (delete-backward-char 1) | 3039 | (delete-backward-char 1) |
| 2954 | (insert "\")") | 3040 | (insert "\")") |
| 2955 | (goto-char (point-min)) | 3041 | (goto-char (point-min)) |
| 2956 | (mapcar | 3042 | (mapcar |
| 2957 | (function (lambda (x) | 3043 | (function (lambda (x) |
| 2958 | (tramp-make-tramp-file-name multi-method method | 3044 | (tramp-make-tramp-file-name multi-method method |
| 2959 | user host x))) | 3045 | user host x))) |
| 2960 | (read (current-buffer)))))) | 3046 | (read (current-buffer)))))) |
| 2961 | (list (tramp-handle-expand-file-name name))))) | 3047 | (list (tramp-handle-expand-file-name name)))))) |
| 2962 | 3048 | ||
| 2963 | ;; Check for complete.el and override PC-expand-many-files if appropriate. | 3049 | ;; Check for complete.el and override PC-expand-many-files if appropriate. |
| 2964 | (eval-when-compile | 3050 | (eval-when-compile |
| @@ -3202,20 +3288,24 @@ file exists and nonzero exit status otherwise." | |||
| 3202 | ((string-match "^~root$" (buffer-string)) | 3288 | ((string-match "^~root$" (buffer-string)) |
| 3203 | (setq shell | 3289 | (setq shell |
| 3204 | (or (tramp-find-executable multi-method method user host | 3290 | (or (tramp-find-executable multi-method method user host |
| 3205 | "bash" tramp-remote-path t) | 3291 | "bash" tramp-remote-path t) |
| 3206 | (tramp-find-executable multi-method method user host | 3292 | (tramp-find-executable multi-method method user host |
| 3207 | "ksh" tramp-remote-path t))) | 3293 | "ksh" tramp-remote-path t))) |
| 3208 | (unless shell | 3294 | (unless shell |
| 3209 | (error "Couldn't find a shell which groks tilde expansion")) | 3295 | (error "Couldn't find a shell which groks tilde expansion")) |
| 3210 | ;; Hack: avoid reading of ~/.bashrc. What we should do is have an | 3296 | ;; Find arguments for this shell. |
| 3211 | ;; alist for extra args to give to each shell... | 3297 | (let ((alist tramp-sh-extra-args) |
| 3212 | (when (string-match "/bash\\'" shell) | 3298 | item extra-args) |
| 3213 | (setq shell (concat shell " --norc"))) | 3299 | (while (and alist (null extra-args)) |
| 3300 | (setq item (pop alist)) | ||
| 3301 | (when (string-match (car item) shell) | ||
| 3302 | (setq extra-args (cdr item)))) | ||
| 3303 | (when extra-args (setq shell (concat shell " " extra-args)))) | ||
| 3214 | (tramp-message | 3304 | (tramp-message |
| 3215 | 5 "Starting remote shell `%s' for tilde expansion..." shell) | 3305 | 5 "Starting remote shell `%s' for tilde expansion..." shell) |
| 3216 | (tramp-send-command | 3306 | (tramp-send-command |
| 3217 | multi-method method user host | 3307 | multi-method method user host |
| 3218 | (concat "PS1='$ ' ; exec " shell)) | 3308 | (concat "PS1='$ ' ; exec " shell)) ; |
| 3219 | (unless (tramp-wait-for-regexp | 3309 | (unless (tramp-wait-for-regexp |
| 3220 | (get-buffer-process (current-buffer)) | 3310 | (get-buffer-process (current-buffer)) |
| 3221 | 60 (format "\\(\\$ *\\|\\(%s\\)\\'\\)" shell-prompt-pattern)) | 3311 | 60 (format "\\(\\$ *\\|\\(%s\\)\\'\\)" shell-prompt-pattern)) |
| @@ -3236,7 +3326,7 @@ file exists and nonzero exit status otherwise." | |||
| 3236 | shell (buffer-name)))) | 3326 | shell (buffer-name)))) |
| 3237 | (tramp-message 5 "Waiting for remote `%s' to start up...done" shell)) | 3327 | (tramp-message 5 "Waiting for remote `%s' to start up...done" shell)) |
| 3238 | (t (tramp-message 5 "Remote `%s' groks tilde expansion, good" | 3328 | (t (tramp-message 5 "Remote `%s' groks tilde expansion, good" |
| 3239 | (tramp-get-remote-sh multi-method method)))))) | 3329 | (tramp-get-remote-sh multi-method method)))))) |
| 3240 | 3330 | ||
| 3241 | (defun tramp-check-ls-command (multi-method method user host cmd) | 3331 | (defun tramp-check-ls-command (multi-method method user host cmd) |
| 3242 | "Checks whether the given `ls' executable groks `-n'. | 3332 | "Checks whether the given `ls' executable groks `-n'. |
| @@ -4486,21 +4576,37 @@ remote path name." | |||
| 4486 | (save-match-data | 4576 | (save-match-data |
| 4487 | (unless (string-match (nth 0 tramp-file-name-structure) name) | 4577 | (unless (string-match (nth 0 tramp-file-name-structure) name) |
| 4488 | (error "Not a tramp file name: %s" name)) | 4578 | (error "Not a tramp file name: %s" name)) |
| 4489 | (setq method (or (match-string (nth 1 tramp-file-name-structure) name) | 4579 | (setq method (match-string (nth 1 tramp-file-name-structure) name)) |
| 4490 | tramp-default-method)) | 4580 | (if (and method (member method tramp-multi-methods)) |
| 4491 | (if (member method tramp-multi-methods) | ||
| 4492 | ;; If it's a multi method, the file name structure contains | 4581 | ;; If it's a multi method, the file name structure contains |
| 4493 | ;; arrays of method, user and host. | 4582 | ;; arrays of method, user and host. |
| 4494 | (tramp-dissect-multi-file-name name) | 4583 | (tramp-dissect-multi-file-name name) |
| 4495 | ;; Normal method. | 4584 | ;; Normal method. First, find out default method. |
| 4496 | (make-tramp-file-name | 4585 | (let ((user (match-string (nth 2 tramp-file-name-structure) name)) |
| 4497 | :multi-method nil | 4586 | (host (match-string (nth 3 tramp-file-name-structure) name)) |
| 4498 | :method method | 4587 | (path (match-string (nth 4 tramp-file-name-structure) name))) |
| 4499 | :user (or (match-string (nth 2 tramp-file-name-structure) name) | 4588 | (when (not method) |
| 4500 | nil) | 4589 | (setq method (tramp-find-default-method user host))) |
| 4501 | :host (match-string (nth 3 tramp-file-name-structure) name) | 4590 | (make-tramp-file-name |
| 4502 | :path (match-string (nth 4 tramp-file-name-structure) name)))))) | 4591 | :multi-method nil |
| 4503 | 4592 | :method method | |
| 4593 | :user (or user nil) | ||
| 4594 | :host host | ||
| 4595 | :path path)))))) | ||
| 4596 | |||
| 4597 | (defun tramp-find-default-method (user host) | ||
| 4598 | "Look up the right method to use in `tramp-default-method-alist'." | ||
| 4599 | (let ((choices tramp-default-method-alist) | ||
| 4600 | (method tramp-default-method) | ||
| 4601 | item) | ||
| 4602 | (while choices | ||
| 4603 | (setq item (pop choices)) | ||
| 4604 | (when (and (string-match (nth 0 item) host) | ||
| 4605 | (string-match (nth 1 item) (or user ""))) | ||
| 4606 | (setq method (nth 2 item)) | ||
| 4607 | (setq choices nil))) | ||
| 4608 | method)) | ||
| 4609 | |||
| 4504 | ;; HHH: Not Changed. Multi method. Will probably not handle the case where | 4610 | ;; HHH: Not Changed. Multi method. Will probably not handle the case where |
| 4505 | ;; a user name is not provided in the "file name" very well. | 4611 | ;; a user name is not provided in the "file name" very well. |
| 4506 | (defun tramp-dissect-multi-file-name (name) | 4612 | (defun tramp-dissect-multi-file-name (name) |
| @@ -4581,14 +4687,18 @@ remote path name." | |||
| 4581 | (incf i))) | 4687 | (incf i))) |
| 4582 | (concat prefix hops path))) | 4688 | (concat prefix hops path))) |
| 4583 | 4689 | ||
| 4584 | ;; HHH: Changed. Handles the case where no user name is given in the | ||
| 4585 | ;; file name. | ||
| 4586 | (defun tramp-make-rcp-program-file-name (user host path) | 4690 | (defun tramp-make-rcp-program-file-name (user host path) |
| 4587 | "Create a file name suitable to be passed to `rcp'." | 4691 | "Create a file name suitable to be passed to `rcp'." |
| 4588 | (if user | 4692 | (if user |
| 4589 | (format "%s@%s:%s" user host path) | 4693 | (format "%s@%s:%s" user host path) |
| 4590 | (format "%s:%s" host path))) | 4694 | (format "%s:%s" host path))) |
| 4591 | 4695 | ||
| 4696 | (defun tramp-make-ange-ftp-file-name (user host path) | ||
| 4697 | "Given user, host, and path, return an Ange-FTP filename." | ||
| 4698 | (if user | ||
| 4699 | (format "/%s@%s:%s" user host path) | ||
| 4700 | (format "/%s:%s" host path))) | ||
| 4701 | |||
| 4592 | (defun tramp-method-out-of-band-p (multi-method method) | 4702 | (defun tramp-method-out-of-band-p (multi-method method) |
| 4593 | "Return t if this is an out-of-band method, nil otherwise. | 4703 | "Return t if this is an out-of-band method, nil otherwise. |
| 4594 | It is important to check for this condition, since it is not possible | 4704 | It is important to check for this condition, since it is not possible |
| @@ -5047,6 +5157,7 @@ TRAMP. | |||
| 5047 | 5157 | ||
| 5048 | ;;; TODO: | 5158 | ;;; TODO: |
| 5049 | 5159 | ||
| 5160 | ;; * Revise the comments near the beginning of the file. | ||
| 5050 | ;; * Cooperate with PCL-CVS. It uses start-process, which doesn't | 5161 | ;; * Cooperate with PCL-CVS. It uses start-process, which doesn't |
| 5051 | ;; work for remote files. | 5162 | ;; work for remote files. |
| 5052 | ;; * Allow /[method/user@host:port] syntax for the ssh "-p" argument. | 5163 | ;; * Allow /[method/user@host:port] syntax for the ssh "-p" argument. |