@end defun
@defun files-equal-p file1 file2
-This function return @code{t} if the files @var{file1} and @var{file2} name
-the same file.
-Comparison is made with the @code{file-attributes} of both files.
+This function returns @code{t} if the files @var{file1} and
+@var{file2} name the same file. Two ordinary files are considered to
+be the same if the function @code{file-attributes} (@xref{File
+Attributes}) returns @code{equal} values for them.
@end defun
@defun file-subdir-of-p dir1 dir2
-This function return @code{t} if directory @var{dir1} is a subdirectory
-of @var{dir2} or if @var{dir1} and @var{dir2} are the same directory.
-Arguments @var{dir1} and @var{dir2} must be existing directories,
-otherwise, return nil.
-Check is done by building a directory name based on equality of differents
-components of both directory names, if this resulting directory name
-is equal to @var{dir2}, we assume directory @var{dir1}
-is a subdirectory of @var{dir2}.
+This function returns @code{t} if directory @var{dir1} is a
+subdirectory of @var{dir2}, or if @var{dir1} and @var{dir2} are the
+same directory. It compares the @code{file-truename} values of the
+two directories (@pxref{Truenames}). If either @var{dir1} or
+@var{dir2} do not name existing directories, the return value is
+@code{nil}.
@end defun
@node Truenames
(delete-directory-internal directory)))))
(defun files-equal-p (file1 file2)
- "Return non-nil if FILE1 and FILE2 name the same file."
+ "Return non-nil if FILE1 and FILE2 name the same file.
+Ordinary files are considered to be the same if `file-attributes'
+returns `equal' values for them."
(let ((handler (or (find-file-name-handler file1 'files-equal-p)
(find-file-name-handler file2 'files-equal-p))))
(if handler
(defun file-subdir-of-p (dir1 dir2)
"Return non-nil if DIR1 is a subdirectory of DIR2.
-Note that a directory is treated by this function as a subdirectory of itself.
-This function only works when its two arguments already exist,
-when they don't, it returns nil."
+A directory is considered to be a subdirectory of itself.
+Return nil if DIR1 or DIR2 are not existing directories."
(let ((handler (or (find-file-name-handler dir1 'file-subdir-of-p)
(find-file-name-handler dir2 'file-subdir-of-p))))
(if handler
(funcall handler 'file-subdir-of-p dir1 dir2)
(when (and (file-directory-p dir1)
(file-directory-p dir2))
- (loop with f1 = (file-truename dir1)
- with f2 = (file-truename dir2)
- with ls1 = (or (split-string f1 "/" t) (list "/"))
- with ls2 = (or (split-string f2 "/" t) (list "/"))
- for p = (string-match "^/" f1)
- for i in ls1
- for j in ls2
- when (string= i j)
- concat (if p (concat "/" i) (concat i "/"))
- into root
- finally return
- (files-equal-p (file-truename root) f2))))))
+ (setq dir1 (file-truename dir1)
+ dir2 (file-truename dir2))
+ (let ((ls1 (or (split-string dir1 "/" t) '("/")))
+ (ls2 (or (split-string dir2 "/" t) '("/")))
+ (root (if (string-match "\\`/" dir1) "/" ""))
+ (mismatch nil))
+ (while (and ls1 ls2 (not mismatch))
+ (if (string-equal (car ls1) (car ls2))
+ (setq root (concat root (car ls1) "/"))
+ (setq mismatch t))
+ (setq ls1 (cdr ls1)
+ ls2 (cdr ls2)))
+ (unless mismatch
+ (files-equal-p (file-truename root) dir2)))))))
(defun copy-directory (directory newname &optional keep-time parents copy-contents)
"Copy DIRECTORY to NEWNAME. Both args must be strings.