Function: require-with-check
require-with-check is a byte-compiled function defined in files.el.gz.
Signature
(require-with-check FEATURE &optional FILENAME NOERROR)
Documentation
If FEATURE is not already loaded, load it from FILENAME.
This is like require except if FEATURE is already a member of the list
`features’, then check if it was provided by a different file than the
one that is about to be loaded now (presumably because load-path has
been changed since FILENAME was loaded). If that is the case, either
signal an error (the default), or forcibly reload the new file (if
NOERROR is equal to reload), or otherwise emit a warning.
Probably introduced at or before Emacs version 30.1.
Source Code
;; Defined in /usr/src/emacs/lisp/files.el.gz
(defun require-with-check (feature &optional filename noerror)
"If FEATURE is not already loaded, load it from FILENAME.
This is like `require' except if FEATURE is already a member of the list
`features’, then check if it was provided by a different file than the
one that is about to be loaded now (presumably because `load-path' has
been changed since FILENAME was loaded). If that is the case, either
signal an error (the default), or forcibly reload the new file (if
NOERROR is equal to `reload'), or otherwise emit a warning."
(let ((lh load-history)
(res (require feature filename (if (eq noerror 'reload) nil noerror))))
;; If the `feature' was not yet provided, `require' just loaded the right
;; file, so we're done.
(when (and res (eq lh load-history))
;; If `require' did nothing, we need to make sure that was warranted.
(let* ((fn (locate-file (or filename (symbol-name feature))
load-path (get-load-suffixes) nil
)) ;; load-prefer-newer
;; We used to look for `fn' in `load-history' with `assoc'
;; which works in most cases, but in some cases (e.g. when
;; `load-prefer-newer' is set) `locate-file' can return a
;; different file than the file that `require' would load,
;; so the file won't be found in `load-history' even though
;; we did load "it". (bug#74040)
;; So use a "permissive" search which doesn't pay attention to
;; differences between file extensions.
(prefix (if (string-match
(concat (regexp-opt (get-load-suffixes)) "\\'") fn)
(concat (substring fn 0 (match-beginning 0)) ".")
fn))
(lh load-history))
(while (and lh (let ((file (car-safe (car lh))))
(not (and file (string-prefix-p prefix file)))))
(setq lh (cdr lh)))
(cond
(lh nil) ;We loaded the right file.
((eq noerror 'reload) (load fn nil 'nomessage))
((and fn (memq feature features))
(let ((oldfile (symbol-file feature 'provide)))
(funcall (if noerror #'warn #'error)
"Feature `%S' loaded from %S is now provided by %S"
feature (if oldfile (abbreviate-file-name oldfile))
(abbreviate-file-name fn))))
(fn
(funcall (if noerror #'warn #'error)
"Could not load file: %s" fn))
(t
(funcall (if noerror #'warn #'error)
"Could not locate file in load path: %s"
(or filename (symbol-name feature)))))))
res))