;;; lisp-mnt.el --- utility functions for Emacs Lisp maintainers -*- lexical-binding:t -*-
-;; Copyright (C) 1992, 1994, 1997, 2000-2024 Free Software Foundation,
-;; Inc.
+;; Copyright (C) 1992-2024 Free Software Foundation, Inc.
;; Author: Eric S. Raymond <esr@thyrsus.com>
;; Maintainer: emacs-devel@gnu.org
;; * Code line --- exists so Lisp can know where commentary and/or
;; change-log sections end.
;;
-;; * Footer line --- marks end-of-file so it can be distinguished from
-;; an expanded formfeed or the results of truncation.
+;; * Footer line --- marks end-of-file so it can be distinguished
+;; from an expanded formfeed or the results of truncation. This is
+;; required for a package to be installable by package.el in Emacs 29.1
+;; or earlier, but is optional in later versions.
;;; Code:
(lm--prepare-package-dependencies
(package-read-from-string (mapconcat #'identity require-lines " "))))))
+(defun lm-package-needs-footer-line (&optional file)
+ "Return non-nil if package in current buffer needs a footer line.
+
+Footer lines (sometimes referred to as \"terminating comments\") look
+like this:
+
+ ;;; some-cool-package.el ends here
+
+Such lines are required for a package to be installable by package.el in
+Emacs 29.1 or earlier, but are optional in later versions. If the
+package depends on a version of Emacs where package.el requires such
+comments, or if no version requirement is specified, return non-nil.
+
+If optional argument FILE is non-nil, use that file instead of the
+current buffer."
+ (lm-with-file file
+ ;; Starting in Emacs 30.1, avoid warning if the minimum Emacs
+ ;; version is specified as 30.1 or later.
+ (let ((min-emacs (cadar (seq-filter (lambda (x) (eq (car x) 'emacs))
+ (lm-package-requires)))))
+ (or (null min-emacs)
+ (version< min-emacs "30.1")))))
+
(defun lm-keywords (&optional file)
"Return the keywords given in file FILE, or current buffer if FILE is nil.
The return is a `downcase'-ed string, or nil if no keywords
((not (lm-code-start))
"Can't find a `Code' section marker")
((progn
- (goto-char (point-max))
- (not
- (re-search-backward
- (rx bol ";;; " (regexp name) " ends here")
- nil t)))
+ (when (lm-package-needs-footer-line)
+ (goto-char (point-max))
+ (not
+ (re-search-backward
+ (rx bol ";;; " (regexp name) " ends here")
+ nil t))))
"Can't find the footer line")
((not (and (lm-copyright-mark) (lm-crack-copyright)))
"Can't find a valid copyright notice")
(let ((file-name (match-string-no-properties 1))
(desc (match-string-no-properties 2))
(start (line-beginning-position)))
+ (require 'lisp-mnt)
;; This warning was added in Emacs 27.1, and should be removed at
;; the earliest in version 31.1. The idea is to phase out the
;; requirement for a "footer line" without unduly impacting users
;; on earlier Emacs versions. See Bug#26490 for more details.
(unless (search-forward (concat ";;; " file-name ".el ends here") nil 'move)
- ;; Starting in Emacs 30.1, avoid warning if the minimum Emacs
- ;; version is specified as 30.1 or later.
- (let ((min-emacs (cadar (seq-filter (lambda (x) (eq (car x) 'emacs))
- (lm-package-requires)))))
- (when (or (null min-emacs)
- (version< min-emacs "30.1"))
- (lwarn '(package package-format) :warning
- "Package lacks a terminating comment"))))
+ (when (lm-package-needs-footer-line)
+ (lwarn '(package package-format) :warning
+ "Package lacks a terminating comment")))
;; Try to include a trailing newline.
(forward-line)
(narrow-to-region start (point))
- (require 'lisp-mnt)
;; Use some headers we've invented to drive the process.
(let* (;; Prefer Package-Version; if defined, the package author
;; probably wants us to use it. Otherwise try Version.
(project "0.9.8") (xref "1.6.2") (eldoc "1.14.0")
(seq "2.23") (external-completion "0.1"))))))
+(ert-deftest lm-tests--lm-package-needs-footer-line/empty-dependencies ()
+ (with-temp-buffer
+ (should (lm-package-needs-footer-line))))
+
+(ert-deftest lm-tests--lm-package-needs-footer-line/old-version ()
+ (with-temp-buffer
+ (insert ";; Package-Requires: ((emacs \"29.1\"))\n")
+ (should (lm-package-needs-footer-line))))
+
+(ert-deftest lm-tests--lm-package-needs-footer-line/new-version ()
+ (with-temp-buffer
+ (insert ";; Package-Requires: ((emacs \"30.1\"))\n")
+ (should (not (lm-package-needs-footer-line)))))
(ert-deftest lm--tests-lm-website ()
(with-temp-buffer