branch: elpa/projectile
commit 446886481850d8cfa3fc09b7fbcc7f3cbdc967e8
Author: Bozhidar Batsov <[email protected]>
Commit: Bozhidar Batsov <[email protected]>

    Bump minimum Emacs version from 26.1 to 27.1
    
    Emacs 27.1 was released nearly 6 years ago (August 2020). Bumping
    the minimum version lets us remove ~30 lines of compatibility code:
    
    - Remove fileloop fallback using deprecated tags-loop-scan/operate
    - Fix tags-query-replace FIXME in projectile-replace-regexp by using
      fileloop-initialize-replace + fileloop-continue
    - Replace projectile-flatten with built-in flatten-tree (6 call sites)
    - Simplify projectile-time-seconds to just (time-convert nil 'integer)
    - Use proper-list-p for known-projects file validation
    - Use json-parse-buffer unconditionally in CMake preset reader
    - Use package-get-version unconditionally
    - Add (require 'fileloop) as a proper dependency
    - Drop Emacs 26.3 from CI matrix
---
 .github/workflows/test.yml |  2 +-
 CHANGELOG.md               |  1 +
 projectile.el              | 70 +++++++++++++---------------------------------
 3 files changed, 21 insertions(+), 52 deletions(-)

diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index f6a5a95ce2..4b84aaa488 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -14,7 +14,7 @@ jobs:
     strategy:
       matrix:
         # Earliest supported + latest in each stable branch + snapshot.
-        emacs_version: ['26.3', '27.2', '28.2', '29.4', '30.2', 'snapshot']
+        emacs_version: ['27.2', '28.2', '29.4', '30.2', 'snapshot']
 
     steps:
     - name: Set up Emacs
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a26fc6b5a8..7cf63dcfbd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -34,6 +34,7 @@
 
 ### Changes
 
+* **[Breaking]** Bump minimum required Emacs version from 26.1 to 27.1. This 
removes ~30 lines of compatibility code (fileloop fallback, `time-convert` 
fallback, `projectile-flatten` shim) and fixes the `tags-query-replace` FIXME 
in `projectile-replace-regexp`.
 * [#1958](https://github.com/bbatsov/projectile/issues/1958): Exclude 
`.projectile-cache.eld` from search results (ripgrep/ag/grep) by default.
 * [#1957](https://github.com/bbatsov/projectile/pull/1957): Add `:caller` 
information to calls to `ivy-read` (used by packages like `ivy-rich`).
 * [#1947](https://github.com/bbatsov/projectile/issues/1947): 
`projectile-project-name` should be marked as safe.
diff --git a/projectile.el b/projectile.el
index fe253f3a2c..8f224433a5 100644
--- a/projectile.el
+++ b/projectile.el
@@ -6,7 +6,7 @@
 ;; URL: https://github.com/bbatsov/projectile
 ;; Keywords: project, convenience
 ;; Version: 2.9.1
-;; Package-Requires: ((emacs "26.1"))
+;; Package-Requires: ((emacs "27.1"))
 
 ;; This file is NOT part of GNU Emacs.
 
@@ -41,6 +41,7 @@
 (require 'ibuf-ext)
 (require 'compile)
 (require 'grep)
+(require 'fileloop)
 (eval-when-compile
   (require 'find-dired)
   (require 'subr-x))
@@ -55,8 +56,6 @@
 (defvar ag-ignore-list)
 (defvar ggtags-completion-table)
 (defvar tags-completion-table)
-(defvar tags-loop-scan)
-(defvar tags-loop-operate)
 (defvar eshell-buffer-name)
 (defvar explicit-shell-file-name)
 (defvar grep-files-aliases)
@@ -73,9 +72,8 @@
 (declare-function vc-dir "vc-dir")
 (declare-function vc-dir-busy "vc-dir")
 (declare-function string-trim "subr-x")
-(declare-function fileloop-continue "fileloop")
-(declare-function fileloop-initialize-replace "fileloop")
 (declare-function tramp-archive-file-name-p "tramp-archive")
+(declare-function tramp-archive-file-name-archive "tramp-archive")
 (declare-function helm-grep-get-file-extensions "helm-grep")
 
 (declare-function ggtags-ensure-project "ext:ggtags")
@@ -957,9 +955,7 @@ Should be set via .dir-locals.el.")
   "Extract Projectile's package version from its package metadata."
   ;; Use `cond' below to avoid a compiler unused return value warning
   ;; when `package-get-version' returns nil. See #3181.
-  ;; FIXME: Inline the logic from package-get-version and adapt it
-  (cond ((fboundp 'package-get-version)
-         (package-get-version))))
+  (cond ((package-get-version))))
 
 ;;;###autoload
 (defun projectile-version (&optional show-version)
@@ -1126,10 +1122,7 @@ argument)."
 
 (defun projectile-time-seconds ()
   "Return the number of seconds since the unix epoch."
-  (if (fboundp 'time-convert)
-      (time-convert nil 'integer)
-    (cl-destructuring-bind (high low _usec _psec) (current-time)
-      (+ (ash high 16) low))))
+  (time-convert nil 'integer))
 
 (defun projectile-cache-project (project files)
   "Cache PROJECTs FILES.
@@ -1390,7 +1383,7 @@ If DIR is not supplied it's set to the current directory 
by default."
   (let ((dir (or dir default-directory)))
     ;; Back out of any archives, the project will live on the outside and
     ;; searching them is slow.
-    (when (and (fboundp 'tramp-archive-file-name-archive)
+    (when (and (fboundp 'tramp-archive-file-name-p)
                (tramp-archive-file-name-p dir))
       (setq dir (file-name-directory (tramp-archive-file-name-archive dir))))
     ;; the cached value will be 'none in the case of no project root (this is 
to
@@ -1612,11 +1605,6 @@ sub-modules there)."
     ;; TODO: Add support for other VCS
     (_ nil)))
 
-(defun projectile-flatten (lst)
-  "Take a nested list LST and return its contents as a single, flat list."
-  (if (and (listp lst) (listp (cdr lst)))
-      (cl-mapcan 'projectile-flatten lst)
-    (list lst)))
 
 (defun projectile-get-all-sub-projects (project)
   "Get all sub-projects for a given project.
@@ -1627,7 +1615,7 @@ PROJECT is base directory to start search recursively."
      ((null submodules)
       nil)
      (t
-      (nconc submodules (projectile-flatten
+      (nconc submodules (flatten-tree
                          ;; recursively get sub-projects of each sub-project
                          (mapcar (lambda (s)
                                    (projectile-get-all-sub-projects s)) 
submodules)))))))
@@ -1662,7 +1650,7 @@ they are excluded from the results of this function."
 
 (defun projectile-get-sub-projects-files (project-root _vcs)
   "Get files from sub-projects for PROJECT-ROOT recursively."
-  (projectile-flatten
+  (flatten-tree
    (mapcar (lambda (sub-project)
              (let ((project-relative-path
                     (file-name-as-directory (file-relative-name
@@ -1949,7 +1937,7 @@ Elements containing wildcards are expanded and spliced 
into the
 resulting paths.  The returned PATHS are absolute, based on the
 projectile project root."
   (let ((default-directory (projectile-project-root)))
-    (projectile-flatten (mapcar
+    (flatten-tree (mapcar
                          (lambda (pattern)
                            (or (file-expand-wildcards pattern t)
                                (projectile-expand-root pattern)))
@@ -2110,7 +2098,7 @@ Unignored files/directories are not included."
   (projectile-normalise-paths (nth 2 (projectile-parse-dirconfig-file))))
 
 (defun projectile-files-to-ensure ()
-  (projectile-flatten (mapcar (lambda (pat) (file-expand-wildcards pat t))
+  (flatten-tree (mapcar (lambda (pat) (file-expand-wildcards pat t))
                               (projectile-patterns-to-ensure))))
 
 (defun projectile-patterns-to-ensure ()
@@ -2434,7 +2422,7 @@ With FLEX-MATCHING, match any file that contains the base 
name of current file"
                         (string-match filename project-file))
                       project-file-list))
          (candidates
-          (projectile-flatten (mapcar
+          (flatten-tree (mapcar
                                (lambda (file)
                                  (cl-remove-if-not
                                   (lambda (project-file)
@@ -3265,8 +3253,7 @@ it acts on the current project."
   (when (file-exists-p filename)
     (with-temp-buffer
       (insert-file-contents filename)
-      (when (functionp 'json-parse-buffer)
-        (json-parse-buffer :array-type 'list)))))
+      (json-parse-buffer :array-type 'list))))
 
 (defconst projectile--cmake-command-preset-array-id-alist
   '((:configure-command . "configurePresets")
@@ -3299,7 +3286,7 @@ it acts on the current project."
 
 (defun projectile--cmake-all-command-presets (command-type)
   "Get CMake user and system COMMAND-TYPE presets."
-  (projectile-flatten
+  (flatten-tree
    (mapcar (lambda (filename) (projectile--cmake-command-presets filename 
command-type))
            '("CMakeUserPresets.json" "CMakePresets.json"))))
 
@@ -4995,27 +4982,8 @@ on which to run the replacement."
                     (projectile-prepend-project-name
                      (format "Replace %s with: " old-text))))
          (files (projectile-files-with-string old-text directory file-ext)))
-    (require 'fileloop nil t)
-    (if (fboundp #'fileloop-continue)
-        ;; Emacs 27+
-        (progn (fileloop-initialize-replace (regexp-quote old-text) new-text 
files 'default)
-               (fileloop-continue))
-      ;; Emacs 25 and 26
-      ;;
-      ;; Adapted from `tags-query-replace' for literal strings (not regexp)
-      (with-no-warnings
-        (setq tags-loop-scan
-              `(let ,(unless (equal old-text (downcase old-text))
-                       '((case-fold-search nil)))
-                 (if (search-forward ',old-text nil t)
-                     ;; When we find a match, move back to
-                     ;; the beginning of it so
-                     ;; perform-replace will see it.
-                     (goto-char (match-beginning 0)))))
-        (setq tags-loop-operate
-              `(perform-replace ',old-text ',new-text t nil nil
-                                nil multi-query-replace-map))
-        (tags-loop-continue (or (cons 'list files) t))))))
+    (fileloop-initialize-replace (regexp-quote old-text) new-text files 
'default)
+    (fileloop-continue)))
 
 ;;;###autoload
 (defun projectile-replace-regexp (&optional arg)
@@ -5045,8 +5013,8 @@ to run the replacement."
            (lambda (f) (or (file-directory-p f) (not (file-exists-p f))))
            (mapcar #'(lambda (file) (expand-file-name file directory))
                    (projectile-dir-files directory)))))
-    ;; FIXME: Probably would fail on Emacs 27+, fourth argument is gone.
-    (with-no-warnings (tags-query-replace old-text new-text nil (cons 'list 
files)))))
+    (fileloop-initialize-replace old-text new-text files 'default)
+    (fileloop-continue)))
 
 ;;;###autoload
 (defun projectile-kill-buffers ()
@@ -5933,7 +5901,7 @@ Return a list of projects removed."
 Also set `projectile-known-projects'."
   (let ((data (projectile-unserialize projectile-known-projects-file)))
     (setq projectile-known-projects
-          (if (and (listp data) (null (cdr (last data)))) data nil))
+          (if (proper-list-p data) data nil))
     (unless (equal data projectile-known-projects)
       (message "Warning: Projectile known projects file was corrupted, 
ignoring saved data"))
     (setq projectile-known-projects-on-file
@@ -5957,7 +5925,7 @@ overwriting each other's changes."
          (known-on-last-sync projectile-known-projects-on-file)
          (known-on-file
           (let ((data (projectile-unserialize projectile-known-projects-file)))
-            (if (and (listp data) (null (cdr (last data)))) data nil)))
+            (if (proper-list-p data) data nil)))
          (removed-after-sync (projectile-difference known-on-last-sync 
known-now))
          (removed-in-other-process
           (projectile-difference known-on-last-sync known-on-file))

Reply via email to