Commit ce0da8a4 authored by Michael Albinus's avatar Michael Albinus

Rework time-* functions in Tramp

* doc/misc/emacs-mime.texi (time-date): Add time-equal-p.

* lisp/net/tramp-compat.el (tramp-compat-time-equal-p): New defsubst.

* lisp/net/tramp.el (tramp-file-name-handler): Remove `debug'
error handler.
(tramp-half-a-year): Remove.
(tramp-time-dont-know, tramp-time-doesnt-exist): New defconst.
(tramp-time-diff): Remove compat code.
(tramp-handle-set-visited-file-modtime)
(tramp-handle-verify-visited-file-modtime):
* lisp/net/tramp-adb.el (tramp-do-parse-file-attributes-with-ls)
(tramp-adb-handle-set-file-times):
* lisp/net/tramp-sh.el (tramp-do-file-attributes-with-ls)
(tramp-sh-handle-set-visited-file-modtime)
(tramp-sh-handle-verify-visited-file-modtime)
(tramp-sh-handle-set-file-times)
(tramp-sh-handle-file-newer-than-file-p):
Use `tramp-time-dont-know', `tramp-time-doesnt-exist' and
`tramp-compat-time-equal-p'.
(tramp-sh-handle-verify-visited-file-modtime): Simplify check.

* lisp/net/tramp-smb.el (tramp-smb-handle-file-attributes)
(tramp-smb-read-file-entry): Use `tramp-time-dont-know'.
(tramp-smb-handle-insert-directory): Adapt half-a-year check.

* src/editfns.c (Ftime_equal_p): Adapt docstring.

* test/lisp/net/tramp-tests.el
(tramp-test19-directory-files-and-attributes)
(tramp-test22-file-times): Use `tramp-compat-time-equal-p' and
`tramp-time-dont-know'.
(tramp-test23-visited-file-modtime): Extend test.
parent 9284e226
......@@ -1561,6 +1561,9 @@ Here's a bunch of time/date/second/day examples:
(time-less-p '(13818 19266) '(13818 19145))
@result{} nil
(time-equal-p '(13818 19266) '(13818 19145))
@result{} nil
(time-subtract '(13818 19266) '(13818 19145))
@result{} (0 121)
......@@ -1641,6 +1644,10 @@ return a ``zero'' time.
Take two times and say whether the first time is less (i.e., earlier)
than the second time. (This is a built-in function.)
@item time-equal-p
Check, whether two time values are equal. The time values must not be
in the same format. (This is a built-in function.)
@item time-since
Take a time and return a time saying how long it was since that time.
......
......@@ -411,9 +411,9 @@ pass to the OPERATION."
;; no way to handle numeric ids in Androids ash
(if (eq id-format 'integer) 0 uid)
(if (eq id-format 'integer) 0 gid)
'(0 0) ; atime
tramp-time-dont-know ; atime
(date-to-time date) ; mtime
'(0 0) ; ctime
tramp-time-dont-know ; ctime
size
mod-string
;; fake
......@@ -725,7 +725,9 @@ But handle the case, if the \"test\" command is not available."
(with-parsed-tramp-file-name filename nil
(tramp-flush-file-properties v (file-name-directory localname))
(tramp-flush-file-properties v localname)
(let ((time (if (or (null time) (equal time '(0 0)))
(let ((time (if (or (null time)
(tramp-compat-time-equal-p time tramp-time-doesnt-exist)
(tramp-compat-time-equal-p time tramp-time-dont-know))
(current-time)
time)))
(tramp-adb-send-command-and-check
......
......@@ -118,9 +118,8 @@ Returns DEFAULT if not set."
(and (consp value)
(or (null remote-file-name-inhibit-cache)
(and (integerp remote-file-name-inhibit-cache)
(<=
(tramp-time-diff (current-time) (car value))
remote-file-name-inhibit-cache))
(<= (tramp-time-diff (current-time) (car value))
remote-file-name-inhibit-cache))
(and (consp remote-file-name-inhibit-cache)
(time-less-p
remote-file-name-inhibit-cache (car value)))))
......
......@@ -247,6 +247,14 @@ If NAME is a remote file name, the local part of NAME is unquoted."
(funcall handler 'exec-path)
exec-path)))))
;; `time-equal-p' has appeared in Emacs 27.1.
(if (fboundp 'time-equal-p)
(defalias 'tramp-compat-time-equal-p 'time-equal-p)
(defsubst tramp-compat-time-equal-p (t1 t2)
"Return non-nil if time value T1 is equal to time value T2.
A nil value for either argument stands for the current time."
(equal (or t1 (current-time)) (or t2 (current-time)))))
(add-hook 'tramp-unload-hook
(lambda ()
(unload-feature 'tramp-loaddefs 'force)
......
......@@ -650,7 +650,7 @@ Return nil for null BYTE-ARRAY."
(cond
((and (consp message) (characterp (car message)))
(format "%S" (tramp-gvfs-dbus-byte-array-to-string message)))
((and (consp message) (not (consp (cdr message))))
((and (consp message) (atom (cdr message)))
(cons (tramp-gvfs-stringify-dbus-message (car message))
(tramp-gvfs-stringify-dbus-message (cdr message))))
((consp message)
......
......@@ -1348,13 +1348,10 @@ component is used as the target of the symlink."
res-uid
;; 3. File gid.
res-gid
;; 4. Last access time, as a list of integers. Normally
;; this would be in the same format as `current-time', but
;; the subseconds part is not currently implemented, and
;; (0 0) denotes an unknown time.
;; 5. Last modification time, likewise.
;; 6. Last status change time, likewise.
'(0 0) '(0 0) '(0 0) ;CCC how to find out?
;; 4. Last access time.
;; 5. Last modification time.
;; 6. Last status change time.
tramp-time-dont-know tramp-time-dont-know tramp-time-dont-know
;; 7. Size in bytes (-1, if number is out of range).
res-size
;; 8. File modes, as a string of ten letters or dashes as in ls -l.
......@@ -1420,13 +1417,10 @@ component is used as the target of the symlink."
(with-parsed-tramp-file-name f nil
(let* ((remote-file-name-inhibit-cache t)
(attr (file-attributes f))
;; '(-1 65535) means file doesn't exists yet.
(modtime (or (tramp-compat-file-attribute-modification-time attr)
'(-1 65535))))
tramp-time-doesnt-exist)))
(setq coding-system-used last-coding-system-used)
;; We use '(0 0) as a don't-know value. See also
;; `tramp-do-file-attributes-with-ls'.
(if (not (equal modtime '(0 0)))
(if (not (tramp-compat-time-equal-p modtime tramp-time-dont-know))
(tramp-run-real-handler 'set-visited-file-modtime (list modtime))
(progn
(tramp-send-command
......@@ -1455,7 +1449,7 @@ of."
;; recorded last modification time, or there is no established
;; connection.
(if (or (not f)
(eq (visited-file-modtime) 0)
(zerop (visited-file-modtime))
(not (file-remote-p f nil 'connected)))
t
(with-parsed-tramp-file-name f nil
......@@ -1466,16 +1460,10 @@ of."
(cond
;; File exists, and has a known modtime.
((and attr (not (equal modtime '(0 0))))
(< (abs (tramp-time-diff
modtime
;; For compatibility, deal with both the old
;; (HIGH . LOW) and the new (HIGH LOW) return
;; values of `visited-file-modtime'.
(if (atom (cdr mt))
(list (car mt) (cdr mt))
mt)))
2))
((and attr
(not
(tramp-compat-time-equal-p modtime tramp-time-dont-know)))
(< (abs (tramp-time-diff modtime mt)) 2))
;; Modtime has the don't know value.
(attr
(tramp-send-command
......@@ -1491,7 +1479,7 @@ of."
v localname "visited-file-modtime-ild" "")))
;; If file does not exist, say it is not modified if and
;; only if that agrees with the buffer's record.
(t (equal mt '(-1 65535))))))))))
(t (tramp-compat-time-equal-p mt tramp-time-doesnt-exist)))))))))
(defun tramp-sh-handle-set-file-modes (filename mode)
"Like `set-file-modes' for Tramp files."
......@@ -1510,9 +1498,12 @@ of."
(when (tramp-get-remote-touch v)
(tramp-flush-file-properties v (file-name-directory localname))
(tramp-flush-file-properties v localname)
(let ((time (if (or (null time) (equal time '(0 0)))
(current-time)
time)))
(let ((time
(if (or (null time)
(tramp-compat-time-equal-p time tramp-time-doesnt-exist)
(tramp-compat-time-equal-p time tramp-time-dont-know))
(current-time)
time)))
(tramp-send-command-and-check
v (format
"env TZ=UTC %s %s %s"
......@@ -1685,11 +1676,13 @@ be non-negative integers."
(fa2 (file-attributes file2)))
(if (and
(not
(equal (tramp-compat-file-attribute-modification-time fa1)
'(0 0)))
(tramp-compat-time-equal-p
(tramp-compat-file-attribute-modification-time fa1)
tramp-time-dont-know))
(not
(equal (tramp-compat-file-attribute-modification-time fa2)
'(0 0))))
(tramp-compat-time-equal-p
(tramp-compat-file-attribute-modification-time fa2)
tramp-time-dont-know)))
(> 0 (tramp-time-diff
(tramp-compat-file-attribute-modification-time fa2)
(tramp-compat-file-attribute-modification-time fa1)))
......
......@@ -817,18 +817,18 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
;; Check result.
(when entry
(list (and (string-match "d" (nth 1 entry))
t) ;0 file type
-1 ;1 link count
uid ;2 uid
gid ;3 gid
'(0 0) ;4 atime
(nth 3 entry) ;5 mtime
'(0 0) ;6 ctime
(nth 2 entry) ;7 size
(nth 1 entry) ;8 mode
nil ;9 gid weird
inode ;10 inode number
device)))))))) ;11 file system number
t) ;0 file type
-1 ;1 link count
uid ;2 uid
gid ;3 gid
tramp-time-dont-know ;4 atime
(nth 3 entry) ;5 mtime
tramp-time-dont-know ;6 ctime
(nth 2 entry) ;7 size
(nth 1 entry) ;8 mode
nil ;9 gid weird
inode ;10 inode number
device)))))))) ;11 file system number
(defun tramp-smb-do-file-attributes-with-stat (vec &optional id-format)
"Implement `file-attributes' for Tramp files using stat command."
......@@ -1085,8 +1085,9 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
(or (tramp-compat-file-attribute-group-id attr) "nogroup")
(or (tramp-compat-file-attribute-size attr) (nth 2 x))
(format-time-string
(if (time-less-p (time-subtract (current-time) (nth 3 x))
tramp-half-a-year)
(if (time-less-p
;; Half a year.
(time-since (nth 3 x)) (days-to-time 183))
"%b %e %R"
"%b %e %Y")
(nth 3 x))))) ; date
......@@ -1816,7 +1817,7 @@ Result is the list (LOCALNAME MODE SIZE MTIME)."
sec min hour day
(cdr (assoc (downcase month) parse-time-months))
year)
'(0 0)))
tramp-time-dont-know))
(list localname mode size mtime))))
(defun tramp-smb-get-cifs-capabilities (vec)
......
......@@ -3602,13 +3602,11 @@ support symbolic links."
(buffer-name)))
(unless time-list
(let ((remote-file-name-inhibit-cache t))
;; '(-1 65535) means file doesn't exists yet.
(setq time-list
(or (tramp-compat-file-attribute-modification-time
(file-attributes (buffer-file-name)))
'(-1 65535)))))
;; We use '(0 0) as a don't-know value.
(unless (equal time-list '(0 0))
tramp-time-doesnt-exist))))
(unless (tramp-compat-time-equal-p time-list tramp-time-dont-know)
(tramp-run-real-handler 'set-visited-file-modtime (list time-list))))
(defun tramp-handle-verify-visited-file-modtime (&optional buf)
......@@ -3634,21 +3632,14 @@ of."
(cond
;; File exists, and has a known modtime.
((and attr (not (equal modtime '(0 0))))
(< (abs (tramp-time-diff
modtime
;; For compatibility, deal with both the old
;; (HIGH . LOW) and the new (HIGH LOW) return
;; values of `visited-file-modtime'.
(if (atom (cdr mt))
(list (car mt) (cdr mt))
mt)))
2))
((and attr
(not (tramp-compat-time-equal-p modtime tramp-time-dont-know)))
(< (abs (tramp-time-diff modtime mt)) 2))
;; Modtime has the don't know value.
(attr t)
;; If file does not exist, say it is not modified if and
;; only if that agrees with the buffer's record.
(t (equal mt '(-1 65535)))))))))
(t (tramp-compat-time-equal-p mt tramp-time-doesnt-exist))))))))
;; This is used in tramp-gvfs.el and tramp-sh.el.
(defconst tramp-gio-events
......@@ -4531,17 +4522,19 @@ Invokes `password-read' if available, `read-passwd' else."
:host ,host-port :port ,method))
(password-cache-remove (tramp-make-tramp-file-name vec 'noloc 'nohop))))
;; Snarfed code from time-date.el.
;;;###tramp-autoload
(defconst tramp-time-dont-know '(0 0 0 1000)
"An invalid time value, used as \"Don’t know\" value.")
(defconst tramp-half-a-year '(241 17024)
"Evaluated by \"(days-to-time 183)\".")
;;;###tramp-autoload
(defconst tramp-time-doesnt-exist '(-1 65535)
"An invalid time value, used as \"Doesn’t exist\" value.")
;;;###tramp-autoload
(defun tramp-time-diff (t1 t2)
"Return the difference between the two times, in seconds.
T1 and T2 are time values (as returned by `current-time' for example)."
;; Starting with Emacs 25.1, we could change this to use `time-subtract'.
(float-time (tramp-compat-funcall 'subtract-time t1 t2)))
(float-time (time-subtract t1 t2)))
(defun tramp-unquote-shell-quote-argument (s)
"Remove quotation prefix \"/:\" from string S, and quote it then for shell."
......
......@@ -1677,7 +1677,9 @@ See `current-time-string' for the various forms of a time value. */)
}
DEFUN ("time-equal-p", Ftime_equal_p, Stime_equal_p, 2, 2, 0,
doc: /* Return non-nil if T1 and T2 are equal time values. */)
doc: /* Return non-nil if T1 and T2 are equal time values.
A nil value for either argument stands for the current time.
See `current-time-string' for the various forms of a time value. */)
(Lisp_Object t1, Lisp_Object t2)
{
return time_cmp (t1, t2) == 0 ? Qt : Qnil;
......
......@@ -2882,16 +2882,17 @@ This tests also `file-readable-p', `file-regular-p' and
;; able to return the date correctly. They say "don't know".
(dolist (elt attr)
(unless
(zerop
(float-time
(nth 5 (file-attributes
(expand-file-name (car elt) tmp-name2)))))
(tramp-compat-time-equal-p
(nth
5 (file-attributes (expand-file-name (car elt) tmp-name2)))
tramp-time-dont-know)
(should
(equal (file-attributes (expand-file-name (car elt) tmp-name2))
(cdr elt)))))
(setq attr (directory-files-and-attributes tmp-name2 'full))
(dolist (elt attr)
(unless (zerop (float-time (nth 5 (file-attributes (car elt)))))
(unless (tramp-compat-time-equal-p
(nth 5 (file-attributes (car elt))) tramp-time-dont-know)
(should
(equal (file-attributes (car elt)) (cdr elt)))))
(setq attr (directory-files-and-attributes tmp-name2 nil "^b"))
......@@ -3215,14 +3216,13 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(write-region "foo" nil tmp-name1)
(should (file-exists-p tmp-name1))
(should (consp (nth 5 (file-attributes tmp-name1))))
;; A zero timestamp means don't know, and will be replaced by
;; `current-time'. Therefore, use timestamp 1. Skip the
;; test, if the remote handler is not able to set the
;; correct time.
;; Skip the test, if the remote handler is not able to set
;; the correct time.
(skip-unless (set-file-times tmp-name1 (seconds-to-time 1)))
;; Dumb remote shells without perl(1) or stat(1) are not
;; able to return the date correctly. They say "don't know".
(unless (zerop (float-time (nth 5 (file-attributes tmp-name1))))
(unless (tramp-compat-time-equal-p
(nth 5 (file-attributes tmp-name1)) tramp-time-dont-know)
(should
(equal (nth 5 (file-attributes tmp-name1)) (seconds-to-time 1)))
(write-region "bla" nil tmp-name2)
......@@ -3252,6 +3252,14 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(should (verify-visited-file-modtime))
(set-visited-file-modtime (seconds-to-time 1))
(should (verify-visited-file-modtime))
(should (= 1 (float-time (visited-file-modtime))))
;; Checks with deleted file.
(delete-file tmp-name)
(dired-uncache tmp-name)
(should (verify-visited-file-modtime))
(set-visited-file-modtime (seconds-to-time 1))
(should (verify-visited-file-modtime))
(should (= 1 (float-time (visited-file-modtime))))))
;; Cleanup.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment