diff -pruN 2.1.0-1.1/Cask 2.5.0-1/Cask
--- 2.1.0-1.1/Cask	2020-02-04 18:30:35.000000000 +0000
+++ 2.5.0-1/Cask	1970-01-01 00:00:00.000000000 +0000
@@ -1,7 +0,0 @@
-(source gnu)
-(source melpa)
-
-(package-file "projectile.el")
-
-(development
- (depends-on "buttercup"))
diff -pruN 2.1.0-1.1/CHANGELOG.md 2.5.0-1/CHANGELOG.md
--- 2.1.0-1.1/CHANGELOG.md	2020-02-04 18:30:35.000000000 +0000
+++ 2.5.0-1/CHANGELOG.md	2021-08-10 10:11:43.000000000 +0000
@@ -2,6 +2,98 @@
 
 ## master (unreleased)
 
+## 2.5.0 (2021-08-10)
+
+### New features
+
+* [#1680](https://github.com/bbatsov/projectile/pull/1680): Add support for recursive project discovery.
+* [#1671](https://github.com/bbatsov/projectile/pull/1671)/[#1679](https://github.com/bbatsov/projectile/pull/1679) Allow the `:test-dir` and `:src-dir` options of a project to be set to functions for more flexible test switching.
+* [#1672](https://github.com/bbatsov/projectile/pull/1672)Add projectile-*-use-comint-mode variables for each compilation command.
+
+### Bugs fixed
+
+* [#1550](https://github.com/bbatsov/projectile/issues/1550): Make `projectile-regenerate-tags` tramp-aware.
+* [#1673](https://github.com/bbatsov/projectile/issues/1673): Fix CMake system-preset filename.
+* [#1691](https://github.com/bbatsov/projectile/pull/1691): Fix `compilation-find-file` advice handling of directory.
+
+### Changes
+
+* Remove `pkg-info` dependency.
+
+## 2.4.0 (2021-05-27)
+
+### New features
+
+* Add `projectile-<cmd>-use-comint-mode` variables (where `<cmd>` is `configure`, `compile`, `test`, `install`, `package`, or `run`). These enable interactive compilation buffers.
+* Add `projectile-update-project-type` function for updating the properties of existing project types.
+* [#1658](https://github.com/bbatsov/projectile/pull/1658): New command `projectile-reset-known-projects`.
+* [#1656](https://github.com/bbatsov/projectile/pull/1656): Add support for CMake configure, build and test presets. Enabled by setting `projectile-cmake-presets` to non-nil, disabled by default.
+* Add optional parameters to `projectile-run-shell-command-in-root` and `projectile-run-async-shell-command-in-root`
+
+### Changes
+
+* Add `project` param to `projectile-generate-process-name`.
+* [#1608](https://github.com/bbatsov/projectile/pull/1608): Use rebar3 build system by default for Erlang projects.
+* Rename `projectile-project-root-files-functions` to `projectile-project-root-functions`.
+* [#1647](https://github.com/bbatsov/projectile/issues/1647): Use "-B" in the mvn commands to avoid ANSI coloring clutter in the compile buffer
+* [#1657](https://github.com/bbatsov/projectile/pull/1657): Add project detection for Debian packaging directories.
+* [#1656](https://github.com/bbatsov/projectile/pull/1656): CMake compilation-dir removed to accomodate preset support, commands adjusted to run from project-root, with "build" still being the default build-directory. The non-preset test-command now uses "cmake" with "--target test" instead of "ctest".
+
+### Bugs fixed
+
+* [#1639](https://github.com/bbatsov/projectile/pull/1639): Do not ask twice for project running ielm, term and vterm.
+* [#1250](https://github.com/bbatsov/projectile/issues/1250): Fix `projectile-globally-ignored-directories` not working with native indexing.
+* [#1438](https://github.com/bbatsov/projectile/pull/1438): Make sure `projectile-files-via-ext-command` returns files, not errors.
+* [#1450](https://github.com/bbatsov/projectile/pull/1450): Call `switch-project-action` within project's temp buffer.
+* [#1340](https://github.com/bbatsov/projectile/pull/1340): Fix remote projects being removed if TRAMP can't connect.
+* [#1655](https://github.com/bbatsov/projectile/pull/1655): Fix `projectile-replace-regexp` searching the wrong files when called with prefix arg.
+* [#1659](https://github.com/bbatsov/projectile/issues/1659): Fix `projectile-project-vcs` to work outside a project.
+* [#1637](https://github.com/bbatsov/projectile/pull/1661): Integrate with savehist-mode.
+
+## 2.3.0 (2020-11-27)
+
+### New features
+
+* [#1517](https://github.com/bbatsov/projectile/issues/1517): Add project-specific compilation buffers and only ask to save files in the project when compiling.
+* New functions `projectile-acquire-root` and `projectile-process-current-project-buffers-current`
+* New project commands `projectile-package-project`, `projectile-install-project`.
+* [#1539](https://github.com/bbatsov/projectile/pull/1539): New defcustom `projectile-auto-discover` controlling whether to automatically discover projects in the search path when `projectile-mode` activates.
+* Add [emacs-eldev](https://github.com/doublep/eldev) project type.
+* Add Dart project type.
+* [#1555](https://github.com/bbatsov/projectile/pull/1555): Add search with ripgrep.
+* Add Python-poetry project type.
+* [#1576](https://github.com/bbatsov/projectile/pull/1576): Add OCaml [Dune](https://github.com/ocaml/dune) project type.
+* Add [Mill](http://www.lihaoyi.com/mill/) project type.
+* Auto-detect completion system, supporting `ido`, `ivy`, `helm` and the default completion system.
+
+### Changes
+
+* [#1540](https://github.com/bbatsov/projectile/pull/1540): Add default `test-suffix` to Angular projects.
+* Add a `:project-file` param to `projectile-register-project-type`.
+* [#1588](https://github.com/bbatsov/projectile/pull/1588): Improve performance of `projectile-ibuffer` with many buffers not in project.
+* [#1601](https://github.com/bbatsov/projectile/pull/1601): Implement separate compilation command history for each project.
+
+### Bugs fixed
+
+* [#1377](https://github.com/bbatsov/projectile/issues/1377): Fix `projectile-regenerate-tags` directory.
+
+## 2.2.0 (2020-06-10)
+
+### New features
+
+* [#1523](https://github.com/bbatsov/projectile/issues/1523): Add a new defcustom (`projectile-max-file-buffer-count`) controlling how many opened file buffers should Projectile maintain per project.
+* Optional support for comments in .projectile dirconfig files using `projectile-dirconfig-comment-prefix`.
+* [#1497](https://github.com/bbatsov/projectile/pull/1497): New command `projectile-run-gdb` (<kbd>x g</kbd> in `projectile-command-map`).
+* Add [Bazel](https://bazel.build) project type.
+
+### Bugs fixed
+
+* [#1503](https://github.com/bbatsov/projectile/pull/1503): Leave archive before searching for the project root.
+
+### Changes
+
+* [#1528](https://github.com/bbatsov/projectile/pull/1528): Improve massively the performance of native indexing (it's around 10x faster now).
+
 ## 2.1.0 (2020-02-04)
 
 ### New features
@@ -15,17 +107,18 @@
 * [#1405](https://github.com/bbatsov/projectile/pull/1405): Add Bloop Scala build server project detection.
 * [#1418](https://github.com/bbatsov/projectile/pull/1418): The presence of a `go.mod` file implies a go project.
 * [#1419](https://github.com/bbatsov/projectile/pull/1419): When possible, use [fd](https://github.com/sharkdp/fd) instead
-  of `find` to list the files of a non-VCS project. This should be much faster.
+of `find` to list the files of a non-VCS project. This should be much faster.
 
 ### Bugs fixed
 
+* [#675](https://github.com/bbatsov/projectile/issues/675): Performance improvement for native project indexing strategy.
 * [#97](https://github.com/bbatsov/projectile/issues/97): Respect `.projectile` ignores which are paths to files and patterns when using `projectile-grep`.
 * [#1391](https://github.com/bbatsov/projectile/issues/1391): A `.cabal` sub-directory is no longer considered project indicator.
 * [#1385](https://github.com/bbatsov/projectile/issues/1385): Update `projectile-replace` for Emacs 27.
 * [#1432](https://github.com/bbatsov/projectile/issues/1432): Support .NET project.
 * [#1270](https://github.com/bbatsov/projectile/issues/1270): Fix running commands that don't have a default value.
 * [#1475](https://github.com/bbatsov/projectile/issues/1475): Fix directories being ignored with hybrid mode despite being explicitly unignored.
-* [#1482](https://github.com/bbatsov/projectile/issues/1482): Run a seperate grep buffer per project root.
+* [#1482](https://github.com/bbatsov/projectile/issues/1482): Run a separate grep buffer per project root.
 * [#1488](https://github.com/bbatsov/projectile/issues/1488): Fix `projectile-find-file-in-directory` when in a subdir of `projectile-project-root`.
 
 ## 2.0.0 (2019-01-01)
@@ -196,7 +289,7 @@ This is done via the variables `projecti
 
 * Rename `projectile-switch-project-hook` to `projectile-after-switch-project-hook`.
 * `projectile-compile-project` now offers appropriate completion
-  targets even when called from a subdirectory.
+targets even when called from a subdirectory.
 * Add an argument specifying the regexp to search to `projectile-grep`.
 * Use `help-projectile-grep` instead of `helm-find-file` when selecting a project.
 * Omit current buffer from `projectile-switch-to-buffer` and `projectile-switch-to-buffer-other-window` choices.
@@ -227,25 +320,25 @@ to behave like `helm-find-files`, such a
 * Allows using Eshell and Magit outside of a project in `helm-projectile`.
 * Add Helm action for incremental grep in the selected projects.
 * Add command projectile-find-other-file  Switch between files with
-  the same  name but different extensions.
+the same  name but different extensions.
 * Add Helm interface to switch project. For more details checkout the file
-  README.md.
+README.md.
 * Make the mode line format customizable with `projectile-mode-line`
 * Add support for `cargo.toml` projects
 * Try to use projectile to find files in compilation buffers
 * Support `helm` as a completion system
 * New command `projectile-project-info` displays basic info about the current project.
 * New `defcustom` `projectile-globally-ignored-buffers` allows you to ignore
-  buffers by name
+buffers by name
 * New `defcustom` `projectile-globally-ignored-file-suffixes` allows
-  you to globally ignore files with particular extensions
+you to globally ignore files with particular extensions
 
 ### Changes
 
 * get-other-files returns more accurate results for files with the same name placed under different directories
 * Collect search tool (`grep`, `ag`, `ack`) keybindings under a common keymap prefix (`C-c p s`)
 * Remove `defcustom` `projectile-remember-window-configs` in favor of
-  `persp-projectile.el`.
+`persp-projectile.el`.
 * Progress reporter for the native indexing method.
 
 ### Bugs fixed
@@ -261,43 +354,43 @@ buffers.
 
 * Added support for default file glob pattern to `projectile-grep`
 * added file existence cache with defcustoms
-  `projectile-file-exists-remote-cache-expire` and
-  `projectile-file-exists-local-cache-expire`.
+`projectile-file-exists-remote-cache-expire` and
+`projectile-file-exists-local-cache-expire`.
 * added new defcustoms `projectile-project-root-files-top-down-recurring`,
-  `projectile-project-root-files-bottom-up` and
-  `projectile-project-root-files-functions`.
+`projectile-project-root-files-bottom-up` and
+`projectile-project-root-files-functions`.
 * Added new command `projectile-save-project-buffers`.
 * Added new command `projectile-cleanup-known-projects`.
 * Added new commands `projectile-display-buffer`
-  and`projectile-find-dir-other-window`.
+and`projectile-find-dir-other-window`.
 * Added new interactive function `projectile-project-buffers-other-buffer`
-  which runs new `projectile-project-buffers-non-visible` function, the former
-  is bound to `C-c p ESC`.
+which runs new `projectile-project-buffers-non-visible` function, the former
+is bound to `C-c p ESC`.
 * New variable `projectile-enable-idle-timer` turns on an idle timer
-  which runs the hook `projectile-idle-timer-hook` every
-  `projectile-idle-timer-seconds` seconds when non-nil.
+which runs the hook `projectile-idle-timer-hook` every
+`projectile-idle-timer-seconds` seconds when non-nil.
 * New defcustom `projectile-remember-window-configs` will make
-  `projectile-switch-project` restore the most recent window configuration (if
-  any) of the target project.
+`projectile-switch-project` restore the most recent window configuration (if
+any) of the target project.
 * New command `projectile-run-command-in-root`.
 * New command `projectile-run-shell-command-in-root`.
 * New command `projectile-run-async-shell-command-in-root`.
 * New defcustom `projectile-use-git-grep` will make `projectile-grep` use `git grep`
 for git projects.
 * Added new `projectile-commander` methods ?v and ?R which run
-  `projectile-vc` and `projectile-regenerate-tags`, respectively.
+`projectile-vc` and `projectile-regenerate-tags`, respectively.
 * `projectile-vc` will use `magit-status` if available.
 * New functions `projectile-find-implementation-or-test` and
-  `projectile-find-implementation-or-test-other-window`, the later is
-  bound to `C-c p 4 t`.
+`projectile-find-implementation-or-test-other-window`, the later is
+bound to `C-c p 4 t`.
 * New defcustoms `projectile-test-prefix-function` and `projectile-test-suffix-function`
 allow users to customize how projectile identifies test files by project type.
 * `projectile-grep` will ask for a file pattern if invoked with a
-  prefix argument.
+prefix argument.
 * Subversion checkouts are now automatically detected.
 * CVS checkouts are now automatically detected.
 * added `projectile-persp-switch-project` command to make perspective
-  mode work along with projectile.
+mode work along with projectile.
 * Changed `projectile-mode-line-lighter` to a defcustom variable to make
 mode line indicator prefix customizable.
 * New command `projectile-find-file-in-known-projects`.
@@ -312,20 +405,20 @@ that shouldn't be added to the known pro
 ### Changes
 
 * The presence of a `Makefile` is no longer taken as an indicator
-  of the project root by default, since recursive make is unfortunately
-  a common occurrence (affects `projectile-project-root-files`).
+of the project root by default, since recursive make is unfortunately
+a common occurrence (affects `projectile-project-root-files`).
 * Projectile is now able to find the project pertaining to a symlink
 pointing to a version-controlled file.
 * Drop `projectile-ack-function` defcustom.
 * `projectile-command-map` is now the keymap referenced by the
-  `projectile-keymap-prefix` in `projectile-mode-map`. This allows
-  modification of the inner map, and allows additional prefix keys to
-  reference it.
+`projectile-keymap-prefix` in `projectile-mode-map`. This allows
+modification of the inner map, and allows additional prefix keys to
+reference it.
 
 ### Bugs fixed
 
 * Modified `projectile-ack` to append to `ack-and-a-half-arguments`
-  instead of overriding them.
+instead of overriding them.
 * [#229] Fix `projectile-find-file-in-directory`'s behavior for project directories
 * `projectile-toggle-between-implementation-or-test` shows
 understandable error if current buffer is not visiting a file.
@@ -339,18 +432,18 @@ understandable error if current buffer i
 * Added new command `projectile-find-file-other-window`.
 * Added new command `projectile-switch-to-buffer-other-window`.
 * Added new command `projectile-find-file-in-directory` that allows
-  you to jump to files in any directory.
+you to jump to files in any directory.
 * `.projectile` is now always taken into account.
 * `projectile-switch-project`'s behavior is now customizable via
-  `projectile-switch-project-action`.
+`projectile-switch-project-action`.
 * Added support for Gradle projects.
 * Added support for `Ag`.
 * Added new command `projectile-purge-file-from-cache`.
 * Added new command `projectile-purge-dir-from-cache`.
 * Added new command `projectile-find-tag`.
 * Added new command `projectile-commander`. It allows you to quickly
-  run many Projectile commands with a single key. Very useful as a
-  project-switching action.
+run many Projectile commands with a single key. Very useful as a
+project-switching action.
 * `projectile-switch-project` now supports a prefix argument. When it's present
 the switch action is `projectile-commander`.
 
@@ -368,11 +461,11 @@ the switch action is `projectile-command
 ### New features
 
 * `projectile-invalidate-cache` now accepts a prefix argument. When
-  present you'll be prompted for the project whose cache to
-  invalidate.
+present you'll be prompted for the project whose cache to
+invalidate.
 * New command `projectile-find-dir` works similar to
-  `projectile-find-file` - displays the project's dirs and opens them
-  with `dired`. It's bound to `C-c p d`.
+`projectile-find-file` - displays the project's dirs and opens them
+with `dired`. It's bound to `C-c p d`.
 * Added support for `grizzl` as a completion system.
 * Added support for `fossil` projects.
 * Added support for `Symfony 2` project.
@@ -390,8 +483,8 @@ the switch action is `projectile-command
 * Rebound `projectile-compile-project` to <kbd>C-c p c</kbd>
 * Rebound `projectile-dired` to <kbd>C-c p D</kbd>
 * Reworked `projectile-compile-project` and `projectile-test-project`
-  to be smarter, more configurable and closer in behavior to the stock
-  `compile` command
+to be smarter, more configurable and closer in behavior to the stock
+`compile` command
 * `projectile-switch-project` (<kbd>C-c p s</kbd>) now runs `projectile-find-file` instead of `dired`.
 
 ## 0.9.1 (2013-04-26)
diff -pruN 2.1.0-1.1/CONTRIBUTING.md 2.5.0-1/CONTRIBUTING.md
--- 2.1.0-1.1/CONTRIBUTING.md	2020-02-04 18:30:35.000000000 +0000
+++ 2.5.0-1/CONTRIBUTING.md	2021-08-10 10:11:43.000000000 +0000
@@ -1,9 +1,8 @@
 # Contributing
 
-If you discover issues, have ideas for improvements or new features, or
-want to contribute a new module, please report them to the
-[issue tracker][1] of the repository or submit a pull request. Please,
-try to follow these guidelines when you do so.
+If you discover issues, have ideas for improvements or new features, please
+report them to the [issue tracker][1] of the repository or submit a pull
+request. Please, try to follow these guidelines when you do so.
 
 ## Issue reporting
 
@@ -14,6 +13,7 @@ try to follow these guidelines when you
 * Open an issue with a descriptive title and a summary in grammatically correct,
   complete sentences.
 * Include any relevant code to the issue summary.
+* If you're reporting performance issues it'd be nice if you added some profiling data (Emacs has a built-in profiler).
 
 ## Pull requests
 
diff -pruN 2.1.0-1.1/debian/changelog 2.5.0-1/debian/changelog
--- 2.1.0-1.1/debian/changelog	2022-05-19 14:10:12.000000000 +0000
+++ 2.5.0-1/debian/changelog	2022-08-01 00:02:30.000000000 +0000
@@ -1,3 +1,45 @@
+projectile (2.5.0-1) unstable; urgency=medium
+
+  * Update to new upstream version 2.5.0.
+  * Adopt the package from Sean Whitton (Closes: #1003031).
+  * Revert to plain patches-unapplied workflow.
+  * Get rid of the projectile-doc package, put the documentation in the
+    main package directly.
+  * Adapt to new documentation build (Closes: #988767).
+  * Bump debhelper compat to 13.
+
+  * d/copyright:
+    - Bump copyright years.
+
+  * d/control:
+    - Bump standards version to 4.5.1 (no changes required).
+    - Replace mkdocs with asciidoctor for documentation build.
+    - Remove elpa-flx-ido from Recommends.
+    - Move exuberant-ctags from Recomments to Suggests.
+    - Add ripgrep to Suggests.
+    - Rewrite package description.
+    - Added optional Rules-Requires-Root field to respect Debian Policy.
+
+  * d/patches:
+    - Refresh and extend patch 001 (more extension packages, correct
+    links).
+    - Refresh patches 002, 003, 006, 007 and 008.
+    - Drop patch 005 (mkdocs) since mkdocs is not used anymore.
+    - Improve patch 005 (test hack) : test for root directory.
+    - Add patch 009 to mention elpa-ggtags instead of upstream.
+    - Add Forwarded field (DEP-3 guidelines).
+
+  * d/watch:
+    - Bump watch version to 4.
+
+  * d/rules:
+    - Change build rules to build documentation.
+
+  * d/source/lintian-overrides:
+    - Updated tag to match rename.
+
+ -- Aymeric Agon-Rambosson <aymeric.agon@yandex.com>  Mon, 01 Aug 2022 02:02:30 +0200
+
 projectile (2.1.0-1.1) unstable; urgency=medium
 
   * Non-maintainer upload.
diff -pruN 2.1.0-1.1/debian/clean 2.5.0-1/debian/clean
--- 2.1.0-1.1/debian/clean	2022-05-19 14:10:12.000000000 +0000
+++ 2.5.0-1/debian/clean	2022-08-01 00:02:30.000000000 +0000
@@ -1,3 +1,3 @@
-html/
-project/
-test/sandbox/
+# Removing produced html files
+doc/modules/ROOT/nav.html
+doc/modules/ROOT/pages/*.html
diff -pruN 2.1.0-1.1/debian/compat 2.5.0-1/debian/compat
--- 2.1.0-1.1/debian/compat	2022-05-19 14:10:12.000000000 +0000
+++ 2.5.0-1/debian/compat	1970-01-01 00:00:00.000000000 +0000
@@ -1 +0,0 @@
-10
diff -pruN 2.1.0-1.1/debian/control 2.5.0-1/debian/control
--- 2.1.0-1.1/debian/control	2022-05-19 14:10:12.000000000 +0000
+++ 2.5.0-1/debian/control	2022-08-01 00:02:30.000000000 +0000
@@ -2,15 +2,15 @@ Source: projectile
 Section: lisp
 Priority: optional
 Maintainer: Debian Emacsen team <debian-emacsen@lists.debian.org>
-Uploaders:
- Sean Whitton <spwhitton@spwhitton.name>,
+Uploaders: Aymeric Agon-Rambosson <aymeric.agon@yandex.com>,
 Build-Depends:
- debhelper (>= 10),
+ debhelper-compat (= 13),
  dh-elpa (>= 1.7),
  dh-exec,
  elpa-buttercup,
- mkdocs (>= 1.0.4),
-Standards-Version: 4.1.2
+ asciidoctor,
+Standards-Version: 4.5.1
+Rules-Requires-Root: no
 Homepage: https://www.projectile.mx/
 Vcs-Git: https://salsa.debian.org/emacsen-team/projectile.git
 Vcs-Browser: https://salsa.debian.org/emacsen-team/projectile
@@ -22,55 +22,35 @@ Depends:
  ${misc:Depends},
 Breaks: emacs24 (<< 1:25.1), emacs24-lucid (<< 1:25.1), emacs24-nox (<< 1:25.1)
 Recommends:
- elpa-flx-ido,
  emacs (>= 46.0),
- exuberant-ctags,
 Suggests:
  elpa-ag,
+ ripgrep,
  fd-find,
- projectile-doc,
+ exuberant-ctags,
 Enhances:
  emacs
 Description: project interaction library for Emacs
- This library enhances Emacs with easy project management and
- navigation. The concept of a project is simple: just a folder
- containing a special file.  Currently git, mercurial, darcs and
- bazaar repos are considered projects by default.  So are lein, maven,
- sbt, scons, rebar and bundler projects.  If you want to mark a folder
- manually as a project just create an empty .projectile file in it.
+ This library provides easy project management and navigation. The concept of a
+ project is pretty basic - just a folder containing special file. Currently git,
+ mercurial and bazaar repos are considered projects by default. If you want to
+ mark a folder manually as a project just create an empty .projectile file in
+ it.
  .
  Some of Projectile's features:
  .
    * jump to a file in project
-   * jump to files at point in project
-   * jump to a directory in project
-   * jump to a file in a directory
    * jump to a project buffer
    * jump to a test in project
-   * toggle between files with same names but different extensions
-     (e.g. `.h` <-> `.c/.cpp`, `Gemfile` <-> `Gemfile.lock`)
+   * toggle between files with same names but different extensions (e.g. `.h`
+     <-> `.c/.cpp`, `Gemfile` <-> `Gemfile.lock`)
    * toggle between code and its test (e.g. `main.service.js` <->
      `main.service.spec.js`)
    * jump to recently visited files in the project
    * switch between projects you have worked on
-   * kill all project buffers
+   * kill (close) all project buffers
    * replace in project
-   * multi-occur in project buffers
-   * grep in project
-   * regenerate project etags or gtags
-   * visit project in dired
-   * run make in a project with a single key chord
-
-Package: projectile-doc
-Section: doc
-Architecture: all
-Depends:
- elpa-projectile (= ${source:Version}),
- ${misc:Depends},
- ${mkdocs:Depends},
-Description: project interaction library for Emacs - documentation
- Projectile enhances Emacs with easy project management and
- navigation. The concept of a project is simple: just a folder
- containing a special file.
- .
- This package include projectile's HTML documentation.
+   * grep (search) in project
+   * run shell commands in a project (e.g. `make`, `lein`)
+   * support for multiple minibuffer completion/selection libraries (`ido`,
+     `ivy`, `helm` and the default completion system)
diff -pruN 2.1.0-1.1/debian/copyright 2.5.0-1/debian/copyright
--- 2.1.0-1.1/debian/copyright	2022-05-19 14:10:12.000000000 +0000
+++ 2.5.0-1/debian/copyright	2022-08-01 00:02:30.000000000 +0000
@@ -3,7 +3,7 @@ Upstream-Name: projectile
 Source: https://github.com/bbatsov/projectile
 
 Files: *
-Copyright: (C) 2011-2016 Bozhidar Batsov <bozhidar@batsov.com>
+Copyright: (C) 2011-2021 Bozhidar Batsov <bozhidar@batsov.com>
 License: GPL-3+
 
 Files: debian/*
diff -pruN 2.1.0-1.1/debian/doc-base 2.5.0-1/debian/doc-base
--- 2.1.0-1.1/debian/doc-base	1970-01-01 00:00:00.000000000 +0000
+++ 2.5.0-1/debian/doc-base	2022-08-01 00:02:30.000000000 +0000
@@ -0,0 +1,11 @@
+Document: projectile-manual
+Title: Projectile Manual
+Author: Bozhidar Batsov
+Abstract: This manual describes what projectile is
+ and how it can be used to
+ manage projects with Emacs.
+Section: Editors
+
+Format: HTML
+Index: /usr/share/doc/elpa-projectile/nav.html
+Files: /usr/share/doc/elpa-projectile/*.html
diff -pruN 2.1.0-1.1/debian/docs 2.5.0-1/debian/docs
--- 2.1.0-1.1/debian/docs	1970-01-01 00:00:00.000000000 +0000
+++ 2.5.0-1/debian/docs	2022-08-01 00:02:30.000000000 +0000
@@ -0,0 +1,3 @@
+README.md
+doc/modules/ROOT/nav.html
+doc/modules/ROOT/pages/*.html
diff -pruN 2.1.0-1.1/debian/elpa 2.5.0-1/debian/elpa
--- 2.1.0-1.1/debian/elpa	1970-01-01 00:00:00.000000000 +0000
+++ 2.5.0-1/debian/elpa	2022-08-01 00:02:30.000000000 +0000
@@ -0,0 +1 @@
+projectile.el
diff -pruN 2.1.0-1.1/debian/elpa-projectile.docs 2.5.0-1/debian/elpa-projectile.docs
--- 2.1.0-1.1/debian/elpa-projectile.docs	2022-05-19 14:10:12.000000000 +0000
+++ 2.5.0-1/debian/elpa-projectile.docs	1970-01-01 00:00:00.000000000 +0000
@@ -1 +0,0 @@
-README.md
diff -pruN 2.1.0-1.1/debian/elpa-projectile.elpa 2.5.0-1/debian/elpa-projectile.elpa
--- 2.1.0-1.1/debian/elpa-projectile.elpa	2022-05-19 14:10:12.000000000 +0000
+++ 2.5.0-1/debian/elpa-projectile.elpa	1970-01-01 00:00:00.000000000 +0000
@@ -1 +0,0 @@
-projectile.el
diff -pruN 2.1.0-1.1/debian/elpa-projectile.install 2.5.0-1/debian/elpa-projectile.install
--- 2.1.0-1.1/debian/elpa-projectile.install	2022-05-19 14:10:12.000000000 +0000
+++ 2.5.0-1/debian/elpa-projectile.install	1970-01-01 00:00:00.000000000 +0000
@@ -1,2 +0,0 @@
-#!/usr/bin/dh-exec
-CHANGELOG.md => usr/share/doc/elpa-projectile/NEWS
diff -pruN 2.1.0-1.1/debian/install 2.5.0-1/debian/install
--- 2.1.0-1.1/debian/install	1970-01-01 00:00:00.000000000 +0000
+++ 2.5.0-1/debian/install	2022-08-01 00:02:30.000000000 +0000
@@ -0,0 +1,2 @@
+#!/usr/bin/dh-exec
+CHANGELOG.md => usr/share/doc/elpa-projectile/NEWS
diff -pruN 2.1.0-1.1/debian/patches/0001-patch-README.patch 2.5.0-1/debian/patches/0001-patch-README.patch
--- 2.1.0-1.1/debian/patches/0001-patch-README.patch	2022-05-19 14:10:12.000000000 +0000
+++ 2.5.0-1/debian/patches/0001-patch-README.patch	2022-08-01 00:02:30.000000000 +0000
@@ -1,49 +1,52 @@
 From: Sean Whitton <spwhitton@spwhitton.name>
 Date: Sun, 13 Dec 2015 10:11:12 -0700
 Subject: patch README.md & extensions.md for Debian
+Forwarded: not-needed
 
 ---
  README.md         | 34 +++++-----------------------------
  doc/extensions.md |  6 ++++--
  2 files changed, 9 insertions(+), 31 deletions(-)
 
-diff --git a/README.md b/README.md
-index 26f33b5..779adc6 100644
 --- a/README.md
 +++ b/README.md
-@@ -1,9 +1,3 @@
+@@ -1,10 +1,5 @@
+ # Projectile
+ 
 -[![License GPL 3][badge-license]](http://www.gnu.org/licenses/gpl-3.0.txt)
 -[![MELPA](http://melpa.org/packages/projectile-badge.svg)](http://melpa.org/#/projectile)
 -[![MELPA Stable](http://stable.melpa.org/packages/projectile-badge.svg)](http://stable.melpa.org/#/projectile)
--[![Build Status](https://travis-ci.org/bbatsov/projectile.png?branch=master)](https://travis-ci.org/bbatsov/projectile)
--[![Patreon](https://img.shields.io/badge/patreon-donate-orange.svg)](https://www.patreon.com/bbatsov)
+-[![Build Status](https://github.com/bbatsov/projectile/workflows/CI/badge.svg)](https://github.com/bbatsov/projectile/actions?query=workflow%3ACI)
 -
  ## Synopsis
  
  **Projectile** is a project interaction library for Emacs. Its goal is to
-@@ -45,10 +39,6 @@ it. Some of Projectile's features:
- * check for dirty repositories
- * toggle read-only mode for the entire project
+@@ -52,42 +47,16 @@ You can support my work on Projectile vi
+  [Patreon](https://www.patreon.com/bbatsov) and
+  [GitHub Sponsors](https://github.com/sponsors/bbatsov).
  
--Here's a glimpse of Projectile in action:
+-## Projectile in Action
 -
--![Projectile Screenshot](doc/screenshots/projectile.png)
+-Here's a glimpse of Projectile in action (using `ivy`):
+-
+-![Projectile Demo](doc/modules/ROOT/assets/images/projectile-demo.gif)
+-
+-In this short demo you can see:
+-
+-* finding files in a project
+-* switching between implementation and test
+-* switching between projects
 -
- You can support my work on Projectile via
-  [PayPal](https://www.paypal.me/bbatsov),
-  [Patreon](https://www.patreon.com/bbatsov) and
-@@ -56,28 +46,14 @@ You can support my work on Projectile via
- 
  ## Quickstart
  
 -The instructions that follow are meant to get you from zero to a running Projectile setup
 -in a minute.  Visit the
--[user manual](https://docs.projectile.mx) for (way) more
+-[online documentation](https://docs.projectile.mx) for (way) more
 -details.
-+The instructions that follow are meant to get you from zero to a
-+running Projectile setup in a minute.  Visit the [user
-+manual](https://docs.projectile.mx) (or `apt-get install
-+projectile-doc`) for (way) more details.
++The instructions that follow are meant to get you from zero to a running
++Projectile setup in a minute.  Visit the [user
++manual](https://docs.projectile.mx) (or
++[here](/usr/share/doc/elpa-projectile/nav.html)) for (way) more details.
  
  ### Installation
  
@@ -64,20 +67,48 @@ index 26f33b5..779adc6 100644
 -Finally add this to your Emacs config:
 +Add this to your Emacs config:
  
- ```el
+ ```elisp
  (projectile-mode +1)
-diff --git a/doc/extensions.md b/doc/extensions.md
-index 29891a5..c3b93e3 100644
---- a/doc/extensions.md
-+++ b/doc/extensions.md
-@@ -3,6 +3,8 @@
+@@ -103,7 +72,8 @@ Those keymap prefixes are just a suggest
+ 
+ Enable `projectile-mode`, open a file in one of your projects and type a command such as <kbd>C-c p f</kbd>.
+ 
+-See the [online documentation](https://docs.projectile.mx) for more details.
++See the [user manual](https://docs.projectile.mx) (or
++[here](/usr/share/doc/elpa-projectile/nav.html)) for more details.
+ 
+ ## Caveats
+ 
+@@ -128,7 +98,7 @@ development of Projectile.
+ 
+ ## Changelog
+ 
+-A fairly extensive changelog is available [here](CHANGELOG.md).
++A fairly extensive changelog is available [here](NEWS.gz).
+ 
+ [badge-license]: https://img.shields.io/badge/license-GPL_3-green.svg
+ 
+--- a/doc/modules/ROOT/pages/extensions.adoc
++++ b/doc/modules/ROOT/pages/extensions.adoc
+@@ -3,16 +3,16 @@
  There are a number of packages that built on top of the basic functionality provided by Projectile:
  
- * [counsel-projectile](https://github.com/ericdanan/counsel-projectile) provides Ivy integration
--* [helm-projectile](https://github.com/bbatsov/helm-projectile) provides Helm integration
--* [persp-projectile](https://github.com/bbatsov/persp-projectile) provides perspective.el integration
-+* [helm-projectile](https://github.com/bbatsov/helm-projectile)
-+  provides Helm integration (`apt-get install elpa-helm-projectile`)
-+* [persp-projectile](https://github.com/bbatsov/persp-projectile)
-+  provides perspective.el integration (`apt-get install elpa-persp-projectile`)
- * [projectile-rails](https://github.com/asok/projectile-rails) provides extra functionality for Ruby on Rails projects
+ * https://github.com/ericdanan/counsel-projectile[counsel-projectile] provides Ivy integration
+-* https://github.com/bbatsov/helm-projectile[helm-projectile] provides Helm integration
+-* https://github.com/bbatsov/persp-projectile[persp-projectile] provides perspective.el integration
++* https://github.com/bbatsov/helm-projectile[helm-projectile] provides Helm integration (`apt install elpa-helm-projectile`)
++* https://github.com/bbatsov/persp-projectile[persp-projectile] provides perspective.el integration (`apt install elpa-persp-projectile`)
+ * https://github.com/asok/projectile-rails[projectile-rails] provides extra functionality for Ruby on Rails projects
+ * https://github.com/IvanMalison/org-projectile[org-projectile] provides functions for the creation of org-mode TODOs that are associated with Projectile projects.
+-* https://github.com/Alexander-Miller/treemacs/blob/master/src/extra/treemacs-projectile.el[treemacs-projectile] provides integration between treemacs and Projectile.
++* https://github.com/Alexander-Miller/treemacs/blob/master/src/extra/treemacs-projectile.el[treemacs-projectile] provides integration between treemacs and Projectile (`apt install elpa-treemacs-projectile`).
+ * https://github.com/anshulverma/projectile-speedbar[projectile-speedbar] provides integration between speedbar and Projectile.
+ 
+ NOTE: MELPA lists https://melpa.org/#/?q=projectile[20 more Projectile extensions], but I'm too lazy to list them all here.
+ 
+ There are also some packages that will use Projectile if present. Here are a few examples:
+ 
+-* https://github.com/jaypei/emacs-neotree[neotree]
+-* https://github.com/emacs-lsp/lsp-mode[lsp-mode]
++* https://github.com/jaypei/emacs-neotree[neotree] (`apt install elpa-neotree`)
++* https://github.com/emacs-lsp/lsp-mode[lsp-mode] (`apt install elpa-lsp-mode`)
diff -pruN 2.1.0-1.1/debian/patches/0002-error-refer-Debian-package.patch 2.5.0-1/debian/patches/0002-error-refer-Debian-package.patch
--- 2.1.0-1.1/debian/patches/0002-error-refer-Debian-package.patch	2022-05-19 14:10:12.000000000 +0000
+++ 2.5.0-1/debian/patches/0002-error-refer-Debian-package.patch	2022-08-01 00:02:30.000000000 +0000
@@ -1,32 +1,29 @@
 From: Sean Whitton <spwhitton@spwhitton.name>
 Date: Fri, 8 Jan 2016 18:16:19 -0700
 Subject: refer to Debian packages rather than upstream homepages
+Forwarded: not-needed
 
 ---
  projectile.el | 6 ++----
  1 file changed, 2 insertions(+), 4 deletions(-)
 
-diff --git a/projectile.el b/projectile.el
-index 73d8f26..83933be 100644
 --- a/projectile.el
 +++ b/projectile.el
-@@ -1781,8 +1781,7 @@ project-root for every file."
-                       :prompt prompt
-                       :input initial-input
-                       :buffer "*helm-projectile*")
--              (user-error "Please install helm from \
--https://github.com/emacs-helm/helm")))
-+              (user-error "Please install the elpa-helm apt package")))
-            ((eq projectile-completion-system 'ivy)
-             (if (fboundp 'ivy-read)
-                 (ivy-read prompt choices
-@@ -1790,8 +1789,7 @@ https://github.com/emacs-helm/helm")))
-                           :action (prog1 action
-                                     (setq action nil))
-                           :caller 'projectile-completing-read)
--              (user-error "Please install ivy from \
--https://github.com/abo-abo/swiper")))
-+              (user-error "Please install the elpa-ivy apt package")))
-            (t (funcall projectile-completion-system prompt choices))))
+@@ -1907,7 +1907,7 @@ project-root for every file."
+                        :prompt prompt
+                        :input initial-input
+                        :buffer "*helm-projectile*")
+-               (user-error "Please install helm")))
++               (user-error "Please install the elpa-helm apt package")))
+             ('ivy
+              (if (fboundp 'ivy-read)
+                  (ivy-read prompt choices
+@@ -1915,7 +1915,7 @@ project-root for every file."
+                            :action (prog1 action
+                                      (setq action nil))
+                            :caller 'projectile-completing-read)
+-               (user-error "Please install ivy")))
++               (user-error "Please install the elpa-ivy apt package")))
+             (_ (funcall projectile-completion-system prompt choices))))
      (if action
          (funcall action res)
diff -pruN 2.1.0-1.1/debian/patches/0003-debianise-exuberant-ctags-dep.patch 2.5.0-1/debian/patches/0003-debianise-exuberant-ctags-dep.patch
--- 2.1.0-1.1/debian/patches/0003-debianise-exuberant-ctags-dep.patch	2022-05-19 14:10:12.000000000 +0000
+++ 2.5.0-1/debian/patches/0003-debianise-exuberant-ctags-dep.patch	2022-08-01 00:02:30.000000000 +0000
@@ -1,6 +1,7 @@
 From: Sean Whitton <spwhitton@spwhitton.name>
 Date: Sun, 21 Feb 2016 12:58:19 -0700
 Subject: Debianise exuberant-ctags dependency
+Forwarded: not-needed
 
 (1) Default to ctags-exuberant rather than just ctags since the user
     might have used the alternatives system to point /usr/bin/ctags to
@@ -12,28 +13,9 @@ Subject: Debianise exuberant-ctags depen
  projectile.el        | 2 +-
  2 files changed, 4 insertions(+), 4 deletions(-)
 
-diff --git a/doc/configuration.md b/doc/configuration.md
-index e3904da..753b1cb 100644
---- a/doc/configuration.md
-+++ b/doc/configuration.md
-@@ -335,9 +335,9 @@ appears.
- 
- ## Regenerate tags
- 
--To be able to regenerate a project's tags via `projectile-tags-command`, you
--should install and add to the PATH
--[Exuberant Ctags](http://ctags.sourceforge.net/) instead of a plain ctags, which
-+To be able to regenerate a project's tags via
-+`projectile-tags-command`, you should install Exuberant Ctags
-+(`apt-get install exuberant-ctags`) instead of a plain ctags, which
- ships with Emacs distribution.
- 
- ## Idle Timer
-diff --git a/projectile.el b/projectile.el
-index 83933be..070a85f 100644
 --- a/projectile.el
 +++ b/projectile.el
-@@ -219,7 +219,7 @@ When nil Projectile will consider the current directory the project root."
+@@ -232,7 +232,7 @@ When nil Projectile will consider the cu
    :group 'projectile
    :type 'string)
  
@@ -42,3 +24,17 @@ index 83933be..070a85f 100644
    "The command Projectile's going to use to generate a TAGS file."
    :group 'projectile
    :type 'string)
+--- a/doc/modules/ROOT/pages/configuration.adoc
++++ b/doc/modules/ROOT/pages/configuration.adoc
+@@ -464,9 +464,8 @@ Both of these degrade properly when not
+ == Regenerate tags
+ 
+ To be able to regenerate a project's tags via `projectile-tags-command`, you
+-should install and add to the PATH
+-http://ctags.sourceforge.net/[Exuberant Ctags] instead of a plain ctags, which
+-ships with Emacs distribution.
++should install Exuberant Ctags (`apt install exuberant-ctags`) instead of a
++plain ctags, which ships with Emacs distribution.
+ 
+ == Idle Timer
+ 
diff -pruN 2.1.0-1.1/debian/patches/0005-configure-mkdocs-for-Debian.patch 2.5.0-1/debian/patches/0005-configure-mkdocs-for-Debian.patch
--- 2.1.0-1.1/debian/patches/0005-configure-mkdocs-for-Debian.patch	2022-05-19 14:10:12.000000000 +0000
+++ 2.5.0-1/debian/patches/0005-configure-mkdocs-for-Debian.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,37 +0,0 @@
-From: Sean Whitton <spwhitton@spwhitton.name>
-Date: Sat, 23 Jul 2016 15:22:49 -0700
-Subject: configure mkdocs for Debian
-
-1. set site_dir so that docs end up in /usr/share/doc/projectile-doc/html
-
-2. set use_directory_urls so that links are to foo/index.html rather
-   than to just foo/, which is better for offline browsing
-
-3. don't generate installation instructions page
----
- mkdocs.yml | 5 +++--
- 1 file changed, 3 insertions(+), 2 deletions(-)
-
-diff --git a/mkdocs.yml b/mkdocs.yml
-index 1302441..7a1ccf8 100644
---- a/mkdocs.yml
-+++ b/mkdocs.yml
-@@ -2,11 +2,11 @@ site_name: "Projectile: The Project Interaction Library for Emacs"
- repo_url: https://github.com/bbatsov/projectile/
- edit_uri: edit/master/doc/
- site_favicon: favicon.ico
-+site_dir: html
- copyright: "Copyright (C) 2011-2020 Bozhidar Batsov and Projectile contributors"
- docs_dir: doc
--pages:
-+nav:
- - Home: index.md
--- Installation: installation.md
- - Usage: usage.md
- - Projects: projects.md
- - Configuration: configuration.md
-@@ -20,3 +20,4 @@ extra_css:
- markdown_extensions:
-   - admonition
- theme: readthedocs
-+use_directory_urls: false
diff -pruN 2.1.0-1.1/debian/patches/0005-hack-projectile-directory-p-test-for-Debian-build.patch 2.5.0-1/debian/patches/0005-hack-projectile-directory-p-test-for-Debian-build.patch
--- 2.1.0-1.1/debian/patches/0005-hack-projectile-directory-p-test-for-Debian-build.patch	2022-05-19 14:10:12.000000000 +0000
+++ 2.5.0-1/debian/patches/0005-hack-projectile-directory-p-test-for-Debian-build.patch	2022-08-01 00:02:30.000000000 +0000
@@ -1,24 +1,22 @@
 From: Sean Whitton <spwhitton@spwhitton.name>
 Date: Fri, 11 Jan 2019 19:05:29 -0700
 Subject: hack projectile--directory-p test for Debian build
+Forwarded: not-needed
 
 Per Debian Policy, we cannot assume that the user's home directory
-exists.
+exists, but we can assume that the root directory does.
 ---
  test/projectile-test.el | 3 +--
  1 file changed, 1 insertion(+), 2 deletions(-)
 
-diff --git a/test/projectile-test.el b/test/projectile-test.el
-index c5cf90a..f7087c9 100644
 --- a/test/projectile-test.el
 +++ b/test/projectile-test.el
-@@ -1408,8 +1408,7 @@ You'd normally combine this with `projectile-test-with-sandbox'."
- (describe "projectile--directory-p"
+@@ -1626,7 +1626,7 @@ Just delegates OPERATION and ARGS for al
    (it "tests which directory exists"
      (expect (projectile--directory-p nil) :to-be nil)
--    (expect (projectile--directory-p "asdf") :to-be nil)
+     (expect (projectile--directory-p "asdf") :to-be nil)
 -    (expect (projectile--directory-p user-emacs-directory) :to-be-truthy)))
-+    (expect (projectile--directory-p "asdf") :to-be nil)))
++    (expect (projectile--directory-p "/") :to-be-truthy)))
  
  (describe "projectile-find-file-in-directory"
    (it "fails when called in a non-existing directory"
diff -pruN 2.1.0-1.1/debian/patches/0006-patch-test-init-code-for-Debian.patch 2.5.0-1/debian/patches/0006-patch-test-init-code-for-Debian.patch
--- 2.1.0-1.1/debian/patches/0006-patch-test-init-code-for-Debian.patch	2022-05-19 14:10:12.000000000 +0000
+++ 2.5.0-1/debian/patches/0006-patch-test-init-code-for-Debian.patch	2022-08-01 00:02:30.000000000 +0000
@@ -1,6 +1,7 @@
 From: Sean Whitton <spwhitton@spwhitton.name>
 Date: Fri, 11 Jan 2019 19:46:20 -0700
 Subject: patch test init code for Debian
+Forwarded: not-needed
 
 - Stop it from trying to load projectile.el
   dh_elpa_test handles doing this.
@@ -15,28 +16,26 @@ Subject: patch test init code for Debian
  test/projectile-test.el | 5 ++---
  1 file changed, 2 insertions(+), 3 deletions(-)
 
-diff --git a/test/projectile-test.el b/test/projectile-test.el
-index f7087c9..d8b95e6 100644
 --- a/test/projectile-test.el
 +++ b/test/projectile-test.el
-@@ -27,6 +27,7 @@
+@@ -28,6 +28,7 @@
  
  (require 'projectile)
  (require 'buttercup)
 +(require 'subr-x)
  
- 
+ ;; Useful debug information
  (message "Running tests on Emacs %s" emacs-version)
-@@ -36,8 +37,6 @@
-        (source-directory (locate-dominating-file current-file "Cask"))
-        ;; Do not load outdated byte code for tests
-        (load-prefer-newer t))
--  ;; Load the file under test
--  (load (expand-file-name "projectile" source-directory))
-   (setq projectile-test-path (expand-file-name "test" source-directory)))
+@@ -37,8 +38,6 @@
+                                     (source-directory (locate-dominating-file current-file "Eldev"))
+                                     ;; Do not load outdated byte code for tests
+                                     (load-prefer-newer t))
+-                               ;; Load the file under test
+-                               (load (expand-file-name "projectile" source-directory))
+                                (expand-file-name "test" source-directory)))
  
  ;;; Test Utilities
-@@ -46,7 +45,7 @@
+@@ -47,7 +46,7 @@
    (declare (indent 0) (debug (&rest form)))
    `(let ((sandbox (expand-file-name
                     (convert-standard-filename "test/sandbox/")
diff -pruN 2.1.0-1.1/debian/patches/0007-Patch-upstream-source-to-check-for-fdfind-rather-tha.patch 2.5.0-1/debian/patches/0007-Patch-upstream-source-to-check-for-fdfind-rather-tha.patch
--- 2.1.0-1.1/debian/patches/0007-Patch-upstream-source-to-check-for-fdfind-rather-tha.patch	2022-05-19 14:10:12.000000000 +0000
+++ 2.5.0-1/debian/patches/0007-Patch-upstream-source-to-check-for-fdfind-rather-tha.patch	2022-08-01 00:02:30.000000000 +0000
@@ -2,17 +2,16 @@ From: Nicholas D Steeves <nsteeves@gmail
 Date: Sun, 9 Feb 2020 15:52:28 -0700
 Subject: =?utf-8?q?Patch_upstream_source_to_check_for_=22fdfind=22_rather_t?=
  =?utf-8?q?han_=22fd=22_so=E2=80=A6?=
+Forwarded: not-needed
 
 [git-debrebase split: mixed commit: upstream part]
 ---
  projectile.el | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)
 
-diff --git a/projectile.el b/projectile.el
-index 070a85f..fc3734a 100644
 --- a/projectile.el
 +++ b/projectile.el
-@@ -651,8 +651,8 @@ Set to nil to disable listing submodules contents."
+@@ -689,8 +689,8 @@ Set to nil to disable listing submodules
    :type 'string)
  
  (defcustom projectile-generic-command
diff -pruN 2.1.0-1.1/debian/patches/0008-Patch-CHANGELOG.md-and-doc-configuration.md-to-direc.patch 2.5.0-1/debian/patches/0008-Patch-CHANGELOG.md-and-doc-configuration.md-to-direc.patch
--- 2.1.0-1.1/debian/patches/0008-Patch-CHANGELOG.md-and-doc-configuration.md-to-direc.patch	2022-05-19 14:10:12.000000000 +0000
+++ 2.5.0-1/debian/patches/0008-Patch-CHANGELOG.md-and-doc-configuration.md-to-direc.patch	2022-08-01 00:02:30.000000000 +0000
@@ -2,6 +2,7 @@ From: Nicholas D Steeves <nsteeves@gmail
 Date: Sun, 9 Feb 2020 15:53:24 -0700
 Subject: =?utf-8?q?Patch_CHANGELOG=2Emd_and_doc/configuration=2Emd_to_direc?=
  =?utf-8?q?t_users_to_our=E2=80=A6?=
+Forwarded: not-needed
 
 [git-debrebase split: mixed commit: upstream part]
 ---
@@ -9,29 +10,25 @@ Subject: =?utf-8?q?Patch_CHANGELOG=2Emd_
  doc/configuration.md | 2 +-
  2 files changed, 2 insertions(+), 2 deletions(-)
 
-diff --git a/CHANGELOG.md b/CHANGELOG.md
-index e1b13be..d888859 100644
 --- a/CHANGELOG.md
 +++ b/CHANGELOG.md
-@@ -14,7 +14,7 @@
+@@ -106,7 +106,7 @@
  * Support a list of functions for `related-files-fn` options and helper functions.
  * [#1405](https://github.com/bbatsov/projectile/pull/1405): Add Bloop Scala build server project detection.
  * [#1418](https://github.com/bbatsov/projectile/pull/1418): The presence of a `go.mod` file implies a go project.
 -* [#1419](https://github.com/bbatsov/projectile/pull/1419): When possible, use [fd](https://github.com/sharkdp/fd) instead
 +* [#1419](https://github.com/bbatsov/projectile/pull/1419): When possible, use fd (`apt install fd-find`) instead
-   of `find` to list the files of a non-VCS project. This should be much faster.
+ of `find` to list the files of a non-VCS project. This should be much faster.
  
  ### Bugs fixed
-diff --git a/doc/configuration.md b/doc/configuration.md
-index 753b1cb..751ac70 100644
---- a/doc/configuration.md
-+++ b/doc/configuration.md
-@@ -81,7 +81,7 @@ find . -type f -print0
+--- a/doc/modules/ROOT/pages/configuration.adoc
++++ b/doc/modules/ROOT/pages/configuration.adoc
+@@ -80,7 +80,7 @@ For non-VCS projects Projectile will inv
+ find . -type f -print0
+ ----
  
- !!! Tip
+-TIP: It's a great idea to install https://github.com/sharkdp/fd[fd] which is much faster than `find`.
++TIP: It's a great idea to install fd (`apt install fd-find`) which is much faster than `find`.
+  If `fd` is found, projectile will use as a replacement for `find`.
  
--    It's a great idea to install [fd](https://github.com/sharkdp/fd) which is much faster than `find`.
-+    It's a great idea to install fd (`apt install fd-find`) which is much faster than `find`.
-     If `fd` is found, projectile will use as a replacement for `find`.
- 
- ## Sorting
+ == Sorting
diff -pruN 2.1.0-1.1/debian/patches/0009-Patch-index.adoc.patch 2.5.0-1/debian/patches/0009-Patch-index.adoc.patch
--- 2.1.0-1.1/debian/patches/0009-Patch-index.adoc.patch	1970-01-01 00:00:00.000000000 +0000
+++ 2.5.0-1/debian/patches/0009-Patch-index.adoc.patch	2022-08-01 00:02:30.000000000 +0000
@@ -0,0 +1,16 @@
+From: Aymeric Agon-Rambosson <aymeric.agon@yandex.com>
+Date: Sat, 30 Jul 2022 06:06:47 +0200
+Subject: Patch index.adoc to mention elpa-ggtags instead of upstream
+Forwarded: not-needed
+
+--- a/doc/modules/ROOT/pages/index.adoc
++++ b/doc/modules/ROOT/pages/index.adoc
+@@ -46,7 +46,7 @@ Here are some of Projectile's features i
+ * replace in project
+ * multi-occur in project buffers
+ * grep in project
+-* regenerate project etags or gtags (requires https://github.com/leoliu/ggtags[ggtags]).
++* regenerate project etags or gtags (requires ggtags (`apt install elpa-ggtags`)).
+ * visit project in dired
+ * run make in a project with a single key chord
+ * browse dirty version controlled projects
diff -pruN 2.1.0-1.1/debian/patches/series 2.5.0-1/debian/patches/series
--- 2.1.0-1.1/debian/patches/series	2022-05-19 14:10:12.000000000 +0000
+++ 2.5.0-1/debian/patches/series	2022-08-01 00:02:30.000000000 +0000
@@ -1,8 +1,8 @@
 0001-patch-README.patch
 0002-error-refer-Debian-package.patch
 0003-debianise-exuberant-ctags-dep.patch
-0005-configure-mkdocs-for-Debian.patch
 0005-hack-projectile-directory-p-test-for-Debian-build.patch
 0006-patch-test-init-code-for-Debian.patch
 0007-Patch-upstream-source-to-check-for-fdfind-rather-tha.patch
 0008-Patch-CHANGELOG.md-and-doc-configuration.md-to-direc.patch
+0009-Patch-index.adoc.patch
diff -pruN 2.1.0-1.1/debian/projectile-doc.doc-base 2.5.0-1/debian/projectile-doc.doc-base
--- 2.1.0-1.1/debian/projectile-doc.doc-base	2022-05-19 14:10:12.000000000 +0000
+++ 2.5.0-1/debian/projectile-doc.doc-base	1970-01-01 00:00:00.000000000 +0000
@@ -1,11 +0,0 @@
-Document: projectile-manual
-Title: Projectile Manual
-Author: Bozhidar Batsov
-Abstract: This manual describes what projectile is
- and how it can be used to
- manage projects with Emacs.
-Section: Editors
-
-Format: HTML
-Index: /usr/share/doc/projectile-doc/html/index.html
-Files: /usr/share/doc/projectile-doc/html/*.html
diff -pruN 2.1.0-1.1/debian/projectile-doc.docs 2.5.0-1/debian/projectile-doc.docs
--- 2.1.0-1.1/debian/projectile-doc.docs	2022-05-19 14:10:12.000000000 +0000
+++ 2.5.0-1/debian/projectile-doc.docs	1970-01-01 00:00:00.000000000 +0000
@@ -1 +0,0 @@
-html
diff -pruN 2.1.0-1.1/debian/rules 2.5.0-1/debian/rules
--- 2.1.0-1.1/debian/rules	2022-05-19 14:10:12.000000000 +0000
+++ 2.5.0-1/debian/rules	2022-08-01 00:02:30.000000000 +0000
@@ -1,17 +1,12 @@
 #!/usr/bin/make -f
 
 %:
-	dh $@ --with elpa --with mkdocs
+	dh $@ --with elpa
 
-# mkdocs under python3 needs a UTF locale or Click gives up
+# We build html manual from asciidoc using asciidoctor
 override_dh_auto_build:
-	LANG=C.UTF-8 LC_ALL=C.UTF-8 mkdocs build --clean
-
-override_dh_installdocs:
-	dh_installdocs -X__pycache__ --link-doc=elpa-projectile
+	find doc -type f -name *.adoc -print0 | \
+	xargs -0 asciidoctor -S secure -a webfonts!
 
 override_dh_installchangelogs:
 	dh_installchangelogs -XCHANGELOG.md
-
-override_dh_compress:
-	dh_compress -Xsearch_index.json
diff -pruN 2.1.0-1.1/debian/source/lintian-overrides 2.5.0-1/debian/source/lintian-overrides
--- 2.1.0-1.1/debian/source/lintian-overrides	2022-05-19 14:10:12.000000000 +0000
+++ 2.5.0-1/debian/source/lintian-overrides	2022-08-01 00:02:30.000000000 +0000
@@ -1,2 +1,2 @@
 # not available
-debian-watch-may-check-gpg-signature
+debian-watch-does-not-check-gpg-signature
diff -pruN 2.1.0-1.1/debian/watch 2.5.0-1/debian/watch
--- 2.1.0-1.1/debian/watch	2022-05-19 14:10:12.000000000 +0000
+++ 2.5.0-1/debian/watch	2022-08-01 00:02:30.000000000 +0000
@@ -1,3 +1,4 @@
-version=3
+version=4
 opts=filenamemangle=s/.+\/v?(\d\S*)\.tar\.gz/projectile-$1\.tar\.gz/ \
-  https://github.com/bbatsov/projectile/tags .*/v?(\d\S*)\.tar\.gz
+  https://github.com/bbatsov/projectile/tags \
+  .*/v?(\d\S*)\.tar\.gz debian uupdate
diff -pruN 2.1.0-1.1/doc/antora.yml 2.5.0-1/doc/antora.yml
--- 2.1.0-1.1/doc/antora.yml	1970-01-01 00:00:00.000000000 +0000
+++ 2.5.0-1/doc/antora.yml	2021-08-10 10:11:43.000000000 +0000
@@ -0,0 +1,5 @@
+name: projectile
+title: Projectile
+version: master
+nav:
+- modules/ROOT/nav.adoc
diff -pruN 2.1.0-1.1/doc/configuration.md 2.5.0-1/doc/configuration.md
--- 2.1.0-1.1/doc/configuration.md	2020-02-04 18:30:35.000000000 +0000
+++ 2.5.0-1/doc/configuration.md	1970-01-01 00:00:00.000000000 +0000
@@ -1,376 +0,0 @@
-In the typical style of Emacs, Projectile is **extremely** configurable.
-Pretty much every aspect of its behaviour can be tweaked or extended.
-
-In this section we'll go over some of the most common things you might
-want to fine-tune to make Projectile fit your workflow better.
-
-## Project indexing method
-
-Projectile has three modes of operation - one is portable and is
-implemented in Emacs Lisp (therefore it's *native* to Emacs and is
-known as the `native indexing method`) and the other two (`hybrid` and
-`alien`) rely on external commands like `find`, `git`, etc to
-obtain the list of files in a project.
-
-The `alien` indexing method optimizes to the limit the speed of
-the `hybrid` indexing method.  This means that Projectile will not do
-any processing or sorting of the files returned by the external commands
-and you're going to get the maximum performance possible.  This behaviour
-makes a lot of sense for most people, as they'd typically be putting
-ignores in their VCS config (e.g. `.gitignore`) and won't care about
-any additional ignores/unignores/sorting that Projectile might also
-provide.
-
-!!! Info
-
-    By default the `alien` method is used on all operating systems except Windows.
-    Prior to Projectile 2.0 `hybrid` used to be the default (but to make things
-    confusing `hybrid` used to be known as `alien` back then).
-
-To force the
-use of native indexing in all operating systems:
-
-```el
-(setq projectile-indexing-method 'native)
-```
-
-To force the use of hybrid indexing in all operating systems:
-
-```el
-(setq projectile-indexing-method 'hybrid)
-```
-
-To force the use of alien indexing in all operating systems:
-
-```el
-(setq projectile-indexing-method 'alien)
-```
-
-This can speed up Projectile in Windows significantly (especially on
-big projects). The disadvantage of this method is that it's not well
-supported on Windows systems, as it requires setting up some Unix
-utilities there. If there's problem, you can always use `native`
-indexing mode.
-
-### Alien indexing
-
-The alien indexing works in a pretty simple manner - it simply shells
-out to a command that returns the list of files within a project.
-For version-controlled projects by default Projectile will use the
-VCS itself to obtain the list of files. As an example, here is the
-command that Projectile uses for Git projects:
-
-```
-git ls-files -zco --exclude-standard
-```
-
-For every supported VCS there's a matching Projectile defcustom holding the command
-to invoke for it (e.g. `projectile-git-command`, `projectile-hg-command`, etc).
-
-!!! Warning
-
-    If you ever decide to tweak those keep in mind that the command should always be returning
-    the list of files **relative** to the project root and the resulting file list should be 0-delimited
-    (as opposed to newline delimited).
-
-For non-VCS projects Projectile will invoke whatever is in `projectile-generic-command`. By default that's:
-
-```
-find . -type f -print0
-```
-
-!!! Tip
-
-    It's a great idea to install [fd](https://github.com/sharkdp/fd) which is much faster than `find`.
-    If `fd` is found, projectile will use as a replacement for `find`.
-
-## Sorting
-
-You can choose how Projectile sorts files by customizing `projectile-sort-order`.
-
-!!! Info
-
-    Note that if Alien indexing is set, files are not sorted by Projectile at all.
-
-The default is to not sort files:
-
-```el
-(setq projectile-sort-order 'default)
-```
-
-To sort files by recently opened:
-
-```el
-(setq projectile-sort-order 'recentf)
-```
-
-To sort files by recently active buffers and then recently opened files:
-
-```el
-(setq projectile-sort-order 'recently-active)
-```
-
-<!-- These URLs below are in HTML so that the parentheses in the URL fragments are properly recognised. -->
-
-To sort files by <a href="https://en.wikipedia.org/wiki/MAC_times#Modification_time_(mtime)">modification time</a> (mtime):
-
-```el
-(setq projectile-sort-order 'modification-time)
-```
-
-To sort files by <a href="https://en.wikipedia.org/wiki/MAC_times#Access_time_(atime)">access time</a> (atime):
-
-```el
-(setq projectile-sort-order 'access-time)
-```
-
-
-## Caching
-
-### Project files
-
-Since indexing a big project is not exactly quick (especially in Emacs
-Lisp), Projectile supports caching of the project's files. The caching
-is enabled by default whenever native indexing is enabled.
-
-To enable caching unconditionally use this snippet of code:
-
-```el
-(setq projectile-enable-caching t)
-```
-
-At this point you can try out a Projectile command such as <kbd>s-p f</kbd> (<kbd>M-x projectile-find-file RET</kbd>).
-
-Running <kbd>C-u s-p f</kbd> will invalidate the cache prior to
-prompting you for a file to jump to.
-
-Pressing <kbd>s-p z</kbd> will add the currently visited file to the
-cache for current project. Generally files created outside Emacs will
-be added to the cache automatically the first time you open them.
-
-The project cache is persistent and will be preserved during Emacs restarts.
-
-You can purge an individual file from the cache with `M-x projectile-purge-file-from-cache` or an
-entire directory with `M-x projectile-purge-dir-from-cache`.
-
-### File exists cache
-
-Projectile does many file existence checks since that is how it identifies a
-project root. Normally this is fine, however in some situations the file system
-speed is much slower than usual and can make emacs "freeze" for extended
-periods of time when opening files and browsing directories.
-
-The most common example would be interfacing with remote systems using
-TRAMP/ssh. By default all remote file existence checks are cached
-
-To disable remote file exists cache that use this snippet of code:
-
-```el
-(setq projectile-file-exists-remote-cache-expire nil)
-```
-
-To change the remote file exists cache expire to 10 minutes use this snippet
-of code:
-
-```el
-(setq projectile-file-exists-remote-cache-expire (* 10 60))
-```
-
-You can also enable the cache for local file systems, that is normally not
-needed but possible:
-
-```el
-(setq projectile-file-exists-local-cache-expire (* 5 60))
-```
-
-## Using Projectile everywhere
-
-If you want Projectile to be usable in every directory (even without the presence of project file):
-
-```el
-(setq projectile-require-project-root nil)
-```
-
-!!! Tip
-
-    This might not be a great idea if you start Projectile in your home folder for instance. :-)
-
-## Switching projects
-
-By default, projectile does not include the current project in the list when
-switching projects. If you want to include the current project, customize
-variable `projectile-current-project-on-switch`.
-
-When running `projectile-switch-project` (<kbd>s-p p</kbd>) Projectile invokes
-the command specified in `projectile-switch-project-action` (by default it is
-`projectile-find-file`).
-
-!!! Tip
-
-    Invoking the command with a prefix argument (<kbd>C-u s-p p</kbd>) will trigger
-    the Projectile Commander, which gives you quick access to most common commands
-    you might want to invoke on a project.
-
-Depending on your personal workflow and habits, you
-may prefer to alter the value of `projectile-switch-project-action`:
-
-### `projectile-find-file`
-
-This is the default.  With this setting, once you have selected your
-project via Projectile's completion system (see below), you will
-remain in the completion system to select a file to visit. `projectile-find-file`
-is capable of retrieving files in all sub-projects under the project root,
-such as Git submodules. Currently, only Git is supported. Support for other VCS
-will be added in the future.
-
-### `projectile-find-file-in-known-projects`
-
-Similar to `projectile-find-file` but lists all files in all known projects. Since
-the total number of files could be huge, it is beneficial to enable caching for subsequent
-usages.
-
-### `projectile-find-file-dwim`
-
-If point is on a filepath, Projectile first tries to search for that
-file in project:
-
-- If it finds just a file, it switches to that file instantly.  This
-works even if the filename is incomplete, but there's only a single file
-in the current project that matches the filename at point. For example,
-if there's only a single file named "projectile/projectile.el" but the
-current filename is "projectile/proj" (incomplete), projectile-find-file
-still switches to "projectile/projectile.el" immediately because this
-is the only filename that matches.
-
-- If it finds a list of files, the list is displayed for selecting. A
-list of files is displayed when a filename appears more than one in the
-project or the filename at point is a prefix of more than two files in a
-project. For example, if `projectile-find-file' is executed on a
-filepath like "projectile/", it lists the content of that directory.
-If it is executed on a partial filename like "projectile/a", a list of
-files with character 'a' in that directory is presented.
-
-- If it finds nothing, display a list of all files in project for
-  selecting.
-
-### `projectile-dired`
-
-```el
-(setq projectile-switch-project-action #'projectile-dired)
-```
-
-With this setting, once you have selected your project, the top-level
-directory of the project is immediately opened for you in a dired
-buffer.
-
-### `projectile-find-dir`
-
-```el
-(setq projectile-switch-project-action #'projectile-find-dir)
-```
-
-With this setting, once you have selected your project, you will
-remain in Projectile's completion system to select a sub-directory of
-your project, and then *that* sub-directory is opened for you in a
-dired buffer.  If you use this setting, then you will probably also
-want to set
-
-```el
-(setq projectile-find-dir-includes-top-level t)
-```
-
-in order to allow for the occasions where you want to select the
-top-level directory.
-
-## Completion Options
-
-### Ido
-
-By default Projectile uses `ido` as its completion system. `ido` is
-extremely popular and it is built into Emacs.
-
-
-!!! Tip
-
-    As already noted above if you're going to use the `ido` completion it's
-    **extremely highly** recommended that you install the optional
-    [flx-ido package](https://github.com/lewang/flx), which provides a much
-    more powerful alternative to `ido`'s built-in `flex` matching.
-
-### Ivy (recommended)
-
-Another completion option is [ivy](https://github.com/abo-abo/swiper):
-
-```el
-(setq projectile-completion-system 'ivy)
-```
-
-### Basic (Emacs's default)
-
-If you don't like `ido` and `ivy` you can use regular completion:
-
-```el
-(setq projectile-completion-system 'default)
-```
-
-You might want to combine default completion with `icomplete-mode` for optimum results.
-
-### Custom Completion Function
-
-You can also set `projectile-completion-system` to a function:
-
-```el
-(setq projectile-completion-system #'my-custom-completion-fn)
-(setq projectile-completion-system
-      (lambda (prompt choices)
-        ;; ...
-        ))
-```
-
-An example of a custom completion function is
-[this one](https://gist.github.com/rejeep/5933343), which only show
-the file name (not including path) and if the file selected is not
-unique, another completion with names relative to project root
-appears.
-
-## Regenerate tags
-
-To be able to regenerate a project's tags via `projectile-tags-command`, you
-should install and add to the PATH
-[Exuberant Ctags](http://ctags.sourceforge.net/) instead of a plain ctags, which
-ships with Emacs distribution.
-
-## Idle Timer
-
-Projectile can be configured to run the hook
-`projectile-idle-timer-hook` every time Emacs is in a project and has
-been idle for `projectile-idle-timer-seconds` seconds (default is 30
-seconds).  To enable this feature, run:
-
-```
-M-x customize-group RET projectile RET
-```
-
-and set `projectile-enable-idle-timer` to non-nil.  By default,
-`projectile-idle-timer-hook` runs `projectile-regenerate-tags`.  Add
-additional functions to the hook using `add-hook`:
-
-```el
-(add-hook 'projectile-idle-timer-hook #'my-projectile-idle-timer-function)
-```
-
-## Mode line indicator
-
-By default the minor mode indicator of Projectile appears in the form
-" Projectile[ProjectName:ProjectType]". This is configurable via several custom variables:
-
-* `projectile-mode-line-prefix` (by default " Projectile") controls the static part of the mode-line
-* `projectile-dynamic-mode-line` (by default `t`) controls whether to display the project name & type part of the mode-line
-* `projectile-mode-line-function` (by default `projectile-default-mode-line`) controls the actual function to be invoked to generate the mode-line. If you'd like to show different info you should supply a custom function to replace the default, for example `(setq projectile-mode-line-function '(lambda () (format " Proj[%s]" (projectile-project-name))))`
-
-!!! Note
-
-    The project name & type will not appear when editing remote files
-    (via TRAMP), as recalculating the project name is a fairly slow operation there
-    and would slow down a bit opening the files. They will also not appear for
-    non-file buffers, as they get updated via `find-file-hook`.
diff -pruN 2.1.0-1.1/doc/contributing.md 2.5.0-1/doc/contributing.md
--- 2.1.0-1.1/doc/contributing.md	2020-02-04 18:30:35.000000000 +0000
+++ 2.5.0-1/doc/contributing.md	1970-01-01 00:00:00.000000000 +0000
@@ -1,77 +0,0 @@
-## Issues
-
-Report issues and suggest features and improvements on the
-[GitHub issue tracker](https://github.com/bbatsov/projectile/issues). Don't ask
-questions on the issue tracker - use the [support channels](support.md) instead.
-
-If you want to file a bug, please provide all the necessary info listed in
-our issue reporting template (it's loaded automatically when you create a
-new GitHub issue).
-
-It's usually a good idea to try to reproduce (obscure) bugs in isolation. You
-can do this by cloning Projectile's GitHub repo and running `make run-projectile` inside
-it.  This will bring up Emacs with only the latest version of Projectile loaded. By
-starting fresh, with the latest code, we can ensure that the problem at hand
-isn't already fixed or caused by interactions with other packages.
-
-## Patches
-
-Patches in any form are always welcome! GitHub pull requests are even better! :-)
-
-Before submitting a patch or a pull request make sure all tests are
-passing and that your patch is in line with the [contribution
-guidelines](https://github.com/bbatsov/projectile/blob/master/CONTRIBUTING.md).
-
-## Documentation
-
-Good documentation is just as important as good code.
-
-Consider improving and extending this manual and the
-[community wiki](https://github.com/bbatsov/projectile/wiki).
-
-### Working on the Manual
-
-The manual is generated from the markdown files in the
-[doc](https://github.com/bbatsov/projectile/tree/master/doc) folder of Projectile's
-GitHub repo and is published to [Read the Docs](readthedocs.org). The
-[MkDocs](http://www.mkdocs.org/) tool is used to convert the markdown sources to
-HTML.
-
-To make changes to the manual you simply have to change the files under
-`doc`. The manual will be regenerated automatically when changes to those files
-are merged in `master` (or the latest stable branch).
-
-You can install `MkDocs` locally and use the command `mkdocs serve` to see the
-result of changes you make to the manual locally:
-
-```sh
-$ cd path/to/projectile/repo
-$ mkdocs serve
-```
-
-If you want to make changes to the manual's page structure you'll have to edit
-[mkdocs.yml](https://github.com/bbatsov/projectile/blob/master/mkdocs.yml).
-
-## Donations
-
-You can support the development of Projectile via
-[PayPal](https://www.paypal.me/bbatsov),
-[Patreon](https://www.patreon.com/bbatsov) and
-[GitHub Sponsors](https://github.com/sponsors/bbatsov).
-
-## Running the tests in batch mode
-
-```sh
-$ cd /path/to/projectile
-$ make update
-$ make compile
-$ make test
-```
-
-Run all tests with:
-
-```sh
-$ make test
-```
-
-Tests should run fine in `shell-mode` or `term-mode`. It's also possible to use <kbd>M-x</kbd> `compile` (or `helm-make`).
diff -pruN 2.1.0-1.1/doc/css/extra.css 2.5.0-1/doc/css/extra.css
--- 2.1.0-1.1/doc/css/extra.css	2020-02-04 18:30:35.000000000 +0000
+++ 2.5.0-1/doc/css/extra.css	1970-01-01 00:00:00.000000000 +0000
@@ -1,15 +0,0 @@
-/* By default kbd doesn't stand out very much. Let's fix this! */
-kbd {
-    padding: 3px 5px;
-    border: solid 1px #ccc;
-    background-color: #fcfcfc;
-    border-radius: 3px;
-    box-shadow: inset 0 -1px 0 #bbb;
-    display: inline-block;
-}
-
-/* The default font-size for code blocks is 75% which makes code
-hard to read. */
-code {
-    font-size: 90%;
-}
diff -pruN 2.1.0-1.1/doc/extensions.md 2.5.0-1/doc/extensions.md
--- 2.1.0-1.1/doc/extensions.md	2020-02-04 18:30:35.000000000 +0000
+++ 2.5.0-1/doc/extensions.md	1970-01-01 00:00:00.000000000 +0000
@@ -1,8 +0,0 @@
-## Extensions
-
-There are a number of packages that built on top of the basic functionality provided by Projectile:
-
-* [counsel-projectile](https://github.com/ericdanan/counsel-projectile) provides Ivy integration
-* [helm-projectile](https://github.com/bbatsov/helm-projectile) provides Helm integration
-* [persp-projectile](https://github.com/bbatsov/persp-projectile) provides perspective.el integration
-* [projectile-rails](https://github.com/asok/projectile-rails) provides extra functionality for Ruby on Rails projects
diff -pruN 2.1.0-1.1/doc/faq.md 2.5.0-1/doc/faq.md
--- 2.1.0-1.1/doc/faq.md	2020-02-04 18:30:35.000000000 +0000
+++ 2.5.0-1/doc/faq.md	1970-01-01 00:00:00.000000000 +0000
@@ -1,27 +0,0 @@
-## Why did you name it Projectile?
-
-I wanted a name that's not as boring as `project.el` and implies that your
-interaction with projects is going to speed up significantly. :-)
-
-## Does Projectile work with TRAMP?
-
-Yeah, it does. I don't use TRAMP myself, however, so I never paid that
-much attention to the TRAMP support. It's mostly community-maintained.
-
-## Why does Projectile violate the rule not to bind keys in the user keymap?
-
-I opted for the `C-c p` prefix fully aware that this violates [a very
-established Emacs
-convention](https://www.gnu.org/software/emacs/manual/html_node/elisp/Key-Binding-Conventions.html),
-mostly because it felt practical and because pressing `C-c C-p` is not
-super convenient for many people. I've come to regret this decision,
-though, and it will likely be reverted down the road.
-
-**Update** This was changed in Projectile 2.0.
-
-## Do you need some help cleanup up all those tickets that have piled up?
-
-Certainly! In our [issue
-tracker](https://github.com/bbatsov/projectile/issues/) we've got
-plenty of tickets marked with `Help Wanted` or `Good First Issue` that
-you can take a stab at, if you'd like to help out!
Binary files 2.1.0-1.1/doc/favicon.ico and 2.5.0-1/doc/favicon.ico differ
diff -pruN 2.1.0-1.1/doc/index.md 2.5.0-1/doc/index.md
--- 2.1.0-1.1/doc/index.md	2020-02-04 18:30:35.000000000 +0000
+++ 2.5.0-1/doc/index.md	1970-01-01 00:00:00.000000000 +0000
@@ -1,59 +0,0 @@
-**Projectile** is a project interaction library for Emacs. Its goal is to
-provide a nice set of features operating on a project level without
-introducing external dependencies (when feasible). For instance -
-finding project files has a portable implementation written in pure
-Emacs Lisp without the use of GNU `find` (but for performance sake an
-indexing mechanism backed by external commands exists as well).
-
-!!! Tip
-
-    In practical terms the fact that Projectile can index the files in
-    a project without shelling out to `find`, `git` or whatever, means
-    that unlike many similar tools it will work on Windows without any
-    additional setup.
-
-Projectile tries to be practical - portability is great, but if some
-external tools could speed up some task substantially and the tools
-are available, Projectile will leverage them.
-
-Here's a glimpse of Projectile in action (find file in project using `ido`):
-
-![Projectile Screenshot](screenshots/projectile.png)
-
-Projectile provides easy project management and navigation. The
-concept of a project is pretty basic - just a folder containing
-special file. Currently most VCS repos (e.g. `git`, `mercurial`, etc)
-are considered projects by default, as are directories containing
-build tools (e.g. `maven`, `leiningen`, etc) or framework markers
-(e.g. Ruby on Rails). If you want to mark a folder manually as a
-project just create an empty `.projectile` file in it. Some of
-Projectile's features:
-
-* jump to a file in project
-* jump to files at point in project
-* jump to a directory in project
-* jump to a file in a directory
-* jump to a project buffer
-* jump to a test in project
-* toggle between files with same names but different extensions (e.g. `.h` <-> `.c/.cpp`, `Gemfile` <-> `Gemfile.lock`)
-* toggle between code and its test (e.g. `main.service.js` <-> `main.service.spec.js`)
-* jump to recently visited files in the project
-* switch between projects you have worked on
-* kill all project buffers
-* replace in project
-* multi-occur in project buffers
-* grep in project
-* regenerate project etags or gtags (requires [ggtags](https://github.com/leoliu/ggtags)).
-* visit project in dired
-* run make in a project with a single key chord
-* browse dirty version controlled projects
-
-!!! Info
-
-    A bit of trivia for you - Projectile was my very first open-source project and
-    it has a very special place in my heart!
-
-You can support my work on Projectile via
- [PayPal](https://www.paypal.me/bbatsov),
- [Patreon](https://www.patreon.com/bbatsov) and
- [GitHub Sponsors](https://github.com/sponsors/bbatsov).
diff -pruN 2.1.0-1.1/doc/installation.md 2.5.0-1/doc/installation.md
--- 2.1.0-1.1/doc/installation.md	2020-02-04 18:30:35.000000000 +0000
+++ 2.5.0-1/doc/installation.md	1970-01-01 00:00:00.000000000 +0000
@@ -1,137 +0,0 @@
-## Prerequisites
-
-You'll need to have Emacs installed (preferably the latest stable
-release). If you're new to Emacs you might want to go through
-[the guided tour of Emacs](https://www.gnu.org/software/emacs/tour/index.html)
-and the built-in tutorial (just press <kbd>C-h t</kbd>).
-
-!!! Note
-
-    Projectile officially supports Emacs 25.1+.
-
-## Installation
-
-The recommended way to install Projectile is via `package.el`.
-
-### Installation via package.el
-
-Projectile is available on the two major `package.el` community
-maintained repos -
-[MELPA Stable](http://stable.melpa.org)
-and [MELPA](http://melpa.org).
-
-You can install Projectile with the following command:
-
-<kbd>M-x package-install [RET] projectile [RET]</kbd>
-
-or by adding this bit of Emacs Lisp code to your Emacs initialization file
-(`.emacs` or `init.el`):
-
-```el
-(unless (package-installed-p 'projectile)
-  (package-install 'projectile))
-```
-
-If the installation doesn't work try refreshing the package list:
-
-<kbd>M-x package-refresh-contents [RET]</kbd>
-
-Keep in mind that MELPA packages are built automatically from
-the `master` branch, meaning bugs might creep in there from time to
-time. Never-the-less, installing from MELPA is a reasonable way of
-obtaining Projectile, as the `master` branch is normally quite stable
-and serious regressions there are usually fixed pretty quickly.
-
-!!! Tip
-
-    If you don't want to (or can't) wait for MELPA to rebuild Projectile,
-    you can easily build and install an up-to-date MELPA package locally yourself. Check out
-    [this article](http://emacsredux.com/blog/2015/05/10/building-melpa-packages-locally/)
-    for details on the subject.
-
-Generally, users of the non-adventurous kind are advised to stick
-with the stable releases, available from MELPA Stable.
-You can pin Projectile to always use MELPA
-Stable by adding this to your Emacs initialization:
-
-```el
-(add-to-list 'package-pinned-packages '(projectile . "melpa-stable") t)
-```
-
-Finally add this to your Emacs config:
-
-```el
-(require 'projectile)
-(define-key projectile-mode-map (kbd "s-p") 'projectile-command-map)
-(define-key projectile-mode-map (kbd "C-c p") 'projectile-command-map)
-(projectile-mode +1)
-```
-
-!!! Note
-
-    Those keymap prefixes are just a suggestion. Feel free to put
-    there whatever works best for you.
-    `C-c p` used to be the default prefix up to version 2.0, but
-    starting with version 2.0 you have to select prefix key(s)
-    yourself.
-
-### Installation via use-package
-
-`use-package` can be used to install Projectile via the `package.el`'s repositories
-[MELPA Stable](http://stable.melpa.org) and [MELPA](http://melpa.org).
-
-If you wanted to install the version of Projectile which is what is to be found in
-the `master` branch, declare the following in your Emacs initialization file
-(`.emacs` or `init.el`):
-
-```el
-(use-package projectile
-  :ensure t
-  :config
-  (define-key projectile-mode-map (kbd "s-p") 'projectile-command-map)
-  (define-key projectile-mode-map (kbd "C-c p") 'projectile-command-map)
-  (projectile-mode +1))
-```
-
-However, if you wanted to be a bit more conservative and only use the stable
-releases of Projectile, you'd declare the following:
-
-```el
-(use-package projectile
-  :ensure t
-  :pin melpa-stable
-  :config
-  (define-key projectile-mode-map (kbd "s-p") 'projectile-command-map)
-  (define-key projectile-mode-map (kbd "C-c p") 'projectile-command-map)
-  (projectile-mode +1))
-```
-
-After placing one of the above s-expressions, evaluate it, for it to take effect
-by entering: <kbd>C-x C-e</kbd>.
-
-For further configuration options with `use-package`, consult the
-official [use-package repository](https://github.com/jwiegley/use-package).
-
-### Installation via el-get
-
-Projectile is also available for installation from
-the [el-get](https://github.com/dimitri/el-get) package manager.
-
-Provided you've already installed `el-get` you can install Projectile with the
-following command:
-
-<kbd>M-x el-get-install [RET] projectile [RET]</kbd>
-
-### Installation on Debian and Ubuntu
-
-Users of Debian 9 or later or Ubuntu 16.10 or later may simply
-`apt-get install elpa-projectile`.
-
-Your favourite Linux distribution might be providing a Projectile package as well.
-
-### Emacs Prelude
-
-Projectile is bundled with
-[Emacs Prelude](https://github.com/bbatsov/prelude). If you're a Prelude
-user, Projectile is already properly configured and ready for
-action.
Binary files 2.1.0-1.1/doc/modules/ROOT/assets/images/projectile-demo.gif and 2.5.0-1/doc/modules/ROOT/assets/images/projectile-demo.gif differ
diff -pruN 2.1.0-1.1/doc/modules/ROOT/nav.adoc 2.5.0-1/doc/modules/ROOT/nav.adoc
--- 2.1.0-1.1/doc/modules/ROOT/nav.adoc	1970-01-01 00:00:00.000000000 +0000
+++ 2.5.0-1/doc/modules/ROOT/nav.adoc	2021-08-10 10:11:43.000000000 +0000
@@ -0,0 +1,10 @@
+* xref:index.adoc[Home]
+* xref:installation.adoc[Installation]
+* xref:usage.adoc[Usage]
+* xref:projects.adoc[Projects]
+* xref:configuration.adoc[Configuration]
+* xref:extensions.adoc[Extensions]
+* xref:faq.adoc[FAQ]
+* xref:troubleshooting.adoc[Troubleshooting]
+* xref:contributing.adoc[Contributing]
+* xref:support.adoc[Support]
diff -pruN 2.1.0-1.1/doc/modules/ROOT/pages/configuration.adoc 2.5.0-1/doc/modules/ROOT/pages/configuration.adoc
--- 2.1.0-1.1/doc/modules/ROOT/pages/configuration.adoc	1970-01-01 00:00:00.000000000 +0000
+++ 2.5.0-1/doc/modules/ROOT/pages/configuration.adoc	2021-08-10 10:11:43.000000000 +0000
@@ -0,0 +1,511 @@
+= Configuration
+
+In the typical style of Emacs, Projectile is *extremely* configurable.
+Pretty much every aspect of its behaviour can be tweaked or extended.
+
+In this section we'll go over some of the most common things you might
+want to fine-tune to make Projectile fit your workflow better.
+
+== Project indexing method
+
+Projectile has three modes of operation - one is portable and is
+implemented in Emacs Lisp (therefore it's _native_ to Emacs and is
+known as the `native indexing method`) and the other two (`hybrid` and
+`alien`) rely on external commands like `find`, `git`, etc to
+obtain the list of files in a project.
+
+The `alien` indexing method optimizes to the limit the speed of
+the `hybrid` indexing method.  This means that Projectile will not do
+any processing or sorting of the files returned by the external commands
+and you're going to get the maximum performance possible.  This behaviour
+makes a lot of sense for most people, as they'd typically be putting
+ignores in their VCS config (e.g. `.gitignore`) and won't care about
+any additional ignores/unignores/sorting that Projectile might also
+provide.
+
+NOTE: By default the `alien` method is used on all operating systems except Windows.
+ Prior to Projectile 2.0 `hybrid` used to be the default (but to make things
+ confusing `hybrid` used to be known as `alien` back then).
+
+To force the
+use of native indexing in all operating systems:
+
+[source,elisp]
+----
+(setq projectile-indexing-method 'native)
+----
+
+To force the use of hybrid indexing in all operating systems:
+
+[source,elisp]
+----
+(setq projectile-indexing-method 'hybrid)
+----
+
+To force the use of alien indexing in all operating systems:
+
+[source,elisp]
+----
+(setq projectile-indexing-method 'alien)
+----
+
+This can speed up Projectile in Windows significantly (especially on
+big projects). The disadvantage of this method is that it's not well
+supported on Windows systems, as it requires setting up some Unix
+utilities there. If there's problem, you can always use `native`
+indexing mode.
+
+=== Alien indexing
+
+The alien indexing works in a pretty simple manner - it simply shells
+out to a command that returns the list of files within a project.
+For version-controlled projects by default Projectile will use the
+VCS itself to obtain the list of files. As an example, here is the
+command that Projectile uses for Git projects:
+
+----
+git ls-files -zco --exclude-standard
+----
+
+For every supported VCS there's a matching Projectile defcustom holding the command
+to invoke for it (e.g. `projectile-git-command`, `projectile-hg-command`, etc).
+
+WARNING: If you ever decide to tweak those keep in mind that the command should always be returning
+ the list of files **relative** to the project root and the resulting file list should be 0-delimited
+ (as opposed to newline delimited).
+
+For non-VCS projects Projectile will invoke whatever is in `projectile-generic-command`. By default that's:
+
+----
+find . -type f -print0
+----
+
+TIP: It's a great idea to install https://github.com/sharkdp/fd[fd] which is much faster than `find`.
+ If `fd` is found, projectile will use as a replacement for `find`.
+
+== Sorting
+
+You can choose how Projectile sorts files by customizing `projectile-sort-order`.
+
+NOTE: Note that if Alien indexing is set, files are not sorted by Projectile at all.
+
+The default is to not sort files:
+
+[source,elisp]
+----
+(setq projectile-sort-order 'default)
+----
+
+To sort files by recently opened:
+
+[source,elisp]
+----
+(setq projectile-sort-order 'recentf)
+----
+
+To sort files by recently active buffers and then recently opened files:
+
+[source,elisp]
+----
+(setq projectile-sort-order 'recently-active)
+----
+
+// These URLs below are in HTML so that the parentheses in the URL fragments are properly recognised.
+
+To sort files by https://en.wikipedia.org/wiki/MAC_times#Modification_time_(mtime)[modification time] (mtime):
+
+[source,elisp]
+----
+(setq projectile-sort-order 'modification-time)
+----
+
+To sort files by https://en.wikipedia.org/wiki/MAC_times#Access_time_(atime)[access time] (atime):
+
+[source,elisp]
+----
+(setq projectile-sort-order 'access-time)
+----
+
+== Caching
+
+=== Project files
+
+Since indexing a big project is not exactly quick (especially in Emacs
+Lisp), Projectile supports caching of the project's files. The caching
+is enabled by default whenever native indexing is enabled.
+
+To enable caching unconditionally use this snippet of code:
+
+[source,elisp]
+----
+(setq projectile-enable-caching t)
+----
+
+At this point you can try out a Projectile command such as kbd:[s-p f] (kbd:[M-x] `projectile-find-file` kbd:[RET]).
+
+Running kbd:[C-u s-p f] will invalidate the cache prior to
+prompting you for a file to jump to.
+
+Pressing kbd:[s-p z] will add the currently visited file to the
+cache for current project. Generally files created outside Emacs will
+be added to the cache automatically the first time you open them.
+
+The project cache is persistent and will be preserved during Emacs restarts.
+
+You can purge an individual file from the cache with `M-x projectile-purge-file-from-cache` or an
+entire directory with `M-x projectile-purge-dir-from-cache`.
+
+=== File exists cache
+
+Projectile does many file existence checks since that is how it identifies a
+project root. Normally this is fine, however in some situations the file system
+speed is much slower than usual and can make emacs "freeze" for extended
+periods of time when opening files and browsing directories.
+
+The most common example would be interfacing with remote systems using
+TRAMP/ssh. By default all remote file existence checks are cached
+
+To disable remote file exists cache that use this snippet of code:
+
+[source,elisp]
+----
+(setq projectile-file-exists-remote-cache-expire nil)
+----
+
+To change the remote file exists cache expire to 10 minutes use this snippet
+of code:
+
+[source,elisp]
+----
+(setq projectile-file-exists-remote-cache-expire (* 10 60))
+----
+
+You can also enable the cache for local file systems, that is normally not
+needed but possible:
+
+[source,elisp]
+----
+(setq projectile-file-exists-local-cache-expire (* 5 60))
+----
+
+== Using Projectile Commands Outside of Projects Directories
+
+Normally, you'd be using Projectile's commands from within some project directory.
+If, however, you invoke a command outside of a project, by default you'll be prompted
+for a project to switch to. That behavior is controlled by `projectile-require-project-root`.
+You can make Projectile simply raise an error outside of Project folders like this:
+
+[source,elisp]
+----
+(setq projectile-require-project-root t)
+----
+
+If you want Projectile to be usable in every directory (even without the presence of project file):
+
+[source,elisp]
+----
+(setq projectile-require-project-root nil)
+----
+
+With this setting if you invoke Projectile outside of a project, the current directory will be
+considered by Projectile the project root.
+
+TIP: This might not be a great idea if you start Projectile in your home folder for instance. :-)
+
+== Switching projects
+
+By default, projectile does not include the current project in the list when
+switching projects. If you want to include the current project, customize
+variable `projectile-current-project-on-switch`.
+
+When running `projectile-switch-project` (kbd:[s-p p]) and
+`projectile-switch-open-project` (kbd:[s-p q]) Projectile invokes the
+command specified in `projectile-switch-project-action` (by default it
+is `projectile-find-file`).
+
+TIP: Invoking the command with a prefix argument (kbd:[C-u s-p p] or kbd:[C-u s-p q]) will trigger
+ the Projectile Commander, which gives you quick access to most common commands
+ you might want to invoke on a project.
+
+Depending on your personal workflow and habits, you
+may prefer to alter the value of `projectile-switch-project-action`:
+
+=== `projectile-find-file`
+
+NOTE: This is the default.
+
+With this setting, once you have selected your
+project via Projectile's completion system (see below), you will
+remain in the completion system to select a file to visit. `projectile-find-file`
+is capable of retrieving files in all sub-projects under the project root,
+such as Git submodules. Currently, only Git is supported. Support for other VCS
+will be added in the future.
+
+=== `projectile-commander`
+
+NOTE: This is the recommended option for people who find themselves often needing
+to invoke a different action on project switch.
+
+With this setting, after selecting a project to switch to, you'll be prompted to specify the action to take with a 1-character mnemonic.
+
+|===
+| Keybinding | Description
+| kbd:[?]
+| Commander help buffer.
+
+| kbd:[D]
+| Open project root in dired.
+
+| kbd:[R]
+| Regenerate the project's etags/gtags.
+
+| kbd:[T]
+| Find test file in project.
+
+| kbd:[V]
+| Browse dirty projects
+
+| kbd:[a]
+| Run ag on project.
+
+| kbd:[b]
+| Switch to project buffer.
+
+| kbd:[d]
+| Find directory in project.
+
+| kbd:[e]
+| Find recently visited file in project.
+
+| kbd:[f]
+| Find file in project.
+
+| kbd:[g]
+| Run grep on project.
+
+| kbd:[j]
+| Find tag in project.
+
+| kbd:[k]
+| Kill all project buffers.
+
+| kbd:[o]
+| Run multi-occur on project buffers.
+
+| kbd:[r]
+| Replace a string in the project.
+
+| kbd:[s]
+| Switch project.
+
+| kbd:[v]
+| Open project root in vc-dir or magit.
+|===
+
+=== `projectile-find-file-in-known-projects`
+
+Similar to `projectile-find-file` but lists all files in all known projects. Since
+the total number of files could be huge, it is beneficial to enable caching for subsequent
+usages.
+
+=== `projectile-find-file-dwim`
+
+If point is on a filepath, Projectile first tries to search for that
+file in project:
+
+* If it finds just a file, it switches to that file instantly.  This
+works even if the filename is incomplete, but there's only a single file
+in the current project that matches the filename at point. For example,
+if there's only a single file named "projectile/projectile.el" but the
+current filename is "projectile/proj" (incomplete), projectile-find-file
+still switches to "projectile/projectile.el" immediately because this
+is the only filename that matches.
+* If it finds a list of files, the list is displayed for selecting. A
+list of files is displayed when a filename appears more than one in the
+project or the filename at point is a prefix of more than two files in a
+project. For example, if `projectile-find-file' is executed on a
+filepath like "projectile/", it lists the content of that directory.
+If it is executed on a partial filename like "projectile/a", a list of
+files with character 'a' in that directory is presented.
+* If it finds nothing, display a list of all files in project for
+selecting.
+
+=== `projectile-dired`
+
+[source,elisp]
+----
+(setq projectile-switch-project-action #'projectile-dired)
+----
+
+With this setting, once you have selected your project, the top-level
+directory of the project is immediately opened for you in a dired
+buffer.
+
+=== `projectile-find-dir`
+
+[source,elisp]
+----
+(setq projectile-switch-project-action #'projectile-find-dir)
+----
+
+With this setting, once you have selected your project, you will
+remain in Projectile's completion system to select a sub-directory of
+your project, and then _that_ sub-directory is opened for you in a
+dired buffer.  If you use this setting, then you will probably also
+want to set
+
+[source,elisp]
+----
+(setq projectile-find-dir-includes-top-level t)
+----
+
+in order to allow for the occasions where you want to select the
+top-level directory.
+
+== Completion Options
+
+=== Auto (default)
+
+By default Projectile detects the completion system in use, based
+on the mode variables `ido-mode`, `ivy-mode` and `helm-mode`.
+If none of those is activated, the `default` completion system is used.
+
+Unless for some reason you want to use a different completion system for Projetile than for the
+rest of Emacs, you'll probably don't want to select a particular completion system manually.
+
+=== Basic (Emacs's default)
+
+If you don't like `ido` and `ivy` you can use regular completion (based on `completing-read`):
+
+[source,elisp]
+----
+(setq projectile-completion-system 'default)
+----
+
+TIP: You might want to combine default completion with `icomplete-mode` for optimum results.
+Emacs 27 added `fido-mode` to `icomplete`.
+
+If you are using `fido-mode`, Projectile will
+use the `default` completion system. The same holds for `selectrum` which also relies
+on the `default` completion system.
+
+=== Ido
+
+The `ido` completion system is extremely popular and it is built into Emacs.
+
+[source,elisp]
+----
+(setq projectile-completion-system 'ido)
+----
+
+As noted above, Projectile will auto-detect `ido-mode` if enabled, so the
+above configuration is not needed most of the time.
+
+TIP: As already noted above if you're going to use the `ido` completion it's
+ **extremely highly** recommended that you install the optional
+ https://github.com/lewang/flx[flx-ido package], which provides a much
+ more powerful alternative to ``ido``'s built-in `flex` matching.
+
+=== Ivy (recommended)
+
+Another completion option is https://github.com/abo-abo/swiper[ivy]:
+
+[source,elisp]
+----
+(setq projectile-completion-system 'ivy)
+----
+
+As noted above, Projectile will auto-detect `ivy-mode` if enabled, so the
+above configuration is not needed most of the time.
+
+=== Custom Completion Function
+
+You can also set `projectile-completion-system` to a function:
+
+[source,elisp]
+----
+(setq projectile-completion-system #'my-custom-completion-fn)
+(setq projectile-completion-system
+      (lambda (prompt choices)
+        ;; ...
+        ))
+----
+
+An example of a custom completion function is
+https://gist.github.com/rejeep/5933343[this one], which only show
+the file name (not including path) and if the file selected is not
+unique, another completion with names relative to project root
+appears.
+
+== Project-specific Compilation Buffers
+
+This affects all commands built on top of `projectile--run-project-cmd` like:
+
+- `projectile-configure-project`
+- `projectile-run-project`
+- `projectile-test-project`
+- `projectile-install-project`
+- `projectile-package-project`
+
+Normally, the buffers created by those commands would be shared (overwritten)
+between projects, but it's also possible to make the compilation buffer names
+project-specific. Currently, this requires that the user explicitly set:
+
+[source,elisp]
+----
+(setq compilation-buffer-name-function
+      #'projectile-compilation-buffer-name)
+(setq compilation-save-buffers-predicate
+      #'projectile-current-project-buffer-p)
+----
+
+Both of these degrade properly when not inside a project.
+
+== Regenerate tags
+
+To be able to regenerate a project's tags via `projectile-tags-command`, you
+should install and add to the PATH
+http://ctags.sourceforge.net/[Exuberant Ctags] instead of a plain ctags, which
+ships with Emacs distribution.
+
+== Idle Timer
+
+Projectile can be configured to run the hook
+`projectile-idle-timer-hook` every time Emacs is in a project and has
+been idle for `projectile-idle-timer-seconds` seconds (default is 30
+seconds).  To enable this feature, run:
+
+----
+M-x customize-group RET projectile RET
+----
+
+and set `projectile-enable-idle-timer` to non-nil.  By default,
+`projectile-idle-timer-hook` runs `projectile-regenerate-tags`.  Add
+additional functions to the hook using `add-hook`:
+
+[source,elisp]
+----
+(add-hook 'projectile-idle-timer-hook #'my-projectile-idle-timer-function)
+----
+
+== Mode line indicator
+
+By default the minor mode indicator of Projectile appears in the form
+" Projectile[ProjectName:ProjectType]". This is configurable via several custom variables:
+
+* `projectile-mode-line-prefix` (by default " Projectile") controls the static part of the mode-line
+* `projectile-dynamic-mode-line` (by default `t`) controls whether to display the project name & type part of the mode-line
+* `projectile-mode-line-function` (by default `projectile-default-mode-line`) controls the actual function to be invoked to generate the mode-line. If you'd like to show different info you should supply a custom function to replace the default, for example `(setq projectile-mode-line-function '(lambda () (format " Proj[%s]" (projectile-project-name))))`
+
+NOTE: The project name & type will not appear when editing remote files
+ (via TRAMP), as recalculating the project name is a fairly slow operation there
+ and would slow down a bit opening the files. They will also not appear for
+ non-file buffers, as they get updated via `find-file-hook`.
+
+== Project-type-specific Configuration
+
+=== CMake
+
+Projectile supports https://cmake.org/cmake/help/git-stage/manual/cmake-presets.7.html[CMake presets]. Preset support is disabled by default, but can be enabled by setting `projectile-enable-cmake-presets` to non-nil. With preset-support enabled Projectile will parse the preset files and present the command-specific presets when executing a lifecycle command. In addition a `*no preset*` option is included for entering the command manually.
+
+NOTE: Preset support requires a CMake version that supports preset and for `json-parse-buffer` to be available.
diff -pruN 2.1.0-1.1/doc/modules/ROOT/pages/contributing.adoc 2.5.0-1/doc/modules/ROOT/pages/contributing.adoc
--- 2.1.0-1.1/doc/modules/ROOT/pages/contributing.adoc	1970-01-01 00:00:00.000000000 +0000
+++ 2.5.0-1/doc/modules/ROOT/pages/contributing.adoc	2021-08-10 10:11:43.000000000 +0000
@@ -0,0 +1,113 @@
+= Contributing
+
+== Issues
+
+Report issues and suggest features and improvements on the
+https://github.com/bbatsov/projectile/issues[GitHub issue tracker]. Don't ask
+questions on the issue tracker - use the xref:support.adoc[support channels] instead.
+
+If you want to file a bug, please provide all the necessary info listed in
+our issue reporting template (it's loaded automatically when you create a
+new GitHub issue).
+
+It's usually a good idea to try to reproduce (obscure) bugs in isolation. You
+can do this by cloning Projectile's GitHub repo and running `eldev emacs` inside
+it (you need to install [Eldev](https://github.com/doublep/eldev) tool first).
+This will bring up Emacs with only the latest version of Projectile loaded. By
+starting fresh, with the latest code, we can ensure that the problem at hand
+isn't already fixed or caused by interactions with other packages.
+
+== Patches
+
+Patches in any form are always welcome! GitHub pull requests are even better! :-)
+
+Before submitting a patch or a pull request make sure all tests are
+passing and that your patch is in line with the https://github.com/bbatsov/projectile/blob/master/CONTRIBUTING.md[contribution
+guidelines].
+
+== Documentation
+
+Good documentation is just as important as good code.
+
+Consider improving and extending this manual and the
+https://github.com/bbatsov/projectile/wiki[community wiki].
+
+=== Working on the Docs
+
+The manual is generated from the AsciiDoc files in the https://github.com/bbatsov/projectile/tree/master/doc[doc] folder of Projectile's GitHub repo and is published to https://docs.projectile.mx.
+https://antora.org[Antora] is used to convert the manual into HTML.
+The filesystem layout is described at https://docs.antora.org/antora/2.0/component-structure/.
+
+To make changes to the manual you simply have to change the files under `doc`.
+The manual will be regenerated manually periodically.
+
+==== Installing Antora
+
+NOTE: The instructions here assume you already have (the right version of) node.js installed.
+
+Installing the Antora is super simple:
+
+[source]
+----
+$ npm i -g @antora/cli@2.0 @antora/site-generator-default@2.0
+----
+
+Check out https://docs.antora.org/antora/2.0/install/install-antora/[the detailed installation instructions]
+if you run into any problems.
+
+==== Building the Site
+
+You can build the documentation locally from the https://github.com/bbatsov/docs.projectile.mx[docs.projectile.mx] repo.
+
+[source]
+----
+$ cd docs.projectile.mx
+$ antora --pull antora-playbook.yml
+----
+
+After you're done with the initial setup you can use the `deploy` script to push changes to the site:
+
+[source]
+----
+./deploy
+----
+
+NOTE: You'll need commit access to the repository for this to work.
+
+To check the generated site you can simply open `docs/index.html` in your favourite browser.
+
+If you want to make changes to the manual's page structure you'll have to edit
+https://github.com/bbatsov/projectile/blob/master/doc/modules/ROOT/nav.adoc[nav.adoc].
+
+== Donations
+
+You can support the development of Projectile via
+https://www.paypal.me/bbatsov[PayPal],
+https://www.patreon.com/bbatsov[Patreon] and
+https://github.com/sponsors/bbatsov[GitHub Sponsors].
+
+== Running the tests in batch mode
+
+[source,sh]
+----
+$ cd /path/to/projectile
+$ eldev test
+----
+
+If you need to make sure dependencies are at the latest version:
+
+[source,sh]
+----
+$ eldev update
+----
+
+Run all tests with Projectile installed as an Emacs package
+(i.e. byte-compiled and all that; this won't affect your normal Emacs
+though):
+
+[source,sh]
+----
+$ eldev -p test
+----
+
+Tests should run fine in `shell-mode` or `term-mode`. It's also possible to use kbd:[M-x] `compile` (or `helm-make`).
diff -pruN 2.1.0-1.1/doc/modules/ROOT/pages/extensions.adoc 2.5.0-1/doc/modules/ROOT/pages/extensions.adoc
--- 2.1.0-1.1/doc/modules/ROOT/pages/extensions.adoc	1970-01-01 00:00:00.000000000 +0000
+++ 2.5.0-1/doc/modules/ROOT/pages/extensions.adoc	2021-08-10 10:11:43.000000000 +0000
@@ -0,0 +1,18 @@
+== Extensions
+
+There are a number of packages that built on top of the basic functionality provided by Projectile:
+
+* https://github.com/ericdanan/counsel-projectile[counsel-projectile] provides Ivy integration
+* https://github.com/bbatsov/helm-projectile[helm-projectile] provides Helm integration
+* https://github.com/bbatsov/persp-projectile[persp-projectile] provides perspective.el integration
+* https://github.com/asok/projectile-rails[projectile-rails] provides extra functionality for Ruby on Rails projects
+* https://github.com/IvanMalison/org-projectile[org-projectile] provides functions for the creation of org-mode TODOs that are associated with Projectile projects.
+* https://github.com/Alexander-Miller/treemacs/blob/master/src/extra/treemacs-projectile.el[treemacs-projectile] provides integration between treemacs and Projectile.
+* https://github.com/anshulverma/projectile-speedbar[projectile-speedbar] provides integration between speedbar and Projectile.
+
+NOTE: MELPA lists https://melpa.org/#/?q=projectile[20 more Projectile extensions], but I'm too lazy to list them all here.
+
+There are also some packages that will use Projectile if present. Here are a few examples:
+
+* https://github.com/jaypei/emacs-neotree[neotree]
+* https://github.com/emacs-lsp/lsp-mode[lsp-mode]
diff -pruN 2.1.0-1.1/doc/modules/ROOT/pages/faq.adoc 2.5.0-1/doc/modules/ROOT/pages/faq.adoc
--- 2.1.0-1.1/doc/modules/ROOT/pages/faq.adoc	1970-01-01 00:00:00.000000000 +0000
+++ 2.5.0-1/doc/modules/ROOT/pages/faq.adoc	2021-08-10 10:11:43.000000000 +0000
@@ -0,0 +1,52 @@
+= Frequently Asked Questions
+
+== Why did you name it Projectile?
+
+I wanted a name that's not as boring as `project.el` and implies that your
+interaction with projects is going to speed up significantly. :-)
+
+NOTE: Funny enough, a few years after Projectile was created, another similar
+project called `project.el` was born. Despite its boring name it's a great
+project and happens to be part of Emacs.
+
+== How does Projectile compare to the built-in `project.el`?
+
+`project.el` was introduced in Emacs 25.1, released in 2016, and a lot of people
+have been asking since how do the two packages compare.
+
+Internally they have a lot of differences (e.g. different approach to project discovery and indexing), but from the user standpoint they are probably quite similar
+these days (circa 2021). Historically, Projectile had a lot more features, but many
+of them found their way into `project.el` over the years. If all you need is
+a way to quickly jump between project files or search/replace inside a project, you can't go wrong with both.
+
+For me Projectile's biggest advantage will always be that it's more community-friendly
+(e.g. the development happens on GitHub), and it's not restricted by the FSF
+contributor agreement, which means that everyone can easily contribute to the project. Of course, this comes with the downside that you have to install Projectile
+yourselves.
+
+One under-appreciated advantage of Projectile is that it has way more documentation.
+Okay, that's only an advantage if you're one of those rare people who enjoy reading it.
+
+== Does Projectile work with TRAMP?
+
+Yeah, it does. I don't use TRAMP myself, however, so I never paid that
+much attention to the TRAMP support. It's mostly community-maintained.
+
+== Why doesn't Projectile have a default prefix for its keybinding?
+
+Historically Projectile used to use `C-c p` as the prefix for all of its commands.
+I opted for the `C-c p` prefix fully aware that this violates https://www.gnu.org/software/emacs/manual/html_node/elisp/Key-Binding-Conventions.html[a very
+established Emacs
+convention],
+mostly because it felt practical and because pressing `C-c C-p` is not
+super convenient for many people.
+
+Eventually this was changed in Projectile 2.0. That's why currently Projectile
+requires users to select a prefix key for its commands explicitly.
+
+== Do you need some help cleanup up all those tickets that have piled up?
+
+Certainly! In our https://github.com/bbatsov/projectile/issues/[issue
+tracker] we've got
+plenty of tickets marked with `Help Wanted` or `Good First Issue` that
+you can take a stab at, if you'd like to help out!
diff -pruN 2.1.0-1.1/doc/modules/ROOT/pages/index.adoc 2.5.0-1/doc/modules/ROOT/pages/index.adoc
--- 2.1.0-1.1/doc/modules/ROOT/pages/index.adoc	1970-01-01 00:00:00.000000000 +0000
+++ 2.5.0-1/doc/modules/ROOT/pages/index.adoc	2021-08-10 10:11:43.000000000 +0000
@@ -0,0 +1,97 @@
+= Projectile
+
+== Overview
+
+*Projectile* is a project interaction library for Emacs. Its goal is to
+provide a nice set of features operating on a project level without
+introducing external dependencies (when feasible). For instance -
+finding project files has a portable implementation written in pure
+Emacs Lisp without the use of GNU `find` (but for performance sake an
+indexing mechanism backed by external commands exists as well).
+
+TIP: In practical terms the fact that Projectile can index the files in
+ a project without shelling out to `find`, `git` or whatever, means
+ that unlike many similar tools it will work on Windows without any
+ additional setup.
+
+Projectile tries to be practical - portability is great, but if some
+external tools could speed up some task substantially and the tools
+are available, Projectile will leverage them.
+
+== Features
+
+Projectile provides easy project management and navigation. The
+concept of a project is pretty basic - just a folder containing
+special file.footnote:[That file is called a "project marker" in Projectile's lingo.] Currently most VCS repos (e.g. `git`, `mercurial`, etc)
+are considered projects by default, as are directories containing
+build tools (e.g. `maven`, `leiningen`, etc) or framework markers
+(e.g. Ruby on Rails). If you want to mark a folder manually as a
+project just create an empty `.projectile` file in it.
+
+TIP: You can learn more about Projectile's notion of a project xref:projects.adoc[here].
+
+Here are some of Projectile's features in no particular order:
+
+* jump to a file in project
+* jump to files at point in project
+* jump to a directory in project
+* jump to a file in a directory
+* jump to a project buffer
+* jump to a test in project
+* toggle between files with same names but different extensions (e.g. `.h` <--> `.c/.cpp`, `Gemfile` <--> `Gemfile.lock`)
+* toggle between code and its test (e.g. `main.service.js` <--> `main.service.spec.js`)
+* jump to recently visited files in the project
+* switch between projects you have worked on
+* kill all project buffers
+* replace in project
+* multi-occur in project buffers
+* grep in project
+* regenerate project etags or gtags (requires https://github.com/leoliu/ggtags[ggtags]).
+* visit project in dired
+* run make in a project with a single key chord
+* browse dirty version controlled projects
+* support for multiple minibuffer completion/selection libraries (`ido`, `ivy`, `helm` and the default completion system)
+
+== Projectile in Action
+
+Here's a glimpse of Projectile in action (using `ivy` for minibuffer completion):
+
+image::projectile-demo.gif[Projectile Screenshot]
+
+In this short demo you can see:
+
+* finding files in a project
+* switching between implementation and test
+* switching between projects
+
+TIP: You can see in the modeline the keybindings that are used in the demo and
+the commands that they invoked.footnote:[Courtesy of
+https://metaredux.com/posts/2019/12/07/dead-simple-emacs-screencasts.html[keycast-mode].]
+
+== Supporting Projectile
+
+I've started working on Projectile in 2011 and I've been maintaining it ever since. It slowly grew from an obscure
+project with a single user to one of the most popular packages in the realm of Emacs. It's a fun project,
+but it also requires a lot of work.
+
+You can support my work on Projectile (and all my other Emacs package) via one of the following platforms:
+
+* https://github.com/sponsors/bbatsov[GitHub Sponsors]
+* https://ko-fi.com/bbatsov[ko-fi]
+* https://www.paypal.me/bbatsov[PayPal]
+* https://www.patreon.com/bbatsov[Patreon]
+
+Check out the xref:contributing.adoc["Contributing"] section of the docs for all the ways in which you can help
+Projectile.
+
+NOTE: A bit of trivia for you - Projectile was my very first open-source project and
+ it has a very special place in my heart!
+
+== What's Next?
+
+So, what to do next? While you can peruse the documentation in whatever way you’d like, here are a few recommendations:
+
+* xref:installation.adoc[Install] Projectile and get it xref:usage.adoc[up and running]
+* Get familiar with xref:projects.adoc[Projectile's notion of projects]
+* xref:configuration.adoc[Configure] Projectile to your liking
+* Explore the xref:extensions.adoc[Projectile extensions] that can make you more productive
diff -pruN 2.1.0-1.1/doc/modules/ROOT/pages/installation.adoc 2.5.0-1/doc/modules/ROOT/pages/installation.adoc
--- 2.1.0-1.1/doc/modules/ROOT/pages/installation.adoc	1970-01-01 00:00:00.000000000 +0000
+++ 2.5.0-1/doc/modules/ROOT/pages/installation.adoc	2021-08-10 10:11:43.000000000 +0000
@@ -0,0 +1,140 @@
+= Installation
+
+NOTE: Projectile officially supports Emacs 25.1+.
+
+The recommended way to install Projectile is via `package.el`.
+
+== Prerequisites
+
+You'll need to have Emacs installed (preferably the latest stable
+release). If you're new to Emacs you might want to go through
+https://www.gnu.org/software/emacs/tour/index.html[the guided tour of Emacs]
+and the built-in tutorial (just press kbd:[C-h t]).
+
+== Installation via package.el
+
+Projectile is available on the two major `package.el` community
+maintained repos -
+http://stable.melpa.org[MELPA Stable]
+and http://melpa.org[MELPA].
+
+You can install Projectile with the following command:
+
+kbd:[M-x] `package-install` kbd:[RET] `projectile` kbd:[RET]
+
+or by adding this bit of Emacs Lisp code to your Emacs initialization file
+(`.emacs` or `init.el`):
+
+[source,elisp]
+----
+(unless (package-installed-p 'projectile)
+  (package-install 'projectile))
+----
+
+If the installation doesn't work try refreshing the package list:
+
+kbd:[M-x] `package-refresh-contents` kbd:[RET]
+
+Keep in mind that MELPA packages are built automatically from
+the `master` branch, meaning bugs might creep in there from time to
+time. Never-the-less, installing from MELPA is a reasonable way of
+obtaining Projectile, as the `master` branch is normally quite stable
+and serious regressions there are usually fixed pretty quickly.
+
+TIP: If you don't want to (or can't) wait for MELPA to rebuild Projectile,
+ you can easily build and install an up-to-date MELPA package locally yourself. Check out
+ http://emacsredux.com/blog/2015/05/10/building-melpa-packages-locally/[this article]
+ for details on the subject.
+
+Generally, users of the non-adventurous kind are advised to stick
+with the stable releases, available from MELPA Stable.
+You can pin Projectile to always use MELPA
+Stable by adding this to your Emacs initialization:
+
+[source,elisp]
+----
+(add-to-list 'package-pinned-packages '(projectile . "melpa-stable") t)
+----
+
+Finally add this to your Emacs config:
+
+[source,elisp]
+----
+(require 'projectile)
+;; Recommended keymap prefix on macOS
+(define-key projectile-mode-map (kbd "s-p") 'projectile-command-map)
+;; Recommended keymap prefix on Windows/Linux
+(define-key projectile-mode-map (kbd "C-c p") 'projectile-command-map)
+(projectile-mode +1)
+----
+
+NOTE: Those keymap prefixes are just a suggestion. Feel free to put
+ there whatever works best for you.
+ `C-c p` used to be the default prefix up to version 2.0, but
+ starting with version 2.0 you have to select prefix key(s)
+ yourself.
+
+== Installation via use-package
+
+`use-package` can be used to install Projectile via the ``package.el``'s repositories
+http://stable.melpa.org[MELPA Stable] and http://melpa.org[MELPA].
+
+If you wanted to install the version of Projectile which is what is to be found in
+the `master` branch, declare the following in your Emacs initialization file
+(`.emacs` or `init.el`):
+
+[source,elisp]
+----
+(use-package projectile
+  :ensure t
+  :init
+  (projectile-mode +1)
+  :bind (:map projectile-mode-map
+              ("s-p" . projectile-command-map)
+              ("C-c p" . projectile-command-map)))
+----
+
+However, if you wanted to be a bit more conservative and only use the stable
+releases of Projectile, you'd declare the following:
+
+[source,elisp]
+----
+(use-package projectile
+  :ensure t
+  :pin melpa-stable
+  :init
+  (projectile-mode +1)
+  :bind (:map projectile-mode-map
+              ("s-p" . projectile-command-map)
+              ("C-c p" . projectile-command-map)))
+----
+
+After placing one of the above s-expressions, evaluate it, for it to take effect
+by entering: kbd:[C-x C-e].
+
+For further configuration options with `use-package`, consult the
+official https://github.com/jwiegley/use-package[use-package repository].
+
+== Installation via el-get
+
+Projectile is also available for installation from
+the https://github.com/dimitri/el-get[el-get] package manager.
+
+Provided you've already installed `el-get` you can install Projectile with the
+following command:
+
+kbd:[M-x] `el-get-install` kbd:[RET] `projectile` kbd:[RET]
+
+== Installation on Debian and Ubuntu
+
+Users of Debian 9 or later or Ubuntu 16.10 or later may simply
+`apt-get install elpa-projectile`.
+
+Your favourite Linux distribution might be providing a Projectile package as well.
+
+== Emacs Prelude
+
+Projectile is bundled with
+https://github.com/bbatsov/prelude[Emacs Prelude]. If you're a Prelude
+user, Projectile is already properly configured and ready for
+action.
diff -pruN 2.1.0-1.1/doc/modules/ROOT/pages/projects.adoc 2.5.0-1/doc/modules/ROOT/pages/projects.adoc
--- 2.1.0-1.1/doc/modules/ROOT/pages/projects.adoc	1970-01-01 00:00:00.000000000 +0000
+++ 2.5.0-1/doc/modules/ROOT/pages/projects.adoc	2021-08-10 10:11:43.000000000 +0000
@@ -0,0 +1,750 @@
+= Projects
+
+== Supported Project Types
+
+One of the main goals of Projectile is to operate on a wide range of project types
+without the need for any configuration. To achieve this it contains a lot of
+project detection logic and project type specific logic.
+
+Broadly speaking, Projectile identifies projects like this:
+
+* Directories that contain the special `.projectile` file
+* Directories under version control (e.g. a Git repo)
+* Directories that contain some project description file (e.g. a `Gemfile` for Ruby projects or `pom.xml` for Java maven-based projects)
+
+While Projectile aims to recognize most project types out-of-the-box, it's also extremely
+flexible configuration-wise, and you can easily alter the project detection logic.
+
+TIP: If you'd like to override the default project detection functions you should
+check out `projectile-project-root-functions`. We'll discuss how to tweak in more
+details later in the documentation.
+
+=== Version Control Systems
+
+Projectile considers most version-controlled repos to be
+a project. Out of the box Projectile supports:
+
+* Git
+* Mercurial
+* Bazaar
+* Subversion
+* CVS
+* Fossil
+* Darcs
+
+=== File markers
+
+Projectile considers many files to denote the root of a project. Usually those files
+are the configuration files of various build tools. Out of the box the following are supported:
+
+|===
+| File | Project Type
+
+| rebar.config
+| Rebar project file
+
+| project.clj
+| Leiningen project file
+
+| build.boot
+| Boot-clj project file
+
+| deps.edn
+| Clojure CLI project file
+
+| SConstruct
+| Scons project file
+
+| pom.xml
+| Maven project file
+
+| build.sbt
+| SBT project file
+
+| build.sc
+| Mill project file
+
+| gradlew
+| Gradle wrapper script
+
+| build.gradle
+| Gradle project file
+
+| .ensime
+| Ensime configuration file
+
+| Gemfile
+| Bundler file
+
+| requirements.txt
+| Pip file
+
+| setup.py
+| Setuptools file
+
+| tox.ini
+| Tox file
+
+| composer.json
+| Composer project file
+
+| Cargo.toml
+| Cargo project file
+
+| mix.exs
+| Elixir mix project file
+
+| stack.yaml
+| Haskell's stack tool based project
+
+| dune-project
+| OCaml Dune project file
+
+| info.rkt
+| Racket package description file
+
+| DESCRIPTION
+| R package description file
+
+| TAGS
+| etags/ctags are usually in the root of project
+
+| GTAGS
+| GNU Global tags
+
+| configure.in
+| autoconf old style
+
+| configure.ac
+| autoconf new style
+
+| cscope.out
+| cscope
+
+| Makefile
+| Make
+
+| CMakeLists.txt
+| CMake
+
+| WORKSPACE
+| Bazel workspace file
+
+| debian/control
+| Debian package dpkg control file
+|===
+
+There's also Projectile's own `.projectile` which serves both as a project marker
+and a configuration file. We'll talk more about later in this section.
+
+== Adding Custom Project Types
+
+If a project you are working on is recognized incorrectly or you want
+to add your own type of projects you can add following to your Emacs
+initialization code
+
+[source,elisp]
+----
+(projectile-register-project-type 'npm '("package.json")
+                                  :project-file "package.json"
+				  :compile "npm install"
+				  :test "npm test"
+				  :run "npm start"
+				  :test-suffix ".spec")
+----
+
+What this does is:
+
+. add your own type of project, in this case `npm` package.
+. add a list of files and/or folders in a root of the project that helps to identify the type, in this case it is only `package.json`.
+. add _project-file_, which is typically the primary project configuration file. In this case that's `package.json`.
+. add _compile-command_, in this case it is `npm install`.
+. add _test-command_, in this case it is `npm test`.
+. add _run-command_, in this case it is `npm start`.
+. add test files suffix for toggling between implementation/test files, in this case it is `.spec`, so the implementation/test file pair could be `service.js`/`service.spec.js` for example.
+
+Let's see a couple of more complex examples.
+
+[source,elisp]
+----
+;; Ruby + RSpec
+(projectile-register-project-type 'ruby-rspec '("Gemfile" "lib" "spec")
+                                  :project-file "Gemfile"
+                                  :compile "bundle exec rake"
+                                  :src-dir "lib/"
+                                  :test "bundle exec rspec"
+                                  :test-dir "spec/"
+                                  :test-suffix "_spec")
+
+;; Ruby + Minitest
+(projectile-register-project-type 'ruby-test '("Gemfile" "lib" "test")
+                                  :project-file "Gemfile"
+                                  :compile"bundle exec rake"
+                                  :src-dir "lib/"
+                                  :test "bundle exec rake test"
+                                  :test-suffix "_test")
+
+;; Rails + Minitest
+(projectile-register-project-type 'rails-test '("Gemfile" "app" "lib" "db" "config" "test")
+                                  :project-file "Gemfile"
+                                  :compile "bundle exec rails server"
+                                  :src-dir "lib/"
+                                  :test "bundle exec rake test"
+                                  :test-suffix "_test")
+
+;; Rails + RSpec
+(projectile-register-project-type 'rails-rspec '("Gemfile" "app" "lib" "db" "config" "spec")
+                                  :project-file "Gemfile"
+                                  :compile "bundle exec rails server"
+                                  :src-dir "lib/"
+                                  :test "bundle exec rspec"
+                                  :test-dir "spec/"
+                                  :test-suffix "_spec")
+----
+
+All those projects are using `Gemfile` (``bundler``'s project file), but they have different directory structures.
+
+Bellow is a listing of all the available options for `projectile-register-project-type`:
+
+|===
+| Option | Documentation
+
+| :project-file
+| A file, relative to the project root, typically the main project file (e.g. `pom.xml` for Maven projects).
+
+| :compilation-dir
+| A path, relative to the project root, from where to run the tests and compilation commands.
+
+| :compile
+| A command to compile the project.
+
+| :configure
+| A command to configure the project. `%s` will be substituted with the project root.
+
+| :install
+| A function to install the project.
+
+| :package
+| A function to package the project.
+
+| :run
+| A command to run the project.
+
+| :src-dir
+| A path, relative to the project root, where the source code lives.  A function may also be specified which takes one parameter - the directory of a test file, and it should return the directory in which the implementation file should reside.  This option is only used for implementation/test toggling.
+
+| :test
+| A command to test the project.
+
+| :test-dir
+| A path, relative to the project root, where the test code lives.  A function may also be specified which takes one parameter - the directory of a file, and it should return the directory in which the test file should reside.  This option is only used for implementation/test toggling.
+
+| :test-prefix
+| A prefix to generate test files names.
+
+| :test-suffix
+| A suffix to generate test files names.
+
+| :related-files-fn
+| A function to specify test/impl/other files in a more flexible way.
+|===
+
+[discrete]
+==== Returning Projectile Commands from a function
+
+You can also pass a symbolic reference to a function into your project type definition if you wish to define the compile command dynamically:
+
+[source,elisp]
+----
+(defun my/compile-command ()
+  "Returns a String representing the compile command to run for the given context"
+  (cond
+   ((and (eq major-mode 'java-mode)
+         (not (string-match-p (regexp-quote "\\.*/test/\\.*") (buffer-file-name (current-buffer)))))
+    "./gradlew build")
+   ((eq major-mode 'web-mode)
+    "./gradlew compile-templates")
+   ))
+
+(defun my/test-command ()
+  "Returns a String representing the test command to run for the given context"
+  (cond
+   ((eq major-mode 'js-mode) "grunt test") ;; Test the JS of the project
+   ((eq major-mode 'java-mode) "./gradlew test") ;; Test the Java code of the project
+   ((eq major-mode 'my-mode) "special-command.sh") ;; Even Special conditions/test-sets can be covered
+   ))
+
+(projectile-register-project-type 'has-command-at-point '("file.txt")
+                                  :compile 'my/compile-command
+                                  :test 'my/test-command)
+----
+
+If you would now navigate to a file that has the `*.java` extension under the `./tests/` directory and hit `C-c c p` you
+will see `./gradlew build` as the suggestion. If you were to navigate to a HTML file the compile command will have switched
+to `./gradlew compile-templates`.
+
+This works for:
+
+* `:configure`
+* `:compile`
+* `:compilation-dir`
+* `:run`
+
+Note that your function has to return a string to work properly.
+
+=== Related file location
+
+The `:test-prefix` and `:test-suffix` will work regardless of file extension
+or directory path should and be enough for simple projects.  The
+`projectile-other-file-alist` variable can also be set to find other files
+based on the extension.
+
+For fine-grained control of implementation/test toggling, the `:test-dir` option
+of a project may take a function of one parameter (the implementation
+directory absolute path) and return the directory of the test file. This in
+conjunction with the options `:test-prefix` and `:test-suffix` will then be
+used to determine the full path of the test file. This option will always be
+respected if it is set.
+
+Similarly, the `:src-dir` option, the analogue of `:test-dir`, may also take a
+function and exhibits exactly the same behaviour as above except that its
+parameter corresponds to the directory of a test file and it should return the
+directory of the corresponding implementation file.
+
+It's recommended that either both or neither of these options are set to
+functions for consistent behaviour.
+
+Alternatively, for flexible file switching accross a range of projects,
+the `:related-files-fn` option set to a custom function or a
+list of custom functions can be used. The custom function accepts the relative
+file name from the project root and it should return related file information
+as a plist with the following optional key/value pairs:
+
+|===
+| Key | Value | Command applicable
+
+| :impl
+| matching implementation file if the given file is a test file
+| projectile-toggle-between-implementation-and-test, projectile-find-related-file
+
+| :test
+| matching test file if the given file has test files.
+| projectile-toggle-between-implementation-and-test, projectile-find-related-file
+
+| :other
+| any other files if the given file has them.
+| projectile-find-other-file, projectile-find-related-file
+
+| :foo
+| any key other than above
+| projectile-find-related-file
+|===
+
+For each value, following type can be used:
+
+|===
+| Type | Meaning
+
+| string / a list of strings
+| Relative paths from the project root. The paths which actually exist on the file system will be matched.
+
+| a function
+| A predicate which accepts a relative path as the input and return t if it matches.
+
+| nil
+| No match exists.
+|===
+
+Notes:
+
+. For a big project consisting of many source files, returning strings instead
+of a function can be fast as it does not iterate over each source file.
+. There is a difference in behaviour between no key and `nil` value for the
+key. Only when the key does not exist, other project options such as
+`:test_prefix` or `projectile-other-file-alist` mechanism is tried.
+. If the `:test-dir` option is set to a function, this will take precedence over
+any value for `:related-files-fn` set when `projectile-toggle-between-implementation-and-test` is called.
+
+==== Example - Same source file name for test and impl
+
+[source,elisp]
+----
+(defun my/related-files (path)
+  (if (string-match (rx (group (or "src" "test")) (group "/" (1+ anything) ".cpp")) path)
+      (let ((dir (match-string 1 path))
+            (file-name (match-string 2 path)))
+        (if (equal dir "test")
+            (list :impl (concat "src" file-name))
+          (list :test (concat "test" file-name)
+                :other (concat "src" file-name ".def"))))))
+
+(projectile-register-project-type
+   ;; ...
+   :related-files-fn #'my/related-files)
+----
+
+With the above example, src/test directory can contain the same name file for test and its implementation file.
+For example, "src/foo/abc.cpp" will match to "test/foo/abc.cpp" as test file and "src/foo/abc.cpp.def" as other file.
+
+==== Example - Different test prefix per extension
+
+A custom function for the project using multiple programming languages with different test prefixes.
+
+[source,elisp]
+----
+(defun my/related-files(file)
+  (let ((ext-to-test-prefix '(("cpp" . "Test")
+                              ("py" . "test_"))))
+    (if-let ((ext (file-name-extension file))
+             (test-prefix (assoc-default ext ext-to-test-prefix))
+             (file-name (file-name-nondirectory file)))
+        (if (string-prefix-p test-prefix file-name)
+            (let ((suffix (concat "/" (substring file-name (length test-prefix)))))
+              (list :impl (lambda (other-file)
+                            (string-suffix-p suffix other-file))))
+          (let ((suffix (concat "/" test-prefix file-name)))
+            (list :test (lambda (other-file)
+                          (string-suffix-p suffix other-file))))))))
+----
+
+`projectile-find-related-file` command is also available to find and choose
+related files of any kinds. For example, the custom function can specify the
+related documents with ':doc' key. Note that `projectile-find-related-file` only
+relies on `:related-files-fn` for now.
+
+=== Related file custom function helper
+
+`:related-files-fn` can accept a list of custom functions to combine the result
+of each custom function. This allows users to write several custom functions
+and apply them differently to projects.
+
+Projectile includes a couple of helpers to generate commonly used custom functions.
+
+|===
+| Helper name and params | Purpose
+
+| groups KIND GROUPS
+| Relates files in each group as the specified kind.
+
+| extensions KIND EXTENSIONS
+| Relates files with extensions as the specified kind.
+
+| test-with-prefix EXTENSION PREFIX
+| Relates files with prefix and extension as :test and :impl.
+
+| test-with-suffix EXTENSION SUFFIX
+| Relates files with suffix and extension as :test and :impl.
+|===
+
+Each helper means `projectile-related-files-fn-helper-name` function.
+
+==== Example usage of projectile-related-files-fn-helpers
+
+[source,elisp]
+----
+(setq my/related-files
+      (list
+       (projectile-related-files-fn-extensions :other '("cpp" "h" "hpp"))
+       (projectile-related-files-fn-test-with-prefix "cpp" "Test")
+       (projectile-related-files-fn-test-with-suffix "el" "_test")
+       (projectile-related-files-fn-groups
+        :doc
+        '(("doc/common.txt"
+           "src/foo.h"
+           "src/bar.h")))))
+
+(projectile-register-project-type
+   ;; ...
+   :related-files-fn my/related-files)
+----
+
+=== Editing Existing Project Types
+
+You can also edit specific options of already existing project types:
+
+[source,elisp]
+----
+(projectile-update-project-type
+ 'sbt
+ :related-files-fn
+ (list
+  (projectile-related-files-fn-test-with-suffix "scala" "Spec")
+  (projectile-related-files-fn-test-with-suffix "scala" "Test")))
+----
+
+This will keep all existing options for the `sbt` project type, but change the value of the `related-files-fn` option.
+
+
+=== `:test-dir`/`:src-dir` vs `:related-files-fn`
+
+Setting the `:test-dir` and `:src-dir` options to functions is useful if the
+test location for a given implementation file is almost always going to be in
+the same place accross all projects belonging to a given project type, `maven`
+projects are an example of this:
+
+[source,elisp]
+----
+(projectile-update-project-type
+ 'maven
+ :src-dir
+ (lambda (file-path) (projectile-complementary-dir file-path "test" "main"))
+ :test-dir
+ (lambda (file-path) (projectile-complementary-dir file-path "main" "test")))
+----
+
+If instead you work on a lot of elisp projects using `eldev`, the
+`:related-files-fn` option may be more appropriate since the test locations tend
+to vary accross projects:
+
+[source,elisp]
+----
+(projectile-update-project-type
+ 'emacs-eldev
+ :related-files-fn
+ (list
+  (projectile-related-files-fn-test-with-suffix "el" "-test")
+  (projectile-related-files-fn-test-with-prefix "el" "test-")))
+----
+
+== Customizing Project Detection
+
+Project detection is pretty simple - Projectile just runs a list of
+project detection functions
+(`projectile-project-root-functions`) until one of them returns
+a project directory.
+
+This list of functions is customizable, and while Projectile has some
+defaults for it, you can tweak it however you see fit.
+
+Let's take a closer look at `projectile-project-root-functions`:
+
+[source,elisp]
+----
+(defcustom projectile-project-root-functions
+  '(projectile-root-local
+    projectile-root-bottom-up
+    projectile-root-top-down
+    projectile-root-top-down-recurring)
+  "A list of functions for finding project roots."
+  :group 'projectile
+  :type '(repeat function))
+----
+
+The important thing to note here is that the functions get invoked in their
+order on the list, so the functions earlier in the list will have a higher
+precedence with respect to project detection. Let's examine the defaults:
+
+* `projectile-root-local` looks for project path set via the buffer-local variable `projectile-project-root`. Typically you'd set this variable via `.dir-locals.el` and it will take precedence over everything else.
+
+* `projectile-root-bottom-up` will start looking for a project marker file/folder(e.g. `.projectile`, `.hg`, `.git`) from the current folder (a.k.a. `default-directory` in Emacs lingo) up the directory tree. It will return the first match it discovers. The assumption is pretty simple - the root marker appear only once, at the root folder of a project. If a root marker appear in several nested folders (e.g. you've got nested git projects), the bottom-most (closest to the current dir) match has precedence. You can customize the root markers recognized by this function via `projectile-project-root-functions`
+
+* `projectile-root-top-down` is similar, but it will return the top-most (farthest from the current directory) match. It's configurable via `projectile-project-root-files` and all project manifest markers like `pom.xml`, `Gemfile`, `project.clj`, etc go there.
+
+* `projectile-root-top-down-recurring` will look for project markers that can appear at every level of a project (e.g. `Makefile` or `.svn`) and will return the top-most match for those.
+
+The default ordering should work well for most people, but depending on the structure of your project you might want to tweak it.
+
+Re-ordering those functions will alter the project detection, but you can also replace the list. Here's how you can delegate the project detection to Emacs's built-in function `vc-root-dir`:
+
+[source,elisp]
+----
+;; we need this wrapper to match Projectile's API
+(defun projectile-vc-root-dir (dir)
+  "Retrieve the root directory of the project at DIR using `vc-root-dir'."
+  (let ((default-directory dir))
+    (vc-root-dir)))
+
+(setq projectile-project-root-functions '(projectile-vc-root-dir))
+----
+
+Similarly, you can leverage the built-in `project.el` like this:
+
+[source,elisp]
+----
+;; we need this wrapper to match Projectile's API
+(defun projectile-project-current (dir)
+  "Retrieve the root directory of the project at DIR using `project-current'."
+  (cdr (project-current nil dir)))
+
+(setq projectile-project-root-functions '(projectile-project-current))
+----
+
+== Ignoring files
+
+WARNING: The contents of `.projectile` are ignored when using the
+ `alien` project indexing method.
+
+If you'd like to instruct Projectile to ignore certain files in a
+project, when indexing it you can do so in the `.projectile` file by
+adding each path to ignore, where the paths all are relative to the
+root directory and start with a slash. Everything ignored should be
+preceded with a `-` sign. Alternatively, not having any prefix at all
+also means to ignore the directory or file pattern that follows.
+Here's an example for a typical Rails application:
+
+----
+-/log
+-/tmp
+-/vendor
+-/public/uploads
+----
+
+This would ignore the folders only at the root of the project.
+Projectile also supports relative pathname ignores:
+
+----
+-tmp
+-*.rb
+-*.yml
+-models
+----
+
+You can also ignore everything except certain subdirectories. This is
+useful when selecting the directories to keep is easier than selecting
+the directories to ignore, although you can do both. To select
+directories to keep, that means everything else will be ignored.
+
+Example:
+
+----
++/src/foo
++/tests/foo
+----
+
+Keep in mind that you can only include subdirectories, not file
+patterns.
+
+If both directories to keep and ignore are specified, the directories
+to keep first apply, restricting what files are considered. The paths
+and patterns to ignore are then applied to that set.
+
+Finally, you can override ignored files. This is especially useful
+when some files ignored by your VCS should be considered as part of
+your project by projectile:
+
+----
+!/src/foo
+!*.yml
+----
+
+When a path is overridden, its contents are still subject to ignore
+patterns. To override those files as well, specify their full path
+with a bang prefix.
+
+If you would like to include comment lines in your .projectile file,
+you can customize the variable `projectile-dirconfig-comment-prefix`.
+Assigning it a non-nil character value, e.g. `#`, will cause lines in
+the .projectile file starting with that character to be treated as
+comments instead of patterns.
+
+=== File-local project root definitions
+
+If you want to override the projectile project root for a specific
+file, you can set the file-local variable `projectile-project-root`. This
+can be useful if you have files within one project that are related to
+a different project (for instance, Org files in one git repo that
+correspond to other projects).
+
+== Storing project settings
+
+From project to project, some things may differ even in the same
+language - coding styles, auto-completion sources, etc.  If you need
+to set some variables according to the selected project, you can use a
+standard Emacs feature called
+http://www.gnu.org/software/emacs/manual/html_node/emacs/Directory-Variables.html[Per-directory Local Variables].
+To use it you must create a file named `.dir-locals.el` (as specified
+by the constant `dir-locals-file`) inside the project directory.  This
+file should contain something like this:
+
+[source,elisp]
+----
+((nil . ((secret-ftp-password . "secret")
+         (compile-command . "make target-x")
+         (eval . (progn
+                   (defun my-project-specific-function ()
+                     ;; ...
+                     )))))
+ (c-mode . ((c-file-style . "BSD"))))
+----
+
+The top-level alist member referenced with the key `nil` applies to
+the entire project.  A key with the name `eval` will evaluate its
+corresponding value.  In the example above, this is used to create a
+function.  It could also be used to e.g. add such a function to a key
+map.
+
+TIP: You can also quickly visit or create the `dir-locals-file` with
+kbd:[s-p E] (kbd:[M-x] `projectile-edit-dir-locals` kbd:[RET]).
+
+Here are a few examples of how to use this feature with Projectile.
+
+== Configuring Projectile's Behavior
+
+Projectile exposes many variables (via `defcustom`) which allow users
+to customize its behavior.  Directory variables can be used to set
+these customizations on a per-project basis.
+
+You could enable caching for a project in this way:
+
+[source,elisp]
+----
+((nil . ((projectile-enable-caching . t))))
+----
+
+If one of your projects had a file that you wanted Projectile to
+ignore, you would customize Projectile by:
+
+[source,elisp]
+----
+((nil . ((projectile-globally-ignored-files . ("MyBinaryFile")))))
+----
+
+If you wanted to wrap the git command that Projectile uses to list
+the files in you repository, you could do:
+
+[source,elisp]
+----
+((nil . ((projectile-git-command . "/path/to/other/git ls-files -zco --exclude-standard"))))
+----
+
+If you want to use a different project name than how Projectile named
+your project, you could customize it with the following:
+
+[source,elisp]
+----
+((nil . ((projectile-project-name . "your-project-name-here"))))
+----
+
+By default, compilation buffers are not writable, which allows you to
+e.g.  press `g` to restart the last command. Setting
+`projectile-<cmd>-use-comint-mode` (where `<cmd>` is `configure`,
+`compile`, `test`, `install`, `package`, or `run`) to a non-nil value
+allows you to make projectile compilation buffers interactive, letting
+you e.g. test a command-line program with `projectile-run-project`.
+
+[source,elisp]
+----
+(setq projectile-comint-mode t)
+----
+
+== Configure a Project's Lifecycle Commands
+
+There are a few variables that are intended to be customized via `.dir-locals.el`.
+
+* for configuration - `projectile-project-configure-cmd`
+* for compilation - `projectile-project-compilation-cmd`
+* for testing - `projectile-project-test-cmd`
+* for installation - `projectile-project-install-cmd`
+* for packaging - `projectile-project-package-cmd`
+* for running - `projectile-project-run-cmd`
+
+When these variables have their default value of `nil`, Projectile
+runs the default command for the current project type.  You can
+override this behavior by setting them to either a string to run an
+external command or an Emacs Lisp function:
+
+[source,elisp]
+----
+(setq projectile-test-cmd #'custom-test-function)
+----
+
diff -pruN 2.1.0-1.1/doc/modules/ROOT/pages/support.adoc 2.5.0-1/doc/modules/ROOT/pages/support.adoc
--- 2.1.0-1.1/doc/modules/ROOT/pages/support.adoc	1970-01-01 00:00:00.000000000 +0000
+++ 2.5.0-1/doc/modules/ROOT/pages/support.adoc	2021-08-10 10:11:43.000000000 +0000
@@ -0,0 +1,39 @@
+= Support
+
+Projectile currently has several official & unofficial support channels.
+
+For questions, suggestions and support refer to one of them.  Please, don't
+use the support channels to report issues, as this makes them harder to track.
+
+== Gitter
+
+Most internal discussions about the development of Projectile happen on its
+https://gitter.im/bbatsov/projectile[gitter channel].  You can often find
+Projectile's maintainers there and get some interesting news from the project's
+kitchen.
+
+== Mailing List
+
+The https://groups.google.com/forum/#!forum/projectile[official mailing list] is
+hosted at Google Groups. It's a low-traffic list, so don't be too hesitant to subscribe.
+
+== Freenode
+
+If you're into IRC you can visit the `#projectile` channel on Freenode.
+It's not actively
+monitored by the Projectile maintainers themselves, but still you can get support
+from other Projectile users there.
+
+== Stackoverflow
+
+We're also encouraging users to ask Projectile-related questions on StackOverflow.
+
+When doing so you should use the
+http://stackoverflow.com/questions/tagged/projectile[Projectile] tag (ideally combined
+with the tag `emacs`).
+
+== Bountysource
+
+If you're willing to pay for some feature to be implemented you can use
+https://www.bountysource.com/teams/projectile/issues[Bountysource] to place a
+bounty for the work you want to be done.
diff -pruN 2.1.0-1.1/doc/modules/ROOT/pages/troubleshooting.adoc 2.5.0-1/doc/modules/ROOT/pages/troubleshooting.adoc
--- 2.1.0-1.1/doc/modules/ROOT/pages/troubleshooting.adoc	1970-01-01 00:00:00.000000000 +0000
+++ 2.5.0-1/doc/modules/ROOT/pages/troubleshooting.adoc	2021-08-10 10:11:43.000000000 +0000
@@ -0,0 +1,74 @@
+= Troubleshooting
+
+In case you run into issues here are a few tips that can help you diagnose the
+problem.
+
+Generally, it's not a bad idea to configure Emacs to spit the backtrace on error
+(instead of just logging the error in the `+*Messages*+` buffer). You can toggle
+this behavior by using kbd:[M-x] `toggle-debug-on-error`.
+
+== Debugging Projectile commands
+
+Emacs features a super powerful built-in
+http://www.gnu.org/software/emacs/manual/html_node/elisp/Edebug.html[Emacs Lisp debugger]
+and using it is the best way to diagnose problems of any kind.
+
+TIP: Here's a https://www.youtube.com/watch?v=odkYXXYOxpo[great crash course] on
+ using the debugger.
+
+To debug some command you need to do the following:
+
+* Figure out the name of the command you want to debug (e.g. by using kbd:[C-h k]
+to see which command is associated with some keybinding)
+* Find the source of the command (e.g. by using kbd:[M-x] `find-function`
+kbd:[RET] `function-name`)
+* Press kbd:[C-u C-M-x] while in the body of the function
+* Run the command again
+
+At this point you'll be dropped in the debugger and you can step forward until
+you find the problem.
+
+== Profiling Projectile commands
+
+Emacs comes with a https://www.gnu.org/software/emacs/manual/html_node/elisp/Profiling.html[built-in
+profiler]. Using
+it is pretty simple:
+
+. Start it with kbd:[M-x] `profiler-start`.
+. Invoke some commands.
+. Get the report with kbd:[M-x] `profiler-report`.
+
+TIP: If you intend to share the profiling results with someone it's a good idea to
+ save the report buffer to a file with kbd:[C-x C-w].
+
+== Commonly encountered problems (and how to solve them)
+
+=== Using some command causes Emacs to freeze for a while
+
+Sometimes a Projectile command might hang for a while (e.g. due to a bug or a
+configuration issue). Such problems are super annoying, but are relatively easy
+to debug. Here are a few steps you can take in such situations:
+
+* Do kbd:[M-x] `toggle-debug-on-quit`
+* Reproduce the problem
+* Hit kbd:[C-g] around 10 seconds into the hang
+
+This will bring up a backtrace with the entire function stack, including
+function arguments. So you should be able to figure out what's going on (or at
+least what's being required).
+
+=== I upgraded Projectile using `package.el` and nothing changed
+
+Emacs doesn't load the new files, it only installs them on disk.  To see the
+effect of changes you have to restart Emacs.
+
+=== Some commands not working properly with the fish shell
+
+I'm not sure what's causing this (likely different quoting rules), but it's easy to fix it:
+
+[source,elisp]
+----
+(setq shell-file-name "/bin/bash")
+----
+
+In general, I've noticed that Emacs doesn't play very well with fish.
diff -pruN 2.1.0-1.1/doc/modules/ROOT/pages/usage.adoc 2.5.0-1/doc/modules/ROOT/pages/usage.adoc
--- 2.1.0-1.1/doc/modules/ROOT/pages/usage.adoc	1970-01-01 00:00:00.000000000 +0000
+++ 2.5.0-1/doc/modules/ROOT/pages/usage.adoc	2021-08-10 10:11:43.000000000 +0000
@@ -0,0 +1,376 @@
+= Usage
+
+NOTE: Everything in this section assumes you've enabled `projectile-mode`.
+
+== Basic setup
+
+In this section we'll cover the bare minimum of setup you might want to
+do. Projectile works fine with no setup, but if you tweak the configuration a
+bit you'll get more out of it.
+
+Check out the xref:configuration.adoc["Configuration"] section of the manual
+for a lot more information about configuring Projectile.
+
+=== Automated Project Discovery
+
+To add a project to Projectile's list of known projects, open a file
+in the project. If you have a projects directory, you can tell
+Projectile about all of the projects in it with the command `M-x
+projectile-discover-projects-in-directory`.
+
+You can go one step further and set a list of folders which Projectile
+is automatically going to check for projects on startup.
+
+Recursive discovery is configured by specifying the search depth in a cons cell:
+
+[source,elisp]
+----
+(setq projectile-project-search-path '("~/projects/" "~/work/" ("~/github" . 1)))
+----
+
+
+You can suppress the auto-discovery of projects on startup by setting
+`projectile-auto-discover` to `nil`. You can manually trigger the project
+discovery using `M-x projectile-discover-projects-in-search-path`.
+
+=== Minibuffer Completion
+
+While Projectile works fine with Emacs's default minibuffer completion system you're highly encouraged to use some
+powerful alternative like `ido`, `ivy` or `selectrum`.
+
+TIP: If you're going to use the `ido` completion it's **highly** recommended that you install the optional
+https://github.com/lewang/flx[flx-ido package], which provides a much more powerful
+alternative to ``ido``'s built-in `flex` matching. Similarly, for `selectrum` it's
+a good idea to enable `prescient` (a package similar to `flx`).
+
+=== Installing External Tools
+
+NOTE: Windows users can ignore this section unless they are using Emacs via WSL or `cygwin`.
+
+It's recommended to install the following command-line tools:
+
+* `fd` (a super-fast alternative to `find`)
+* `ag` (a.k.a. `the_silver_searcher`, a powerful alternative to `grep`) or `rg` (a.k.a. `ripgrep`)
+
+Projectile will make use of them automatically when available, and fallback to the standard Unix tools otherwise.
+
+== Basic Usage
+
+Just open some file in a version-controlled (e.g. `git`) or a project
+(e.g. `maven`) directory that's recognized by Projectile and you're
+ready for action. Projectile happens to recognize out of the box every common
+VCS and many popular project types for various programming languages.
+You can learn more about Projectile's notion of a project xref:projects.adoc[here].
+
+NOTE: The extent of the support for every VCS differs and Git is the best supported
+ one. Projectile supports some advanced features like working with Git submodules
+ and using `git-grep` instead GNU grep.
+
+You need to know only a handful of Projectile commands to start benefiting from it.
+
+* Find file in current project (kbd:[s-p f])
+* Switch project (kbd:[s-p p]) (you can also switch between open projects with kbd:[s-p q])
+* Grep (search for text/regexp) in project (kbd:[s-p s g]) (`grep` alternatives like `ag`, `pt` and `rg` are also supported)
+* Replace in project (kbd:[s-p r])
+* Invoke any Projectile command via the Projectile Commander (kbd:[s-p m])
+* Toggle between implementation and test (kbd:[s-p t])
+* Toggle between related files (e.g. `foo.h` <-> `foo.c` and `Gemfile` <-> `Gemfile.lock`) (kbd:[s-p a])
+* Run a shell command in the root of the project (kbd:[s-p !] for a sync command and kbd:[s-p &] for an async command)
+* Run various pre-defined project commands like:
+** build/compile project (kbd:[s-p c])
+** test project (kbd:[s-p T])
+
+The next section lists many more commands, but the basics can get you pretty far.
+
+== Interactive Commands
+
+NOTE: Projectile doesn't have a default key prefix for its commands, but all the examples
+ in the manual assume you've opted for kbd:[s-p] (`super`-p).
+
+Here's a list of the interactive Emacs Lisp functions, provided by Projectile:
+
+|===
+| Keybinding | Description
+
+| kbd:[s-p f]
+| Display a list of all files in the project. With a prefix argument it will clear the cache first.
+
+| kbd:[s-p F]
+| Display a list of all files in all known projects.
+
+| kbd:[s-p g]
+| Display a list of all files at point in the project. With a prefix argument it will clear the cache first.
+
+| kbd:[s-p 4 f]
+| Jump to a project's file using completion and show it in another window.
+
+| kbd:[s-p 4 g]
+| Jump to a project's file based on context at point and show it in another window.
+
+| kbd:[s-p 5 f]
+| Jump to a project's file using completion and show it in another frame.
+
+| kbd:[s-p 5 g]
+| Jump to a project's file based on context at point and show it in another frame.
+
+| kbd:[s-p d]
+| Display a list of all directories in the project. With a prefix argument it will clear the cache first.
+
+| kbd:[s-p 4 d]
+| Switch to a project directory and show it in another window.
+
+| kbd:[s-p 5 d]
+| Switch to a project directory and show it in another frame.
+
+| kbd:[s-p T]
+| Display a list of all test files(specs, features, etc) in the project.
+
+| kbd:[s-p l]
+| Display a list of all files in a directory (that's not necessarily a project)
+
+| kbd:[s-p s g]
+| Run grep on the files in the project.
+
+| kbd:[M-- s-p s g]
+| Run grep on `projectile-grep-default-files` in the project.
+
+| kbd:[s-p v]
+| Run `vc-dir` on the root directory of the project.
+
+| kbd:[s-p V]
+| Browse dirty version controlled projects.
+
+| kbd:[s-p b]
+| Display a list of all project buffers currently open.
+
+| kbd:[s-p 4 b]
+| Switch to a project buffer and show it in another window.
+
+| kbd:[s-p 5 b]
+| Switch to a project buffer and show it in another frame.
+
+| kbd:[s-p 4 C-o]
+| Display a project buffer in another window without selecting it.
+
+| kbd:[s-p a]
+| Switch between files with the same name but different extensions.
+
+| kbd:[s-p 4 a]
+| Switch between files with the same name but different extensions in other window.
+
+| kbd:[s-p 5 a]
+| Switch between files with the same name but different extensions in other frame.
+
+| kbd:[s-p o]
+| Runs `multi-occur` on all project buffers currently open.
+
+| kbd:[s-p r]
+| Runs interactive query-replace on all files in the projects.
+
+| kbd:[s-p i]
+| Invalidates the project cache (if existing).
+
+| kbd:[s-p R]
+| Regenerates the projects `TAGS` file.
+
+| kbd:[s-p j]
+| Find tag in project's `TAGS` file.
+
+| kbd:[s-p k]
+| Kills all project buffers.
+
+| kbd:[s-p D]
+| Opens the root of the project in `dired`.
+
+| kbd:[s-p 4 D]
+| Opens the root of the project in `dired` in another window.
+
+| kbd:[s-p 5 D]
+| Opens the root of the project in `dired` in another frame.
+
+| kbd:[s-p e]
+| Shows a list of recently visited project files.
+
+| kbd:[s-p left]
+| Switch to the previous project buffer.
+
+| kbd:[s-p right]
+| Switch to the next project buffer.
+
+| kbd:[s-p E]
+| Opens the root `dir-locals-file` of the project.
+
+| kbd:[s-p s s]
+| Runs `ag` on the project, performing a literal search. Requires the presence of `ag.el`. With a prefix argument it will perform a regex search.
+
+| kbd:[s-p !]
+| Runs `shell-command` in the root directory of the project.
+
+| kbd:[s-p &]
+| Runs `async-shell-command` in the root directory of the project.
+
+| kbd:[s-p C]
+| Runs a standard configure command for your type of project.
+
+| kbd:[s-p c]
+| Runs a standard compilation command for your type of project.
+
+| kbd:[s-p P]
+| Runs a standard test command for your type of project.
+
+| kbd:[s-p t]
+| Toggle between an implementation file and its test file.
+
+| kbd:[s-p 4 t]
+| Jump to implementation or test file in other window.
+
+| kbd:[s-p 5 t]
+| Jump to implementation or test file in other frame.
+
+| kbd:[s-p z]
+| Adds the currently visited file to the cache.
+
+| kbd:[s-p p]
+| Display a list of known projects you can switch to.
+
+| kbd:[s-p q]
+| Display a list of open projects you can switch to.
+
+| kbd:[s-p S]
+| Save all project buffers.
+
+| kbd:[s-p m]
+| Run the commander (an interface to run commands with a single key).
+
+| kbd:[s-p x e]
+| Start or visit an `eshell` for the project.
+
+| kbd:[s-p x i]
+| Start or visit an `ielm` (Elisp REPL) for the project.
+
+| kbd:[s-p x t]
+| Start or visit an `ansi-term` for the project.
+
+| kbd:[s-p x s]
+| Start or visit a `shell` for the project.
+
+| kbd:[s-p x g]
+| Start or visit a `gdb` for the project.
+
+| kbd:[s-p x v]
+| Start or visit a `vterm` for the project.
+
+| kbd:[s-p ESC]
+| Switch to the most recently selected Projectile buffer.
+|===
+
+If you ever forget any of Projectile's keybindings just do a:
+
+kbd:[s-p C-h]
+
+== Customizing Projectile's Keybindings
+
+It is possible to add additional commands to
+`projectile-command-map` referenced by the prefix key in
+`projectile-mode-map`. You can add multiple keymap prefix for all
+commands. Here's an example that adds `super-,` as a command prefix:
+
+[source,elisp]
+----
+(define-key projectile-mode-map (kbd "s-,") 'projectile-command-map)
+----
+
+You can also bind the `projectile-command-map` to any other map you'd
+like (including the global keymap).
+
+TIP: For some common commands you might want to take a little shortcut and
+leverage the fairly unused `Super` key (by default `Command` on Mac
+keyboards and `Windows` on Win keyboards).
+
+Here's something you can
+add to your Emacs config:
+
+[source,elisp]
+----
+(define-key projectile-mode-map [?\s-d] 'projectile-find-dir)
+(define-key projectile-mode-map [?\s-p] 'projectile-switch-project)
+(define-key projectile-mode-map [?\s-f] 'projectile-find-file)
+(define-key projectile-mode-map [?\s-g] 'projectile-grep)
+----
+
+NOTE: Note that the `Super` keybindings are not usable in Windows, as Windows
+ makes heavy use of such keybindings itself. Emacs Prelude already adds those
+ extra keybindings.
+
+== Projectile Commander
+
+Projectile's Commander (`projectile-commander`) is a nifty utility for those of you who are struggling to remember a lot of keybindings. It provides a simple
+interface to most of Projectile's commands via 1-character shortcuts that you
+need to press after invoking the commander (e.g. via kbd:[s-p m]).
+
+The commander was created with the idea to provide a powerful project switching command (it will be triggered if you press kbd:[C-u s-p p]), but it's very useful on its own as well.
+
+|===
+| Keybinding | Description
+| kbd:[?]
+| Commander help buffer.
+
+| kbd:[D]
+| Open project root in dired.
+
+| kbd:[R]
+| Regenerate the project's etags/gtags.
+
+| kbd:[T]
+| Find test file in project.
+
+| kbd:[V]
+| Browse dirty projects
+
+| kbd:[a]
+| Run ag on project.
+
+| kbd:[b]
+| Switch to project buffer.
+
+| kbd:[d]
+| Find directory in project.
+
+| kbd:[e]
+| Find recently visited file in project.
+
+| kbd:[f]
+| Find file in project.
+
+| kbd:[g]
+| Run grep on project.
+
+| kbd:[j]
+| Find tag in project.
+
+| kbd:[k]
+| Kill all project buffers.
+
+| kbd:[o]
+| Run multi-occur on project buffers.
+
+| kbd:[r]
+| Replace a string in the project.
+
+| kbd:[s]
+| Switch project.
+
+| kbd:[v]
+| Open project root in vc-dir or magit.
+|===
+
+You can add additional commands to the commander like this:
+
+[source,elisp]
+----
+(def-projectile-commander-method ?f
+  "Find file in project."
+  (projectile-find-file))
+----
+
+Place such snippets after ``projectile-mode``'s init code.
diff -pruN 2.1.0-1.1/doc/projects.md 2.5.0-1/doc/projects.md
--- 2.1.0-1.1/doc/projects.md	2020-02-04 18:30:35.000000000 +0000
+++ 2.5.0-1/doc/projects.md	1970-01-01 00:00:00.000000000 +0000
@@ -1,417 +0,0 @@
-## Supported Project Types
-
-One of the main goals of Projectile is to operate on a wide range of project types
-without the need for any configuration. To achieve this it contains a lot of
-project detection logic and project type specific logic.
-
-### Version Control Systems
-
-Projectile considers most version-controlled repos to be
-a project. Out of the box Projectile supports:
-
-* Git
-* Mercurial
-* Bazaar
-* Subversion
-* CVS
-* Fossil
-* Darcs
-
-### File markers
-
-Projectile considers many files to denote the root of a project. Usually those files
-are the configuration files of various build tools. Out of the box the following are supported:
-
-File              |  Project Type
-------------------|----------------------
-rebar.config      | Rebar project file
-project.clj       | Leiningen project file
-build.boot        | Boot-clj project file
-deps.edn          | Clojure CLI project file
-SConstruct        | Scons project file
-pom.xml           | Maven project file
-build.sbt         | SBT project file
-gradlew           | Gradle wrapper script
-build.gradle      | Gradle project file
-.ensime           | Ensime configuration file
-Gemfile           | Bundler file
-requirements.txt  | Pip file
-setup.py          | Setuptools file
-tox.ini           | Tox file
-composer.json     | Composer project file
-Cargo.toml        | Cargo project file
-mix.exs           | Elixir mix project file
-stack.yaml        | Haskell's stack tool based project
-info.rkt          | Racket package description file
-DESCRIPTION       | R package description file
-TAGS              | etags/ctags are usually in the root of project
-GTAGS             | GNU Global tags
-configure.in      | autoconf old style
-configure.ac      | autoconf new style
-cscope.out        | cscope
-Makefile          | Make
-
-There's also Projectile's own `.projectile` which serves both as a project marker
-and a configuration file. We'll talk more about later in this section.
-
-## Adding Custom Project Types
-
-If a project you are working on is recognized incorrectly or you want
-to add your own type of projects you can add following to your Emacs
-initialization code
-
-```el
-(projectile-register-project-type 'npm '("package.json")
-				  :compile "npm install"
-				  :test "npm test"
-				  :run "npm start"
-				  :test-suffix ".spec")
-```
-
-What this does is:
-
-  1. add your own type of project, in this case `npm` package.
-  2. add a file in a root of the project that helps to identify the type, in this case it is `package.json`.
-  3. add *compile-command*, in this case it is `npm install`.
-  4. add *test-command*, in this case it is `npm test`.
-  5. add *run-command*, in this case it is `npm start`.
-  6. add test files suffix for toggling between implementation/test files, in this case it is `.spec`, so the implementation/test file pair could be `service.js`/`service.spec.js` for example.
-
-The available options are:
-
-Option            | Documentation
-------------------|--------------------------------------------------------------------------------------------
-:compilation-dir  | A path, relative to the project root, from where to run the tests and compilation commands.
-:compile          | A command to compile the project.
-:configure        | A command to configure the project. `%s` will be substituted with the project root.
-:run              | A command to run the project.
-:src-dir          | A path, relative to the project root, where the source code lives.
-:test             | A command to test the project.
-:test-dir         | A path, relative to the project root, where the test code lives.
-:test-prefix      | A prefix to generate test files names.
-:test-suffix      | A suffix to generate test files names.
-:related-files-fn | A function to specify test/impl/other files in a more flexible way.
-
-#### Returning Projectile Commands from a function
-
-You can also pass a symbolic reference to a function into your project type definition if you wish to define the compile command dynamically:
-
-```el
-(defun my/compile-command ()
-  "Returns a String representing the compile command to run for the given context"
-  (cond
-   ((and (eq major-mode 'java-mode)
-         (not (string-match-p (regexp-quote "\\.*/test/\\.*") (buffer-file-name (current-buffer)))))
-    "./gradlew build")
-   ((eq major-mode 'web-mode)
-    "./gradlew compile-templates")
-   ))
-
-(defun my/test-command ()
-  "Returns a String representing the test command to run for the given context"
-  (cond
-   ((eq major-mode 'js-mode) "grunt test") ;; Test the JS of the project
-   ((eq major-mode 'java-mode) "./gradlew test") ;; Test the Java code of the project
-   ((eq major-mode 'my-mode) "special-command.sh") ;; Even Special conditions/test-sets can be covered
-   ))
-
-(projectile-register-project-type 'has-command-at-point '("file.txt")
-                                  :compile 'my/compile-command
-                                  :test 'my/test-command)
-```
-
-If you would now navigate to a file that has the `*.java` extension under the `./tests/` directory and hit `C-c c p` you
-will see `./gradlew build` as the suggestion. If you were to navigate to a HTML file the compile command will have switched
-to `./gradlew compile-templates`.
-
-This works for:
-
-  * `:configure`
-  * `:compile`
-  * `:compilation-dir`
-  * `:run`
-
-Note that your function has to return a string to work properly.
-
-### Related file location
-
-For simple projects, `:test-prefix` and `:test-suffix` option with string will
-be enough to specify test prefix/suffix applicable regardless of file extensions
-on any directory path. `projectile-other-file-alist` variable can be also set to
-find other files based on the extension.
-
-For the full control of finding related files, `:related-files-fn` option with a
-custom function or a list of custom functions can be used. The custom function
-accepts the relative file name from the project root and it should return the
-related file information as plist with the following optional key/value pairs:
-
-| Key    | Value                                                         | Command applicable                                                              |
-|--------|---------------------------------------------------------------|---------------------------------------------------------------------------------|
-| :impl  | matching implementation file if the given file is a test file | projectile-toggle-between-implementation-and-test, projectile-find-related-file |
-| :test  | matching test file if the given file has test files.          | projectile-toggle-between-implementation-and-test, projectile-find-related-file |
-| :other | any other files if the given file has them.                   | projectile-find-other-file, projectile-find-related-file                        |
-| :foo   | any key other than above                                      | projectile-find-related-file                                                    |
-
-
-For each value, following type can be used:
-
-| Type                       | Meaning                                                                                                  |
-|----------------------------|----------------------------------------------------------------------------------------------------------|
-| string / a list of strings | Relative paths from the project root. The paths which actually exist on the file system will be matched. |
-| a function                 | A predicate which accepts a relative path as the input and return t if it matches.                       |
-| nil                        | No match exists.                                                                                         |
-
-Notes:
- 1. For a big project consisting of many source files, returning strings instead
-    of a function can be fast as it does not iterate over each source file.
- 2. There is a difference in behaviour between no key and `nil` value for the
-    key. Only when the key does not exist, other project options such as
-    `:test_prefix` or `projectile-other-file-alist` mechanism is tried.
-
-
-#### Example - Same source file name for test and impl
-
-```el
-(defun my/related-files (path)
-  (if (string-match (rx (group (or "src" "test")) (group "/" (1+ anything) ".cpp")) path)
-      (let ((dir (match-string 1 path))
-            (file-name (match-string 2 path)))
-        (if (equal dir "test")
-            (list :impl (concat "src" file-name))
-          (list :test (concat "test" file-name)
-                :other (concat "src" file-name ".def"))))))
-
-(projectile-register-project-type
-   ;; ...
-   :related-files-fn #'my/related-files)
-```
-
-With the above example, src/test directory can contain the same name file for test and its implementation file.
-For example, "src/foo/abc.cpp" will match to "test/foo/abc.cpp" as test file and "src/foo/abc.cpp.def" as other file.
-
-
-#### Example - Different test prefix per extension
-A custom function for the project using multiple programming languages with different test prefixes.
-```el
-(defun my/related-files(file)
-  (let ((ext-to-test-prefix '(("cpp" . "Test")
-                              ("py" . "test_"))))
-    (if-let ((ext (file-name-extension file))
-             (test-prefix (assoc-default ext ext-to-test-prefix))
-             (file-name (file-name-nondirectory file)))
-        (if (string-prefix-p test-prefix file-name)
-            (let ((suffix (concat "/" (substring file-name (length test-prefix)))))
-              (list :impl (lambda (other-file)
-                            (string-suffix-p suffix other-file))))
-          (let ((suffix (concat "/" test-prefix file-name)))
-            (list :test (lambda (other-file)
-                          (string-suffix-p suffix other-file))))))))
-```
-
-`projectile-find-related-file` command is also available to find and choose
-related files of any kinds. For example, the custom function can specify the
-related documents with ':doc' key. Note that `projectile-find-related-file` only
-relies on `:related-files-fn` for now.
-
-### Related file custom function helper 
-
-`:related-files-fn` can accept a list of custom functions to combine the result
-of each custom function. This allows users to write several custom functions
-and apply them differently to projects.
-
-Projectile includes a couple of helpers to generate commonly used custom functions.
-
-| Helper name and params             | Purpose                                                     |
-|------------------------------------|-------------------------------------------------------------|
-| groups KIND GROUPS                 | Relates files in each group as the specified kind.          |
-| extensions KIND EXTENSIONS         | Relates files with extensions as the specified kind.        |
-| tests-with-prefix EXTENSION PREFIX | Relates files with prefix and extension as :test and :impl. |
-| tests-with-suffix EXTENSION SUFFIX | Relates files with suffix and extension as :test and :impl. |
-
-Each helper means `projectile-related-files-fn-helper-name` function.
-
-#### Example usage of projectile-related-files-fn-helpers
-```el
-(setq my/related-files
-      (list
-       (projectile-related-files-fn-extensions :other '("cpp" "h" "hpp"))
-       (projectile-related-files-fn-test-with-prefix "cpp" "Test")
-       (projectile-related-files-fn-test-with-suffix "el" "_test")
-       (projectile-related-files-fn-groups
-        :doc
-        '(("doc/common.txt"
-           "src/foo.h"
-           "src/bar.h")))))
-
-(projectile-register-project-type
-   ;; ...
-   :related-files-fn #'my/related-files)
-```
-
-## Customizing project root files
-
-You can set the values of `projectile-project-root-files`,
-`projectile-project-root-files-top-down-recurring`,
-`projectile-project-root-files-bottom-up` and
-`projectile-project-root-files-functions` to customize how project roots are
-identified.
-
-To customize project root files settings:
-
-```
-M-x customize-group RET projectile RET
-```
-
-## Ignoring files
-
-!!! Warning
-
-    The contents of `.projectile` are ignored when using the
-    `alien` project indexing method.
-
-If you'd like to instruct Projectile to ignore certain files in a
-project, when indexing it you can do so in the `.projectile` file by
-adding each path to ignore, where the paths all are relative to the
-root directory and start with a slash. Everything ignored should be
-preceded with a `-` sign. Alternatively, not having any prefix at all
-also means to ignore the directory or file pattern that follows.
-Here's an example for a typical Rails application:
-
-```
--/log
--/tmp
--/vendor
--/public/uploads
-```
-
-This would ignore the folders only at the root of the project.
-Projectile also supports relative pathname ignores:
-
-```
--tmp
--*.rb
--*.yml
--models
-```
-
-You can also ignore everything except certain subdirectories. This is
-useful when selecting the directories to keep is easier than selecting
-the directories to ignore, although you can do both. To select
-directories to keep, that means everything else will be ignored.
-
-Example:
-
-```
-+/src/foo
-+/tests/foo
-```
-
-Keep in mind that you can only include subdirectories, not file
-patterns.
-
-If both directories to keep and ignore are specified, the directories
-to keep first apply, restricting what files are considered. The paths
-and patterns to ignore are then applied to that set.
-
-Finally, you can override ignored files. This is especially useful
-when some files ignored by your VCS should be considered as part of
-your project by projectile:
-
-```
-!/src/foo
-!*.yml
-```
-
-When a path is overridden, its contents are still subject to ignore
-patterns. To override those files as well, specify their full path
-with a bang prefix.
-
-### File-local project root definitions
-
-If you want to override the projectile project root for a specific
-file, you can set the file-local variable `projectile-project-root`. This
-can be useful if you have files within one project that are related to
-a different project (for instance, Org files in one git repo that
-correspond to other projects).
-
-## Storing project settings
-
-From project to project, some things may differ even in the same
-language - coding styles, auto-completion sources, etc.  If you need
-to set some variables according to the selected project, you can use a
-standard Emacs feature called
-[Per-directory Local Variables](http://www.gnu.org/software/emacs/manual/html_node/emacs/Directory-Variables.html).
-To use it you must create a file named `.dir-locals.el` (as specified
-by the constant `dir-locals-file`) inside the project directory.  This
-file should contain something like this:
-
-```el
-((nil . ((secret-ftp-password . "secret")
-         (compile-command . "make target-x")
-         (eval . (progn
-                   (defun my-project-specific-function ()
-                     ;; ...
-                     )))))
- (c-mode . ((c-file-style . "BSD"))))
-```
-
-The top-level alist member referenced with the key `nil` applies to
-the entire project.  A key with the name `eval` will evaluate its
-corresponding value.  In the example above, this is used to create a
-function.  It could also be used to e.g. add such a function to a key
-map.
-
-You can also quickly visit or create the `dir-locals-file` with
-<kbd>s-p E</kbd> (<kbd>M-x projectile-edit-dir-locals RET</kbd>).
-
-Here are a few examples of how to use this feature with Projectile.
-
-## Configuring Projectile's Behavior
-
-Projectile exposes many variables (via `defcustom`) which allow users
-to customize its behavior.  Directory variables can be used to set
-these customizations on a per-project basis.
-
-You could enable caching for a project in this way:
-
-```el
-((nil . ((projectile-enable-caching . t))))
-```
-
-If one of your projects had a file that you wanted Projectile to
-ignore, you would customize Projectile by:
-
-```el
-((nil . ((projectile-globally-ignored-files . ("MyBinaryFile")))))
-```
-
-If you wanted to wrap the git command that Projectile uses to list
-the files in you repository, you could do:
-
-```el
-((nil . ((projectile-git-command . "/path/to/other/git ls-files -zco --exclude-standard"))))
-```
-
-If you want to use a different project name than how Projectile named
-your project, you could customize it with the following:
-
-```el
-((nil . ((projectile-project-name . "your-project-name-here"))))
-```
-
-## Configure a Project's Compilation, Test and Run commands
-
-There are a few variables that are intended to be customized via `.dir-locals.el`.
-
-* for compilation - `projectile-project-compilation-cmd`
-* for testing - `projectile-project-test-cmd`
-* for running - `projectile-project-run-cmd`
-
-When these variables have their default value of `nil`, Projectile
-runs the default command for the current project type.  You can
-override this behavior by setting them to either a string to run an
-external command or an Emacs Lisp function:
-
-```el
-(setq projectile-test-cmd #'custom-test-function)
-```
Binary files 2.1.0-1.1/doc/screenshots/projectile.png and 2.5.0-1/doc/screenshots/projectile.png differ
diff -pruN 2.1.0-1.1/doc/support.md 2.5.0-1/doc/support.md
--- 2.1.0-1.1/doc/support.md	2020-02-04 18:30:35.000000000 +0000
+++ 2.5.0-1/doc/support.md	1970-01-01 00:00:00.000000000 +0000
@@ -1,37 +0,0 @@
-Projectile currently has several official & unofficial support channels.
-
-For questions, suggestions and support refer to one of them.  Please, don't
-use the support channels to report issues, as this makes them harder to track.
-
-## Gitter
-
-Most internal discussions about the development of Projectile happen on its
-[gitter channel](https://gitter.im/bbatsov/projectile).  You can often find
-Projectile's maintainers there and get some interesting news from the project's
-kitchen.
-
-## Mailing List
-
-The [official mailing list](https://groups.google.com/forum/#!forum/projectile) is
-hosted at Google Groups. It's a low-traffic list, so don't be too hesitant to subscribe.
-
-## Freenode
-
-If you're into IRC you can visit the `#projectile` channel on Freenode.
-It's not actively
-monitored by the Projectile maintainers themselves, but still you can get support
-from other Projectile users there.
-
-## Stackoverflow
-
-We're also encouraging users to ask Projectile-related questions on StackOverflow.
-
-When doing so you should use the
-[Projectile](http://stackoverflow.com/questions/tagged/projectile) tag (ideally combined
-with the tag `emacs`).
-
-## Bountysource
-
-If you're willing to pay for some feature to be implemented you can use
-[Bountysource](https://www.bountysource.com/teams/projectile/issues) to place a
-bounty for the work you want to be done.
diff -pruN 2.1.0-1.1/doc/troubleshooting.md 2.5.0-1/doc/troubleshooting.md
--- 2.1.0-1.1/doc/troubleshooting.md	2020-02-04 18:30:35.000000000 +0000
+++ 2.5.0-1/doc/troubleshooting.md	1970-01-01 00:00:00.000000000 +0000
@@ -1,63 +0,0 @@
-In case you run into issues here are a few tips that can help you diagnose the
-problem.
-
-Generally, it's not a bad idea to configure Emacs to spit the backtrace on error
-(instead of just logging the error in the `*Messages*` buffer). You can toggle
-this behavior by using <kbd>M-x</kbd> `toggle-debug-on-error`.
-
-## Debugging Projectile commands
-
-Emacs features a super powerful built-in
-[Emacs Lisp debugger](http://www.gnu.org/software/emacs/manual/html_node/elisp/Edebug.html)
-and using it is the best way to diagnose problems of any kind.
-
-!!! Tip
-
-    Here's a [great crash course](https://www.youtube.com/watch?v=odkYXXYOxpo) on
-    using the debugger.
-
-To debug some command you need to do the following:
-
-* Figure out the name of the command you want to debug (e.g. by using <kbd>C-h k</kbd>
-to see which command is associated with some keybinding)
-* Find the source of the command (e.g. by using <kbd>M-x</kbd> `find-function`
-  <kbd>RET</kbd> `function-name`)
-* Press <kbd>C-u C-M-x</kbd> while in the body of the function
-* Run the command again
-
-At this point you'll be dropped in the debugger and you can step forward until
-you find the problem.
-
-## Profiling Projectile commands
-
-Emacs comes with a [built-in
-profiler](https://www.gnu.org/software/emacs/manual/html_node/elisp/Profiling.html). Using
-it is pretty simple:
-
-1. Start it with <kbd>M-x</kbd> `profiler-start`.
-2. Invoke some commands.
-3. Get the report with <kbd>M-x</kbd> `profiler-report`.
-
-!!! Tip
-
-    If you intend to share the profiling results with someone it's a good idea to
-    save the report buffer to a file with <kbd>C-x C-w</kbd>.
-
-## Commonly encountered problems (and how to solve them)
-
-Sometimes a Projectile command might hang for a while (e.g. due to a bug or a
-configuration issue). Such problems are super annoying, but are relatively easy
-to debug. Here are a few steps you can take in such situations:
-
-* Do <kbd>M-x</kbd> `toggle-debug-on-quit`
-* Reproduce the problem
-* Hit <kbd>C-g</kbd> around 10 seconds into the hang
-
-This will bring up a backtrace with the entire function stack, including
-function arguments. So you should be able to figure out what's going on (or at
-least what's being required).
-
-### I upgraded Projectile using `package.el` and nothing changed
-
-Emacs doesn't load the new files, it only installs them on disk.  To see the
-effect of changes you have to restart Emacs.
diff -pruN 2.1.0-1.1/doc/usage.md 2.5.0-1/doc/usage.md
--- 2.1.0-1.1/doc/usage.md	2020-02-04 18:30:35.000000000 +0000
+++ 2.5.0-1/doc/usage.md	1970-01-01 00:00:00.000000000 +0000
@@ -1,151 +0,0 @@
-## Basic setup
-
-!!! Note
-
-    Everything in this section assumes you've enabled `projectile-mode`.
-
-To add a project to Projectile's list of known projects, open a file
-in the project. If you have a projects directory, you can tell
-Projectile about all of the projects in it with the command `M-x
-projectile-discover-projects-in-directory`.
-
-You can go one step further and set a list of folders which Projectile
-is automatically going to check for projects:
-
-```el
-(setq projectile-project-search-path '("~/projects/" "~/work/"))
-```
-
-!!! Tip
-
-    If you're going to use the default `ido` completion it's
-    **extremely highly** recommended that you install the optional
-    [flx-ido package](https://github.com/lewang/flx), which provides a much
-    more powerful alternative to `ido`'s built-in `flex` matching.
-
-Check out the ["Configuration"](configuration.md) section of the manual
-for a lot more information about configuring Projectile.
-
-## Basic Usage
-
-Just open some file in a version-controlled (e.g. `git`) or a project
-(e.g. `maven`) directory that's recognized by Projectile and you're
-ready for action. Projectile happens to recognize out of the box every common
-VCS and many popular project types for various programming languages.
-You can learn more about Projectile's notion of a project [here](projects.md).
-
-!!! Note
-
-    The extent of the support for every VCS differs and Git is the best supported
-    one. Projectile supports some advanced features like working with Git submodules
-    and using `git-grep` instead GNU grep.
-
-You need to know only a handful of Projectile commands to start benefiting from it.
-
-* Find file in current project (<kbd>s-p f</kbd>)
-* Switch project (<kbd>s-p p</kbd>)
-* Grep in project (<kbd>s-p s g</kbd>)
-* Replace in project (<kbd>s-p r</kbd>)
-* Invoke a command via the Projectile Commander (<kbd>s-p m</kbd>)
-
-The next section lists many more commands, but the basics can get you pretty far.
-
-## Interactive Commands
-
-!!! Note
-
-    Projectile doesn't have a default key prefix for its commands, but all the examples
-    in the manual assume you've opted for `s-p` (`super`-p).
-
-Here's a list of the interactive Emacs Lisp functions, provided by Projectile:
-
-Keybinding         | Description
--------------------|------------------------------------------------------------
-<kbd>s-p f</kbd> | Display a list of all files in the project. With a prefix argument it will clear the cache first.
-<kbd>s-p F</kbd> | Display a list of all files in all known projects.
-<kbd>s-p g</kbd> | Display a list of all files at point in the project. With a prefix argument it will clear the cache first.
-<kbd>s-p 4 f</kbd> | Jump to a project's file using completion and show it in another window.
-<kbd>s-p 4 g</kbd> | Jump to a project's file based on context at point and show it in another window.
-<kbd>s-p 5 f</kbd> | Jump to a project's file using completion and show it in another frame.
-<kbd>s-p 5 g</kbd> | Jump to a project's file based on context at point and show it in another frame.
-<kbd>s-p d</kbd> | Display a list of all directories in the project. With a prefix argument it will clear the cache first.
-<kbd>s-p 4 d</kbd> | Switch to a project directory and show it in another window.
-<kbd>s-p 5 d</kbd> | Switch to a project directory and show it in another frame.
-<kbd>s-p T</kbd> | Display a list of all test files(specs, features, etc) in the project.
-<kbd>s-p l</kbd> | Display a list of all files in a directory (that's not necessarily a project)
-<kbd>s-p s g</kbd> | Run grep on the files in the project.
-<kbd>M-- s-p s g</kbd> | Run grep on `projectile-grep-default-files` in the project.
-<kbd>s-p v</kbd> | Run `vc-dir` on the root directory of the project.
-<kbd>s-p V</kbd> | Browse dirty version controlled projects.
-<kbd>s-p b</kbd> | Display a list of all project buffers currently open.
-<kbd>s-p 4 b</kbd> | Switch to a project buffer and show it in another window.
-<kbd>s-p 5 b</kbd> | Switch to a project buffer and show it in another frame.
-<kbd>s-p 4 C-o</kbd> | Display a project buffer in another window without selecting it.
-<kbd>s-p a</kbd> | Switch between files with the same name but different extensions.
-<kbd>s-p 4 a</kbd> | Switch between files with the same name but different extensions in other window.
-<kbd>s-p 5 a</kbd> | Switch between files with the same name but different extensions in other frame.
-<kbd>s-p o</kbd> | Runs `multi-occur` on all project buffers currently open.
-<kbd>s-p r</kbd> | Runs interactive query-replace on all files in the projects.
-<kbd>s-p i</kbd> | Invalidates the project cache (if existing).
-<kbd>s-p R</kbd> | Regenerates the projects `TAGS` file.
-<kbd>s-p j</kbd> | Find tag in project's `TAGS` file.
-<kbd>s-p k</kbd> | Kills all project buffers.
-<kbd>s-p D</kbd> | Opens the root of the project in `dired`.
-<kbd>s-p 4 D</kbd> | Opens the root of the project in `dired` in another window.
-<kbd>s-p 5 D</kbd> | Opens the root of the project in `dired` in another frame.
-<kbd>s-p e</kbd> | Shows a list of recently visited project files.
-<kbd>s-p left</kbd> | Switch to the previous project buffer.
-<kbd>s-p right</kbd> | Switch to the next project buffer.
-<kbd>s-p E</kbd> | Opens the root `dir-locals-file` of the project.
-<kbd>s-p s s</kbd> | Runs `ag` on the project, performing a literal search. Requires the presence of `ag.el`. With a prefix argument it will perform a regex search.
-<kbd>s-p !</kbd> | Runs `shell-command` in the root directory of the project.
-<kbd>s-p &</kbd> | Runs `async-shell-command` in the root directory of the project.
-<kbd>s-p C</kbd> | Runs a standard configure command for your type of project.
-<kbd>s-p c</kbd> | Runs a standard compilation command for your type of project.
-<kbd>s-p P</kbd> | Runs a standard test command for your type of project.
-<kbd>s-p t</kbd> | Toggle between an implementation file and its test file.
-<kbd>s-p 4 t</kbd> | Jump to implementation or test file in other window.
-<kbd>s-p 5 t</kbd> | Jump to implementation or test file in other frame.
-<kbd>s-p z</kbd> | Adds the currently visited file to the cache.
-<kbd>s-p p</kbd> | Display a list of known projects you can switch to.
-<kbd>s-p S</kbd> | Save all project buffers.
-<kbd>s-p m</kbd> | Run the commander (an interface to run commands with a single key).
-<kbd>s-p ESC</kbd> | Switch to the most recently selected Projectile buffer.
-
-If you ever forget any of Projectile's keybindings just do a:
-
-<kbd>s-p C-h</kbd>
-
-It is possible to add additional commands to
-`projectile-command-map` referenced by the prefix key in
-`projectile-mode-map`. You can add multiple keymap prefix for all
-commands. Here's an example that adds `super-,` as a command prefix:
-
-```el
-(define-key projectile-mode-map (kbd "s-,") 'projectile-command-map)
-```
-
-You can also bind the `projectile-command-map` to any other map you'd
-like (including the global keymap).
-
-!!! Tip
-
-    For some common commands you might want to take a little shortcut and
-    leverage the fairly unused `Super` key (by default `Command` on Mac
-    keyboards and `Windows` on Win keyboards).
-
-Here's something you can
-add to your Emacs config:
-
-```el
-(define-key projectile-mode-map [?\s-d] 'projectile-find-dir)
-(define-key projectile-mode-map [?\s-p] 'projectile-switch-project)
-(define-key projectile-mode-map [?\s-f] 'projectile-find-file)
-(define-key projectile-mode-map [?\s-g] 'projectile-grep)
-```
-
-!!! Note
-
-    Note that the `Super` keybindings are not usable in Windows, as Windows
-    makes heavy use of such keybindings itself. Emacs
-    Prelude already adds those extra keybindings.
diff -pruN 2.1.0-1.1/Eldev 2.5.0-1/Eldev
--- 2.1.0-1.1/Eldev	1970-01-01 00:00:00.000000000 +0000
+++ 2.5.0-1/Eldev	2021-08-10 10:11:43.000000000 +0000
@@ -0,0 +1 @@
+(eldev-use-package-archive 'melpa)
diff -pruN 2.1.0-1.1/.github/FUNDING.yml 2.5.0-1/.github/FUNDING.yml
--- 2.1.0-1.1/.github/FUNDING.yml	2020-02-04 18:30:35.000000000 +0000
+++ 2.5.0-1/.github/FUNDING.yml	2021-08-10 10:11:43.000000000 +0000
@@ -2,4 +2,5 @@
 
 github: bbatsov
 patreon: bbatsov
+ko_fi: bbatsov
 custom: https://www.paypal.me/bbatsov
diff -pruN 2.1.0-1.1/.github/PULL_REQUEST_TEMPLATE.md 2.5.0-1/.github/PULL_REQUEST_TEMPLATE.md
--- 2.1.0-1.1/.github/PULL_REQUEST_TEMPLATE.md	2020-02-04 18:30:35.000000000 +0000
+++ 2.5.0-1/.github/PULL_REQUEST_TEMPLATE.md	2021-08-10 10:11:43.000000000 +0000
@@ -6,11 +6,11 @@ The more detailed you are, the better.**
 Before submitting a PR make sure the following things have been done (and denote this
 by checking the relevant checkboxes):
 
-- [ ] The commits are consistent with our [contribution guidelines](../CONTRIBUTING.md)
+- [ ] The commits are consistent with our [contribution guidelines](../blob/master/CONTRIBUTING.md)
 - [ ] You've added tests (if possible) to cover your change(s)
-- [ ] All tests are passing (`make test`)
+- [ ] All tests are passing ([`eldev test`](https://github.com/doublep/eldev))
 - [ ] The new code is not generating bytecode or `M-x checkdoc` warnings
-- [ ] You've updated the changelog (if adding/changing user-visible functionality)
+- [ ] You've updated the [changelog](../blob/master/CHANGELOG.md) (if adding/changing user-visible functionality)
 - [ ] You've updated the readme (if adding/changing user-visible functionality)
 
 Thanks!
diff -pruN 2.1.0-1.1/.github/workflows/test.yml 2.5.0-1/.github/workflows/test.yml
--- 2.1.0-1.1/.github/workflows/test.yml	1970-01-01 00:00:00.000000000 +0000
+++ 2.5.0-1/.github/workflows/test.yml	2021-08-10 10:11:43.000000000 +0000
@@ -0,0 +1,34 @@
+name: CI
+
+on:
+  push:
+    paths-ignore: ['**.md', '**.adoc']
+  pull_request:
+    paths-ignore: ['**.md', '**.adoc']
+
+jobs:
+  test:
+    runs-on: ubuntu-latest
+    continue-on-error: ${{matrix.emacs_version == 'snapshot'}}
+
+    strategy:
+      matrix:
+        # Earliest supported + latest in each stable branch + snapshot.
+        emacs_version: ['25.1', '25.3', '26.3', '27.1', 'snapshot']
+
+    steps:
+    - name: Set up Emacs
+      uses: purcell/setup-emacs@master
+      with:
+        version: ${{matrix.emacs_version}}
+
+    - name: Install Eldev
+      run: curl -fsSL https://raw.github.com/doublep/eldev/master/webinstall/github-eldev | sh
+
+    - name: Check out the source code
+      uses: actions/checkout@v2
+
+    - name: Test the project
+      run: |
+        eldev -p -dtT -C test --expect 100
+        eldev -dtT -C compile --warnings-as-errors
diff -pruN 2.1.0-1.1/.gitignore 2.5.0-1/.gitignore
--- 2.1.0-1.1/.gitignore	2020-02-04 18:30:35.000000000 +0000
+++ 2.5.0-1/.gitignore	2021-08-10 10:11:43.000000000 +0000
@@ -2,7 +2,8 @@
 *\#*\#
 *.\#*
 *.elc
-.cask
-elpa*
+/Eldev-local
+/.eldev
+/dist
 /TAGS
 /project
diff -pruN 2.1.0-1.1/LICENSE 2.5.0-1/LICENSE
--- 2.1.0-1.1/LICENSE	2020-02-04 18:30:35.000000000 +0000
+++ 2.5.0-1/LICENSE	2021-08-10 10:11:43.000000000 +0000
@@ -1,165 +1,674 @@
-                   GNU LESSER GENERAL PUBLIC LICENSE
+                    GNU GENERAL PUBLIC LICENSE
                        Version 3, 29 June 2007
 
  Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
  Everyone is permitted to copy and distribute verbatim copies
  of this license document, but changing it is not allowed.
 
+                            Preamble
 
-  This version of the GNU Lesser General Public License incorporates
-the terms and conditions of version 3 of the GNU General Public
-License, supplemented by the additional permissions listed below.
-
-  0. Additional Definitions.
-
-  As used herein, "this License" refers to version 3 of the GNU Lesser
-General Public License, and the "GNU GPL" refers to version 3 of the GNU
-General Public License.
-
-  "The Library" refers to a covered work governed by this License,
-other than an Application or a Combined Work as defined below.
-
-  An "Application" is any work that makes use of an interface provided
-by the Library, but which is not otherwise based on the Library.
-Defining a subclass of a class defined by the Library is deemed a mode
-of using an interface provided by the Library.
-
-  A "Combined Work" is a work produced by combining or linking an
-Application with the Library.  The particular version of the Library
-with which the Combined Work was made is also called the "Linked
-Version".
-
-  The "Minimal Corresponding Source" for a Combined Work means the
-Corresponding Source for the Combined Work, excluding any source code
-for portions of the Combined Work that, considered in isolation, are
-based on the Application, and not on the Linked Version.
-
-  The "Corresponding Application Code" for a Combined Work means the
-object code and/or source code for the Application, including any data
-and utility programs needed for reproducing the Combined Work from the
-Application, but excluding the System Libraries of the Combined Work.
-
-  1. Exception to Section 3 of the GNU GPL.
-
-  You may convey a covered work under sections 3 and 4 of this License
-without being bound by section 3 of the GNU GPL.
-
-  2. Conveying Modified Versions.
-
-  If you modify a copy of the Library, and, in your modifications, a
-facility refers to a function or data to be supplied by an Application
-that uses the facility (other than as an argument passed when the
-facility is invoked), then you may convey a copy of the modified
-version:
-
-   a) under this License, provided that you make a good faith effort to
-   ensure that, in the event an Application does not supply the
-   function or data, the facility still operates, and performs
-   whatever part of its purpose remains meaningful, or
-
-   b) under the GNU GPL, with none of the additional permissions of
-   this License applicable to that copy.
-
-  3. Object Code Incorporating Material from Library Header Files.
-
-  The object code form of an Application may incorporate material from
-a header file that is part of the Library.  You may convey such object
-code under terms of your choice, provided that, if the incorporated
-material is not limited to numerical parameters, data structure
-layouts and accessors, or small macros, inline functions and templates
-(ten or fewer lines in length), you do both of the following:
-
-   a) Give prominent notice with each copy of the object code that the
-   Library is used in it and that the Library and its use are
-   covered by this License.
-
-   b) Accompany the object code with a copy of the GNU GPL and this license
-   document.
-
-  4. Combined Works.
-
-  You may convey a Combined Work under terms of your choice that,
-taken together, effectively do not restrict modification of the
-portions of the Library contained in the Combined Work and reverse
-engineering for debugging such modifications, if you also do each of
-the following:
-
-   a) Give prominent notice with each copy of the Combined Work that
-   the Library is used in it and that the Library and its use are
-   covered by this License.
-
-   b) Accompany the Combined Work with a copy of the GNU GPL and this license
-   document.
-
-   c) For a Combined Work that displays copyright notices during
-   execution, include the copyright notice for the Library among
-   these notices, as well as a reference directing the user to the
-   copies of the GNU GPL and this license document.
-
-   d) Do one of the following:
-
-       0) Convey the Minimal Corresponding Source under the terms of this
-       License, and the Corresponding Application Code in a form
-       suitable for, and under terms that permit, the user to
-       recombine or relink the Application with a modified version of
-       the Linked Version to produce a modified Combined Work, in the
-       manner specified by section 6 of the GNU GPL for conveying
-       Corresponding Source.
-
-       1) Use a suitable shared library mechanism for linking with the
-       Library.  A suitable mechanism is one that (a) uses at run time
-       a copy of the Library already present on the user's computer
-       system, and (b) will operate properly with a modified version
-       of the Library that is interface-compatible with the Linked
-       Version.
-
-   e) Provide Installation Information, but only if you would otherwise
-   be required to provide such information under section 6 of the
-   GNU GPL, and only to the extent that such information is
-   necessary to install and execute a modified version of the
-   Combined Work produced by recombining or relinking the
-   Application with a modified version of the Linked Version. (If
-   you use option 4d0, the Installation Information must accompany
-   the Minimal Corresponding Source and Corresponding Application
-   Code. If you use option 4d1, you must provide the Installation
-   Information in the manner specified by section 6 of the GNU GPL
-   for conveying Corresponding Source.)
-
-  5. Combined Libraries.
-
-  You may place library facilities that are a work based on the
-Library side by side in a single library together with other library
-facilities that are not Applications and are not covered by this
-License, and convey such a combined library under terms of your
-choice, if you do both of the following:
-
-   a) Accompany the combined library with a copy of the same work based
-   on the Library, uncombined with any other library facilities,
-   conveyed under the terms of this License.
-
-   b) Give prominent notice with the combined library that part of it
-   is a work based on the Library, and explaining where to find the
-   accompanying uncombined form of the same work.
-
-  6. Revised Versions of the GNU Lesser General Public License.
-
-  The Free Software Foundation may publish revised and/or new versions
-of the GNU Lesser General Public License from time to time. Such new
-versions will be similar in spirit to the present version, but may
-differ in detail to address new problems or concerns.
-
-  Each version is given a distinguishing version number. If the
-Library as you received it specifies that a certain numbered version
-of the GNU Lesser General Public License "or any later version"
-applies to it, you have the option of following the terms and
-conditions either of that published version or of any later version
-published by the Free Software Foundation. If the Library as you
-received it does not specify a version number of the GNU Lesser
-General Public License, you may choose any version of the GNU Lesser
-General Public License ever published by the Free Software Foundation.
-
-  If the Library as you received it specifies that a proxy can decide
-whether future versions of the GNU Lesser General Public License shall
-apply, that proxy's public statement of acceptance of any version is
-permanent authorization for you to choose that version for the
-Library.
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<https://www.gnu.org/licenses/>.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+<https://www.gnu.org/licenses/why-not-lgpl.html>.
diff -pruN 2.1.0-1.1/Makefile 2.5.0-1/Makefile
--- 2.1.0-1.1/Makefile	2020-02-04 18:30:35.000000000 +0000
+++ 2.5.0-1/Makefile	1970-01-01 00:00:00.000000000 +0000
@@ -1,31 +0,0 @@
-CASK = cask
-export EMACS ?= emacs
-EMACSFLAGS =
-TESTFLAGS =
-
-SRCS = $(wildcard *.el)
-OBJS = $(SRCS:.el=.elc)
-
-.PHONY: compile test clean elpa
-
-all: compile
-
-elpa-$(EMACS):
-	$(CASK) install
-	$(CASK) update
-	touch $@
-
-elpa: elpa-$(EMACS)
-
-elpaclean:
-	rm -f elpa*
-	rm -rf .cask # Clean packages installed for development
-
-compile: elpa
-	$(CASK) build
-
-clean:
-	rm -f $(OBJS)
-
-test: elpa
-	$(CASK) exec buttercup -L .
diff -pruN 2.1.0-1.1/mkdocs.yml 2.5.0-1/mkdocs.yml
--- 2.1.0-1.1/mkdocs.yml	2020-02-04 18:30:35.000000000 +0000
+++ 2.5.0-1/mkdocs.yml	1970-01-01 00:00:00.000000000 +0000
@@ -1,22 +0,0 @@
-site_name: "Projectile: The Project Interaction Library for Emacs"
-repo_url: https://github.com/bbatsov/projectile/
-edit_uri: edit/master/doc/
-site_favicon: favicon.ico
-copyright: "Copyright (C) 2011-2020 Bozhidar Batsov and Projectile contributors"
-docs_dir: doc
-pages:
-- Home: index.md
-- Installation: installation.md
-- Usage: usage.md
-- Projects: projects.md
-- Configuration: configuration.md
-- Extensions: extensions.md
-- FAQ: faq.md
-- Troubleshooting: troubleshooting.md
-- Contributing: contributing.md
-- Support: support.md
-extra_css:
-  - css/extra.css
-markdown_extensions:
-  - admonition
-theme: readthedocs
diff -pruN 2.1.0-1.1/projectile.el 2.5.0-1/projectile.el
--- 2.1.0-1.1/projectile.el	2020-02-04 18:30:35.000000000 +0000
+++ 2.5.0-1/projectile.el	2021-08-10 10:11:43.000000000 +0000
@@ -1,12 +1,12 @@
 ;;; projectile.el --- Manage and navigate projects in Emacs easily -*- lexical-binding: t -*-
 
-;; Copyright © 2011-2020 Bozhidar Batsov <bozhidar@batsov.com>
+;; Copyright © 2011-2021 Bozhidar Batsov <bozhidar@batsov.com>
 
 ;; Author: Bozhidar Batsov <bozhidar@batsov.com>
 ;; URL: https://github.com/bbatsov/projectile
 ;; Keywords: project, convenience
-;; Version: 2.1.0
-;; Package-Requires: ((emacs "25.1") (pkg-info "0.4"))
+;; Version: 2.5.0
+;; Package-Requires: ((emacs "25.1"))
 
 ;; This file is NOT part of GNU Emacs.
 
@@ -42,11 +42,15 @@
 (require 'ibuf-ext)
 (require 'compile)
 (require 'grep)
+(require 'lisp-mnt)
 (eval-when-compile
   (require 'find-dired)
   (require 'subr-x))
 
 (eval-when-compile
+  (defvar ido-mode)
+  (defvar ivy-mode)
+  (defvar helm-mode)
   (defvar ag-ignore-list)
   (defvar ggtags-completion-table)
   (defvar tags-completion-table)
@@ -59,16 +63,17 @@
 (declare-function make-term "term")
 (declare-function term-mode "term")
 (declare-function term-char-mode "term")
+(declare-function term-ansi-make-term "term")
 (declare-function eshell-search-path "esh-ext")
 (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 ggtags-ensure-project "ext:ggtags")
 (declare-function ggtags-update-tags "ext:ggtags")
-(declare-function pkg-info-version-info "ext:pkg-info")
 (declare-function ripgrep-regexp "ext:ripgrep")
 (declare-function vterm "ext:vterm")
 (declare-function vterm-send-return "ext:vterm")
@@ -175,8 +180,15 @@ A value of nil means the cache never exp
   :type '(choice (const :tag "Disabled" nil)
                  (integer :tag "Seconds")))
 
+(defcustom projectile-auto-discover t
+  "Whether to discover projects when `projectile-mode' is activated."
+  :group 'projectile
+  :type 'boolean
+  :package-version '(projectile . "2.3.0"))
+
 (defcustom projectile-auto-update-cache t
-  "Wether the cache should automatically be updated when files are opened or deleted."
+  "Whether the cache should automatically be updated when files are opened or
+deleted."
   :group 'projectile
   :type 'boolean)
 
@@ -191,10 +203,11 @@ When nil Projectile will consider the cu
                  (const :tag "Yes" t)
                  (const :tag "Prompt for project" prompt)))
 
-(defcustom projectile-completion-system 'ido
+(defcustom projectile-completion-system 'auto
   "The completion system to be used by Projectile."
   :group 'projectile
   :type '(radio
+          (const :tag "Auto-detect" auto)
           (const :tag "Ido" ido)
           (const :tag "Helm" helm)
           (const :tag "Ivy" ivy)
@@ -285,41 +298,23 @@ It has precedence over function `project
 (defcustom projectile-project-name-function 'projectile-default-project-name
   "A function that receives the project-root and returns the project name.
 
-If variable `projectile-project-name' is non-nil, this function will not be used."
+If variable `projectile-project-name' is non-nil, this function will not be
+used."
   :group 'projectile
   :type 'function
   :package-version '(projectile . "0.14.0"))
 
 (defcustom projectile-project-root-files
-  '("rebar.config"       ; Rebar project file
-    "project.clj"        ; Leiningen project file
-    "build.boot"         ; Boot-clj project file
-    "deps.edn"           ; Clojure CLI project file
-    "SConstruct"         ; Scons project file
-    "pom.xml"            ; Maven project file
-    "build.sbt"          ; SBT project file
-    "gradlew"            ; Gradle wrapper script
-    "build.gradle"       ; Gradle project file
-    ".ensime"            ; Ensime configuration file
-    "Gemfile"            ; Bundler file
-    "requirements.txt"   ; Pip file
-    "setup.py"           ; Setuptools file
-    "pyproject.toml"     ; Python project file
-    "tox.ini"            ; Tox file
-    "composer.json"      ; Composer project file
-    "Cargo.toml"         ; Cargo project file
-    "mix.exs"            ; Elixir mix project file
-    "stack.yaml"         ; Haskell's stack tool based project
-    "info.rkt"           ; Racket package description file
-    "DESCRIPTION"        ; R package description file
-    "TAGS"               ; etags/ctags are usually in the root of project
+  '(
     "GTAGS"              ; GNU Global tags
-    "configure.in"       ; autoconf old style
+    "TAGS"               ; etags/ctags are usually in the root of project
     "configure.ac"       ; autoconf new style
+    "configure.in"       ; autoconf old style
     "cscope.out"         ; cscope
     )
   "A list of files considered to mark the root of a project.
-The topmost match has precedence."
+The topmost match has precedence.
+See `projectile-register-project-type'."
   :group 'projectile
   :type '(repeat string))
 
@@ -349,37 +344,58 @@ containing a root file."
   :group 'projectile
   :type '(repeat string))
 
-(defcustom projectile-project-root-files-functions
+(define-obsolete-variable-alias 'projectile-project-root-files-functions 'projectile-project-root-functions "2.4")
+
+(defcustom projectile-project-root-functions
   '(projectile-root-local
     projectile-root-bottom-up
     projectile-root-top-down
     projectile-root-top-down-recurring)
-  "A list of functions for finding project roots."
+  "A list of functions for finding project root folders.
+The functions will be ran until one of them returns a project folder.
+Reordering the default functions will alter the project discovery
+algorithm."
   :group 'projectile
   :type '(repeat function))
 
+(defcustom projectile-dirconfig-comment-prefix
+  nil
+  "Projectile config file (.projectile) comment start marker.
+If specified, starting a line in a project's .projectile file with this
+character marks that line as a comment instead of a pattern.
+Similar to '#' in .gitignore files."
+  :group 'projectile
+  :type 'character
+  :package-version '(projectile . "2.2.0"))
+
 (defcustom projectile-globally-ignored-files
   (list projectile-tags-file-name)
-  "A list of files globally ignored by projectile."
+  "A list of files globally ignored by projectile.
+Note that files aren't filtered if `projectile-indexing-method'
+is set to 'alien'."
   :group 'projectile
   :type '(repeat string))
 
 (defcustom projectile-globally-unignored-files nil
   "A list of files globally unignored by projectile.
-
-Regular expressions can be used."
+Regular expressions can be used.
+Note that files aren't filtered if `projectile-indexing-method'
+is set to 'alien'."
   :group 'projectile
   :type '(repeat string)
   :package-version '(projectile . "0.14.0"))
 
 (defcustom projectile-globally-ignored-file-suffixes
   nil
-  "A list of file suffixes globally ignored by projectile."
+  "A list of file suffixes globally ignored by projectile.
+Note that files aren't filtered if `projectile-indexing-method'
+is set to 'alien'."
   :group 'projectile
   :type '(repeat string))
 
 (defcustom projectile-globally-ignored-directories
   '(".idea"
+    ".vscode"
     ".ensime_cache"
     ".eunit"
     ".git"
@@ -390,16 +406,33 @@ Regular expressions can be used."
     "_darcs"
     ".tox"
     ".svn"
-    ".stack-work")
+    ".stack-work"
+    ".ccls-cache"
+    ".cache"
+    ".clangd")
   "A list of directories globally ignored by projectile.
+Regular expressions can be used.
+
+Strings that don't start with * are only ignored at the top level
+of the project. Strings that start with * are ignored everywhere
+in the project, as if there was no *. So note that * when used as
+a prefix is not a wildcard; it is an indicator that the directory
+should be ignored at all levels, not just root.
+
+Examples: \"tmp\" ignores only ./tmp at the top level of the
+project, but not ./src/tmp. \"*tmp\" will ignore both ./tmp and
+./src/tmp, but not ./not-a-tmp or ./src/not-a-tmp.
 
-Regular expressions can be used."
+Note that files aren't filtered if `projectile-indexing-method'
+is set to 'alien'."
   :safe (lambda (x) (not (remq t (mapcar #'stringp x))))
   :group 'projectile
   :type '(repeat string))
 
 (defcustom projectile-globally-unignored-directories nil
-  "A list of directories globally unignored by projectile."
+  "A list of directories globally unignored by projectile.
+Note that files aren't filtered if `projectile-indexing-method'
+is set to 'alien'."
   :group 'projectile
   :type '(repeat string)
   :package-version '(projectile . "0.14.0"))
@@ -599,9 +632,14 @@ When set to nil you'll have always add p
 (defcustom projectile-project-search-path nil
   "List of folders where projectile is automatically going to look for projects.
 You can think of something like $PATH, but for projects instead of executables.
-Examples of such paths might be ~/projects, ~/work, etc."
+Examples of such paths might be ~/projects, ~/work, (~/github . 1) etc.
+
+For elements of form (DIRECTORY . DEPTH), DIRECTORY has to be a
+directory and DEPTH an integer that specifies the depth at which to
+look for projects. A DEPTH of 0 means check DIRECTORY. A depth of 1
+means check all the subdirectories of DIRECTORY. Etc."
   :group 'projectile
-  :type 'list
+  :type '(repeat (choice directory (cons directory (integer :tag "Depth"))))
   :package-version '(projectile . "1.0.0"))
 
 (defcustom projectile-git-command "git ls-files -zco --exclude-standard"
@@ -609,7 +647,7 @@ Examples of such paths might be ~/projec
   :group 'projectile
   :type 'string)
 
-(defcustom projectile-git-submodule-command "git submodule --quiet foreach 'echo $path' | tr '\\n' '\\0'"
+(defcustom projectile-git-submodule-command "git submodule --quiet foreach 'echo $displaypath' | tr '\\n' '\\0'"
   "Command used by projectile to list submodules of a given git repository.
 Set to nil to disable listing submodules contents."
   :group 'projectile
@@ -683,6 +721,14 @@ as defined in `vc.el'."
     ("cc"  . ("h" "hh" "hpp"))
     ("hh"  . ("cc"))
 
+    ;; OCaml extensions
+    ("ml" . ("mli"))
+    ("mli" . ("ml" "mll" "mly"))
+    ("mll" . ("mli"))
+    ("mly" . ("mli"))
+    ("eliomi" . ("eliom"))
+    ("eliom" . ("eliomi"))
+
     ;; vertex shader and fragment shader extensions in glsl
     ("vert" . ("frag"))
     ("frag" . ("vert"))
@@ -729,9 +775,22 @@ position."
           (const :tag "Move to end" move-to-end)
           (const :tag "Keep" keep)))
 
+(defcustom projectile-max-file-buffer-count nil
+  "Maximum number of file buffers per project that are kept open.
+
+If the value is nil, there is no limit to the opend buffers count."
+  :group 'projectile
+  :type 'integer
+  :package-version '(projectile . "2.2.0"))
+
 
 ;;; Version information
 
+(defconst projectile-version
+  (eval-when-compile
+    (lm-version (or load-file-name buffer-file-name)))
+  "The current version of Projectile.")
+
 ;;;###autoload
 (defun projectile-version (&optional show-version)
   "Get the Projectile version as string.
@@ -746,12 +805,9 @@ If the version number could not be deter
 if called interactively, or if SHOW-VERSION is non-nil, otherwise
 just return nil."
   (interactive (list t))
-  (if (require 'pkg-info nil t)
-      (let ((version (pkg-info-version-info 'projectile)))
-        (when show-version
-          (message "Projectile %s" version))
-        version)
-    (error "Cannot determine version without package pkg-info")))
+  (if show-version
+      (message "Projectile %s" projectile-version)
+    projectile-version))
 
 ;;; Misc utility functions
 (defun projectile-difference (list1 list2)
@@ -775,9 +831,11 @@ just return nil."
   "Get the symbol at point and strip its properties."
   (substring-no-properties (or (thing-at-point 'symbol) "")))
 
-(defun projectile-generate-process-name (process make-new)
-  "Infer the buffer name for PROCESS or generate a new one if MAKE-NEW is true."
-  (let* ((project (projectile-ensure-project (projectile-project-root)))
+(defun projectile-generate-process-name (process make-new &optional project)
+  "Infer the buffer name for PROCESS or generate a new one if MAKE-NEW is true.
+The function operates on the current project by default, but you can also
+specify a project explicitly via the optional PROJECT param."
+  (let* ((project (or project (projectile-acquire-root)))
          (base-name (format "*%s %s*" process (projectile-project-name project))))
     (if make-new
         (generate-new-buffer-name base-name)
@@ -869,7 +927,7 @@ to invalidate."
          (if prompt
              (completing-read "Remove cache for: "
                               (hash-table-keys projectile-projects-cache))
-           (projectile-ensure-project (projectile-project-root)))))
+           (projectile-acquire-root))))
     (setq projectile-project-root-cache (make-hash-table :test 'equal))
     (remhash project-root projectile-project-type-cache)
     (remhash project-root projectile-projects-cache)
@@ -968,27 +1026,30 @@ The cache is created both in memory and
     (projectile-invalidate-cache nil)))
 
 ;;;###autoload
-(defun projectile-discover-projects-in-directory (directory)
+(defun projectile-discover-projects-in-directory (directory &optional depth)
   "Discover any projects in DIRECTORY and add them to the projectile cache.
-This function is not recursive and only adds projects with roots
-at the top level of DIRECTORY."
-  (interactive
-   (list (read-directory-name "Starting directory: ")))
-  (let ((subdirs (directory-files directory t)))
-    (mapcar
-     (lambda (dir)
-       (when (and (file-directory-p dir)
-                  (not (member (file-name-nondirectory dir) '(".." "."))))
-         (when (projectile-project-p dir)
-           (projectile-add-known-project dir))))
-     subdirs)))
+
+If DEPTH is non-nil recursively descend exactly DEPTH levels below DIRECTORY and
+discover projects there."
+  (if (file-directory-p directory)
+      (if (and (numberp depth) (> depth 0))
+          (dolist (dir (directory-files directory t))
+            (when (and (file-directory-p dir)
+                       (not (member (file-name-nondirectory dir) '(".." "."))))
+	            (projectile-discover-projects-in-directory dir (1- depth))))
+        (when (projectile-project-p directory)
+          (projectile-add-known-project directory)))
+    (message "Project search path directory %s doesn't exist" directory)))
 
 ;;;###autoload
 (defun projectile-discover-projects-in-search-path ()
   "Discover projects in `projectile-project-search-path'.
 Invoked automatically when `projectile-mode' is enabled."
   (interactive)
-  (mapcar #'projectile-discover-projects-in-directory projectile-project-search-path))
+  (dolist (path projectile-project-search-path)
+    (if (consp path)
+	(projectile-discover-projects-in-directory (car path) (cdr path))
+      (projectile-discover-projects-in-directory path 1))))
 
 
 (defun delete-file-projectile-remove-from-cache (filename &optional _trash)
@@ -1077,6 +1138,11 @@ If DIR is not supplied its set to the cu
   ;; cl-subst to replace this 'none value with nil so a nil value is used
   ;; instead
   (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)
+               (tramp-archive-file-name-p dir))
+      (setq dir (file-name-directory (tramp-archive-file-name-archive dir))))
     (cl-subst nil 'none
               ;; The `is-local' and `is-connected' variables are
               ;; used to fix the behavior where Emacs hangs
@@ -1088,6 +1154,8 @@ If DIR is not supplied its set to the cu
               (or (let ((is-local (not (file-remote-p dir)))      ;; `true' if the file is local
                         (is-connected (file-remote-p dir nil t))) ;; `true' if the file is remote AND we are connected to the remote
                     (when (or is-local is-connected)
+                      ;; Here is where all the magic happens.
+                      ;; We run the functions in `projectile-project-root-functions' until we find a project dir.
                       (cl-some
                        (lambda (func)
                          (let* ((cache-key (format "%s-%s" func dir))
@@ -1097,7 +1165,7 @@ If DIR is not supplied its set to the cu
                              (let ((value (funcall func (file-truename dir))))
                                (puthash cache-key value projectile-project-root-cache)
                                value))))
-                       projectile-project-root-files-functions)))
+                       projectile-project-root-functions)))
                   ;; set cached to none so is non-nil so we don't try
                   ;; and look it up again
                   'none))))
@@ -1105,15 +1173,23 @@ If DIR is not supplied its set to the cu
 (defun projectile-ensure-project (dir)
   "Ensure that DIR is non-nil.
 Useful for commands that expect the presence of a project.
-Controlled by `projectile-require-project-root'."
+Controlled by `projectile-require-project-root'.
+
+See also `projectile-acquire-root'."
   (if dir
       dir
     (cond
      ((eq projectile-require-project-root 'prompt) (projectile-completing-read
                                                     "Switch to project: " projectile-known-projects))
-     (projectile-require-project-root (error "Projectile can't find a project definition in %s" dir))
+     (projectile-require-project-root (error "Projectile cannot find a project definition in %s" default-directory))
      (t default-directory))))
 
+(defun projectile-acquire-root (&optional dir)
+  "Find the current project root, and prompts the user for it if that fails.
+Provides the common idiom (projectile-ensure-project (projectile-project-root)).
+Starts the search for the project with DIR."
+  (projectile-ensure-project (projectile-project-root dir)))
+
 (defun projectile-project-p (&optional dir)
   "Check if DIR is a project.
 Defaults to the current directory if not provided
@@ -1156,11 +1232,11 @@ Files are returned as relative paths to
     (or files-list
         (let ((vcs (projectile-project-vcs directory)))
           (pcase projectile-indexing-method
-           ('native (projectile-dir-files-native directory))
-           ;; use external tools to get the project files
-           ('hybrid (projectile-adjust-files directory vcs (projectile-dir-files-alien directory)))
-           ('alien (projectile-dir-files-alien directory))
-           (_ (user-error "Unsupported indexing method `%S'" projectile-indexing-method)))))))
+            ('native (projectile-dir-files-native directory))
+            ;; use external tools to get the project files
+            ('hybrid (projectile-adjust-files directory vcs (projectile-dir-files-alien directory)))
+            ('alien (projectile-dir-files-alien directory))
+            (_ (user-error "Unsupported indexing method `%S'" projectile-indexing-method)))))))
 
 ;;; Native Project Indexing
 ;;
@@ -1176,25 +1252,35 @@ Files are returned as relative paths to
             (projectile-index-directory directory (projectile-filtering-patterns)
                                         progress-reporter))))
 
-(defun projectile-index-directory (directory patterns progress-reporter)
+(defun projectile-index-directory (directory patterns progress-reporter &optional ignored-files ignored-directories globally-ignored-directories)
   "Index DIRECTORY taking into account PATTERNS.
+
 The function calls itself recursively until all sub-directories
 have been indexed.  The PROGRESS-REPORTER is updated while the
-function is executing."
-  (apply #'append
-         (mapcar
-          (lambda (f)
-            (unless (or (and patterns (projectile-ignored-rel-p f directory patterns))
-                        (member (file-name-nondirectory (directory-file-name f))
-                                '("." ".." ".svn" ".cvs")))
-              (progress-reporter-update progress-reporter)
-              (if (file-directory-p f)
-                  (unless (projectile-ignored-directory-p
-                           (file-name-as-directory f))
-                    (projectile-index-directory f patterns progress-reporter))
-                (unless (projectile-ignored-file-p f)
-                  (list f)))))
-          (directory-files directory t))))
+function is executing.  The list of IGNORED-FILES and
+IGNORED-DIRECTORIES may optionally be provided."
+  ;; we compute the ignored files and directories only once and then we reuse the
+  ;; pre-computed values in the subsequent recursive invocations of the function
+  (let ((ignored-files (or ignored-files (projectile-ignored-files)))
+        (ignored-directories (or ignored-directories (projectile-ignored-directories)))
+        (globally-ignored-directories (or globally-ignored-directories (projectile-globally-ignored-directory-names))))
+    (apply #'append
+           (mapcar
+            (lambda (f)
+              (let ((local-f (file-name-nondirectory (directory-file-name f))))
+                (unless (or (and patterns (projectile-ignored-rel-p f directory patterns))
+                            (member local-f '("." "..")))
+                  (progress-reporter-update progress-reporter)
+                  (if (file-directory-p f)
+                      (unless (projectile-ignored-directory-p
+                               (file-name-as-directory f)
+                               ignored-directories
+                               local-f
+                               globally-ignored-directories)
+                        (projectile-index-directory f patterns progress-reporter ignored-files ignored-directories globally-ignored-directories))
+                    (unless (projectile-ignored-file-p f ignored-files)
+                      (list f))))))
+            (directory-files directory t)))))
 
 ;;; Alien Project Indexing
 ;;
@@ -1205,10 +1291,10 @@ function is executing."
   "Get the files for DIRECTORY using external tools."
   (let ((vcs (projectile-project-vcs directory)))
     (cond
-    ((eq vcs 'git)
-     (nconc (projectile-files-via-ext-command directory (projectile-get-ext-command vcs))
-            (projectile-get-sub-projects-files directory vcs)))
-    (t (projectile-files-via-ext-command directory (projectile-get-ext-command vcs))))))
+     ((eq vcs 'git)
+      (nconc (projectile-files-via-ext-command directory (projectile-get-ext-command vcs))
+             (projectile-get-sub-projects-files directory vcs)))
+     (t (projectile-files-via-ext-command directory (projectile-get-ext-command vcs))))))
 
 (define-obsolete-function-alias 'projectile-dir-files-external 'projectile-dir-files-alien "2.0.0")
 (define-obsolete-function-alias 'projectile-get-repo-files 'projectile-dir-files-alien "2.0.0")
@@ -1217,28 +1303,28 @@ function is executing."
   "Determine which external command to invoke based on the project's VCS.
 Fallback to a generic command when not in a VCS-controlled project."
   (pcase vcs
-   ('git projectile-git-command)
-   ('hg projectile-hg-command)
-   ('fossil projectile-fossil-command)
-   ('bzr projectile-bzr-command)
-   ('darcs projectile-darcs-command)
-   ('svn projectile-svn-command)
-   (_ projectile-generic-command)))
+    ('git projectile-git-command)
+    ('hg projectile-hg-command)
+    ('fossil projectile-fossil-command)
+    ('bzr projectile-bzr-command)
+    ('darcs projectile-darcs-command)
+    ('svn projectile-svn-command)
+    (_ projectile-generic-command)))
 
 (defun projectile-get-sub-projects-command (vcs)
   "Get the sub-projects command for VCS.
 Currently that's supported just for Git (sub-projects being Git
 sub-modules there)."
   (pcase vcs
-   ('git projectile-git-submodule-command)
-   (_ "")))
+    ('git projectile-git-submodule-command)
+    (_ "")))
 
 (defun projectile-get-ext-ignored-command (vcs)
   "Determine which external command to invoke based on the project's VCS."
   (pcase vcs
-   ('git projectile-git-ignored-command)
-   ;; TODO: Add support for other VCS
-   (_ nil)))
+    ('git projectile-git-ignored-command)
+    ;; 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."
@@ -1296,9 +1382,9 @@ they are excluded from the results of th
                     (file-name-as-directory (file-relative-name
                                              sub-project project-root))))
                (mapcar (lambda (file)
-                       (concat project-relative-path file))
-                     ;; TODO: Seems we forgot git hardcoded here
-                     (projectile-files-via-ext-command sub-project projectile-git-command))))
+                         (concat project-relative-path file))
+                       ;; TODO: Seems we forgot git hardcoded here
+                       (projectile-files-via-ext-command sub-project projectile-git-command))))
            (projectile-get-all-sub-projects project-root))))
 
 (defun projectile-get-repo-ignored-files (project vcs)
@@ -1318,10 +1404,15 @@ VCS is the VCS of the project."
   "Get a list of relative file names in the project ROOT by executing COMMAND.
 
 If `command' is nil or an empty string, return nil.
-This allows commands to be disabled."
+This allows commands to be disabled.
+
+Only text sent to standard output is taken into account."
   (when (stringp command)
     (let ((default-directory root))
-      (split-string (shell-command-to-string command) "\0" t))))
+      (with-temp-buffer
+        (shell-command command t "*projectile-files-errors*")
+        (let ((shell-output (buffer-substring (point-min) (point-max))))
+          (split-string (string-trim shell-output) "\0" t))))))
 
 (defun projectile-adjust-files (project vcs files)
   "First remove ignored files from FILES, then add back unignored files."
@@ -1405,7 +1496,7 @@ this case unignored files will be absent
 (defun projectile-project-buffers (&optional project)
   "Get a list of a project's buffers.
 If PROJECT is not specified the command acts on the current project."
-  (let* ((project-root (or project (projectile-project-root)))
+  (let* ((project-root (or project (projectile-acquire-root)))
          (all-buffers (cl-remove-if-not
                        (lambda (buffer)
                          (projectile-project-buffer-p buffer project-root))
@@ -1420,6 +1511,14 @@ If PROJECT is not specified the command
     (dolist (buffer project-buffers)
       (funcall action buffer))))
 
+(defun projectile-process-current-project-buffers-current (action)
+  "Invoke ACTION on every project buffer with that buffer current.
+ACTION is called without arguments."
+  (let ((project-buffers (projectile-project-buffers)))
+    (dolist (buffer project-buffers)
+      (with-current-buffer buffer
+        (funcall action)))))
+
 (defun projectile-project-buffer-files (&optional project)
   "Get a list of a project's buffer files.
 If PROJECT is not specified the command acts on the current project."
@@ -1505,7 +1604,7 @@ choices."
 
 ;;;###autoload
 (defun projectile-switch-to-buffer-other-frame ()
-  "Switch to a project buffer and show it in another window."
+  "Switch to a project buffer and show it in another frame."
   (interactive)
   (switch-to-buffer-other-frame
    (projectile-read-buffer-to-switch "Switch to buffer: ")))
@@ -1538,7 +1637,7 @@ Only buffers not visible in windows are
   "Do a `multi-occur' in the project's buffers.
 With a prefix argument, show NLINES of context."
   (interactive "P")
-  (let ((project (projectile-ensure-project (projectile-project-root))))
+  (let ((project (projectile-acquire-root)))
     (multi-occur (projectile-project-buffers project)
                  (car (occur-read-primary-args))
                  nlines)))
@@ -1572,29 +1671,40 @@ projectile project root."
   (let ((project-root (projectile-project-root)))
     (mapcar (lambda (f) (file-relative-name f project-root)) files)))
 
-(defun projectile-ignored-directory-p (directory)
+(defun projectile-ignored-directory-p
+    (directory &optional ignored-directories local-directory globally-ignored-directories)
   "Check if DIRECTORY should be ignored.
 
-Regular expressions can be used."
-  (cl-some
-   (lambda (name)
-     (string-match-p name directory))
-   (projectile-ignored-directories)))
+Regular expressions can be used. Pre-computed lists of
+IGNORED-DIRECTORIES and GLOBALLY-IGNORED-DIRECTORIES
+and the LOCAL-DIRECTORY name may optionally be provided."
+  (let ((ignored-directories (or ignored-directories (projectile-ignored-directories)))
+        (globally-ignored-directories (or globally-ignored-directories (projectile-globally-ignored-directory-names)))
+        (local-directory (or local-directory (file-name-nondirectory (directory-file-name directory)))))
+    (or (cl-some
+         (lambda (name)
+           (string-match-p name directory))
+         ignored-directories)
+        (cl-some
+         (lambda (name)
+           (string-match-p name local-directory))
+         globally-ignored-directories))))
 
-(defun projectile-ignored-file-p (file)
+(defun projectile-ignored-file-p (file &optional ignored-files)
   "Check if FILE should be ignored.
 
-Regular expressions can be used."
+Regular expressions can be used.  A pre-computed list of
+IGNORED-FILES may optionally be provided."
   (cl-some
    (lambda (name)
      (string-match-p name file))
-   (projectile-ignored-files)))
+   (or ignored-files (projectile-ignored-files))))
 
 (defun projectile-check-pattern-p (file pattern)
   "Check if FILE meets PATTERN."
   (or (string-suffix-p (directory-file-name pattern)
-                      (directory-file-name file))
-     (member file (file-expand-wildcards pattern t))))
+                       (directory-file-name file))
+      (member file (file-expand-wildcards pattern t))))
 
 (defun projectile-ignored-rel-p (file directory patterns)
   "Check if FILE should be ignored relative to DIRECTORY
@@ -1617,6 +1727,12 @@ according to PATTERNS: (ignored . unigno
      (projectile-project-ignored-files)))
    (projectile-unignored-files)))
 
+(defun projectile-globally-ignored-directory-names ()
+  "Return list of ignored directory names."
+  (projectile-difference
+   projectile-globally-ignored-directories
+   projectile-globally-unignored-directories))
+
 (defun projectile-ignored-directories ()
   "Return list of ignored directories."
   (projectile-difference
@@ -1739,6 +1855,12 @@ prefix the string will be assumed to be
         (insert-file-contents dirconfig)
         (while (not (eobp))
           (pcase (char-after)
+            ;; ignore comment lines if prefix char has been set
+            ((pred (lambda (leading-char)
+                     (and projectile-dirconfig-comment-prefix
+                          (eql leading-char
+                               projectile-dirconfig-comment-prefix))))
+             nil)
             (?+ (push (buffer-substring (1+ (point)) (line-end-position)) keep))
             (?- (push (buffer-substring (1+ (point)) (line-end-position)) ignore))
             (?! (push (buffer-substring (1+ (point)) (line-end-position)) ensure))
@@ -1763,36 +1885,38 @@ project-root for every file."
   (let ((prompt (projectile-prepend-project-name prompt))
         res)
     (setq res
-          (cond
-           ((eq projectile-completion-system 'ido)
-            (ido-completing-read prompt choices nil nil initial-input))
-           ((eq projectile-completion-system 'default)
-            (completing-read prompt choices nil nil initial-input))
-           ((eq projectile-completion-system 'helm)
-            (if (and (fboundp 'helm)
-                     (fboundp 'helm-make-source))
-                (helm :sources
-                      (helm-make-source "Projectile" 'helm-source-sync
-                        :candidates choices
-                        :action (if action
-                                    (prog1 action
-                                      (setq action nil))
-                                  #'identity))
-                      :prompt prompt
-                      :input initial-input
-                      :buffer "*helm-projectile*")
-              (user-error "Please install helm from \
-https://github.com/emacs-helm/helm")))
-           ((eq projectile-completion-system 'ivy)
-            (if (fboundp 'ivy-read)
-                (ivy-read prompt choices
-                          :initial-input initial-input
-                          :action (prog1 action
-                                    (setq action nil))
-                          :caller 'projectile-completing-read)
-              (user-error "Please install ivy from \
-https://github.com/abo-abo/swiper")))
-           (t (funcall projectile-completion-system prompt choices))))
+          (pcase (if (eq projectile-completion-system 'auto)
+                     (cond
+                      ((bound-and-true-p ido-mode)  'ido)
+                      ((bound-and-true-p helm-mode) 'helm)
+                      ((bound-and-true-p ivy-mode)  'ivy)
+                      (t 'default))
+                   projectile-completion-system)
+            ('default (completing-read prompt choices nil nil initial-input))
+            ('ido (ido-completing-read prompt choices nil nil initial-input))
+            ('helm
+             (if (and (fboundp 'helm)
+                      (fboundp 'helm-make-source))
+                 (helm :sources
+                       (helm-make-source "Projectile" 'helm-source-sync
+                                         :candidates choices
+                                         :action (if action
+                                                     (prog1 action
+                                                       (setq action nil))
+                                                   #'identity))
+                       :prompt prompt
+                       :input initial-input
+                       :buffer "*helm-projectile*")
+               (user-error "Please install helm")))
+            ('ivy
+             (if (fboundp 'ivy-read)
+                 (ivy-read prompt choices
+                           :initial-input initial-input
+                           :action (prog1 action
+                                     (setq action nil))
+                           :caller 'projectile-completing-read)
+               (user-error "Please install ivy")))
+            (_ (funcall projectile-completion-system prompt choices))))
     (if action
         (funcall action res)
       res)))
@@ -1854,7 +1978,7 @@ https://github.com/abo-abo/swiper")))
 
 (defun projectile-current-project-files ()
   "Return a list of the files in the current project."
-  (projectile-project-files (projectile-project-root)))
+  (projectile-project-files (projectile-acquire-root)))
 
 (defun projectile-process-current-project-files (action)
   "Process the current project's files using ACTION."
@@ -1872,7 +1996,7 @@ https://github.com/abo-abo/swiper")))
 
 (defun projectile-current-project-dirs ()
   "Return a list of dirs for the current project."
-  (projectile-project-dirs (projectile-ensure-project (projectile-project-root))))
+  (projectile-project-dirs (projectile-acquire-root)))
 
 (defun projectile-get-other-files (file-name &optional flex-matching)
   "Return a list of other files for FILE-NAME.
@@ -1882,8 +2006,8 @@ to match any basename."
   (if-let ((plist (projectile--related-files-plist-by-kind  file-name :other)))
       (projectile--related-files-from-plist plist)
     (projectile--other-extension-files file-name
-                                           (projectile-current-project-files)
-                                           flex-matching)))
+                                       (projectile-current-project-files)
+                                       flex-matching)))
 
 (defun projectile--find-other-file (&optional flex-matching ff-variant)
   "Switch between files with the same name but different extensions.
@@ -1921,7 +2045,7 @@ Other file extensions can be customized
 
 ;;;###autoload
 (defun projectile-find-other-file-other-frame (&optional flex-matching)
-  "Switch between files with the same name but different extensions in other window.
+  "Switch between files with the same name but different extensions in other frame.
 With FLEX-MATCHING, match any file that contains the base name of current file.
 Other file extensions can be customized with the variable `projectile-other-file-alist'."
   (interactive "P")
@@ -2029,7 +2153,7 @@ A typical example of such a defun would
 
 Subroutine for `projectile-find-file-dwim' and
 `projectile-find-file-dwim-other-window'"
-  (let* ((project-root (projectile-project-root))
+  (let* ((project-root (projectile-acquire-root))
          (project-files (projectile-project-files project-root))
          (files (projectile-select-files project-files invalidate-cache))
          (file (cond ((= (length files) 1)
@@ -2132,9 +2256,9 @@ defun, use that instead of `find-file'.
 would be `find-file-other-window' or `find-file-other-frame'"
   (interactive "P")
   (projectile-maybe-invalidate-cache invalidate-cache)
-  (let* ((project-root (projectile-ensure-project (projectile-project-root)))
+  (let* ((project-root (projectile-acquire-root))
          (file (projectile-completing-read "Find file: "
-                                          (projectile-project-files project-root)))
+                                           (projectile-project-files project-root)))
          (ff (or ff-variant #'find-file)))
     (when file
       (funcall ff (expand-file-name file project-root))
@@ -2169,7 +2293,7 @@ With a prefix arg INVALIDATE-CACHE inval
   (interactive)
   (let ((inhibit-read-only t)
         (val (not buffer-read-only))
-        (default-directory (projectile-ensure-project (projectile-project-root))))
+        (default-directory (projectile-acquire-root)))
     (add-dir-local-variable nil 'buffer-read-only val)
     (save-buffer)
     (kill-buffer)
@@ -2229,7 +2353,7 @@ With INVALIDATE-CACHE invalidates the ca
 defun, use that instead of `dired'.  A typical example of such a defun would be
 `dired-other-window' or `dired-other-frame'"
   (projectile-maybe-invalidate-cache invalidate-cache)
-  (let* ((project (projectile-ensure-project (projectile-project-root)))
+  (let* ((project (projectile-acquire-root))
          (dir (projectile-complete-dir project))
          (dired-v (or dired-variant #'dired)))
     (funcall dired-v (expand-file-name dir project))
@@ -2253,7 +2377,7 @@ With a prefix arg INVALIDATE-CACHE inval
 
 ;;;###autoload
 (defun projectile-find-dir-other-frame (&optional invalidate-cache)
-  "Jump to a project's directory in other window using completion.
+  "Jump to a project's directory in other frame using completion.
 
 With a prefix arg INVALIDATE-CACHE invalidates the cache first."
   (interactive "P")
@@ -2262,10 +2386,10 @@ With a prefix arg INVALIDATE-CACHE inval
 (defun projectile-complete-dir (project)
   (let ((project-dirs (projectile-project-dirs project)))
     (projectile-completing-read
-    "Find dir: "
-    (if projectile-find-dir-includes-top-level
-        (append '("./") project-dirs)
-      project-dirs))))
+     "Find dir: "
+     (if projectile-find-dir-includes-top-level
+         (append '("./") project-dirs)
+       project-dirs))))
 
 ;;;###autoload
 (defun projectile-find-test-file (&optional invalidate-cache)
@@ -2468,17 +2592,36 @@ If KIND is not provided, a list of possi
 The project types are symbols and they are linked to plists holding
 the properties of the various project types.")
 
-(cl-defun projectile-register-project-type
-    (project-type marker-files &key compilation-dir configure compile test run test-suffix test-prefix src-dir test-dir related-files-fn)
-  "Register a project type with projectile.
+(defun projectile--combine-plists (&rest plists)
+  "Create a single property list from all plists in PLISTS.
+The process starts by copying the first list, and then setting properties
+from the other lists.  Settings in the last list are the most significant
+ones and overrule settings in the other lists.  nil values are ignored in
+all but the first plist."
+  (let ((rtn (copy-sequence (pop plists)))
+	p v ls)
+    (while plists
+      (setq ls (pop plists))
+      (while ls
+	(setq p (pop ls) v (pop ls))
+        (when v
+	  (setq rtn (plist-put rtn p v)))))
+    rtn))
+
+(cl-defun projectile--build-project-plist
+    (marker-files &key project-file compilation-dir configure compile install package test run test-suffix test-prefix src-dir test-dir related-files-fn)
+  "Return a project type plist with the provided arguments.
 
 A project type is defined by PROJECT-TYPE, a set of MARKER-FILES,
 and optional keyword arguments:
+PROJECT-FILE the main project file in the root project directory.
 COMPILATION-DIR the directory to run the tests- and compilations in,
 CONFIGURE which specifies a command that configures the project
           `%s' in the command will be substituted with (projectile-project-root)
           before the command is run,
 COMPILE which specifies a command that builds the project,
+INSTALL which specifies a command to install the project.
+PACKAGE which specifies a command to package the project.
 TEST which specified a command that tests the project,
 RUN which specifies a command that runs the project,
 TEST-SUFFIX which specifies test file suffix, and
@@ -2489,17 +2632,22 @@ RELATED-FILES-FN which specifies a custo
 test/impl/other files as below:
     CUSTOM-FUNCTION accepts FILE as relative path from the project root and returns
     a plist containing :test, :impl or :other as key and the relative path/paths or
-    predicate as value. PREDICATE accepts a relative path as the input."
+    predicate as value.  PREDICATE accepts a relative path as the input."
   (let ((project-plist (list 'marker-files marker-files
+                             'project-file project-file
                              'compilation-dir compilation-dir
                              'configure-command configure
                              'compile-command compile
                              'test-command test
+                             'install-command install
+                             'package-command package
                              'run-command run)))
     ;; There is no way for the function to distinguish between an
     ;; explicit argument of nil and an omitted argument. However, the
     ;; body of the function is free to consider nil an abbreviation
     ;; for some other meaningful value
+    (when (and project-file (not (member project-file projectile-project-root-files)))
+      (add-to-list 'projectile-project-root-files project-file))
     (when test-suffix
       (plist-put project-plist 'test-suffix test-suffix))
     (when test-prefix
@@ -2510,10 +2658,112 @@ test/impl/other files as below:
       (plist-put project-plist 'test-dir test-dir))
     (when related-files-fn
       (plist-put project-plist 'related-files-fn related-files-fn))
+    project-plist))
 
-    (setq projectile-project-types
-          (cons `(,project-type . ,project-plist)
-                projectile-project-types))))
+(cl-defun projectile-register-project-type
+    (project-type marker-files &key project-file compilation-dir configure compile install package test run test-suffix test-prefix src-dir test-dir related-files-fn)
+  "Register a project type with projectile.
+
+A project type is defined by PROJECT-TYPE, a set of MARKER-FILES,
+and optional keyword arguments:
+PROJECT-FILE the main project file in the root project directory.
+COMPILATION-DIR the directory to run the tests- and compilations in,
+CONFIGURE which specifies a command that configures the project
+          `%s' in the command will be substituted with (projectile-project-root)
+          before the command is run,
+COMPILE which specifies a command that builds the project,
+INSTALL which specifies a command to install the project.
+PACKAGE which specifies a command to package the project.
+TEST which specified a command that tests the project,
+RUN which specifies a command that runs the project,
+TEST-SUFFIX which specifies test file suffix, and
+TEST-PREFIX which specifies test file prefix.
+SRC-DIR which specifies the path to the source relative to the project root.
+TEST-DIR which specifies the path to the tests relative to the project root.
+RELATED-FILES-FN which specifies a custom function to find the related files such as
+test/impl/other files as below:
+    CUSTOM-FUNCTION accepts FILE as relative path from the project root and returns
+    a plist containing :test, :impl or :other as key and the relative path/paths or
+    predicate as value.  PREDICATE accepts a relative path as the input."
+  (setq projectile-project-types
+        (cons `(,project-type .
+                              ,(projectile--build-project-plist
+                                 marker-files
+                                 :project-file project-file
+                                 :compilation-dir compilation-dir
+                                 :configure configure
+                                 :compile compile
+                                 :install install
+                                 :package package
+                                 :test test
+                                 :run run
+                                 :test-suffix test-suffix
+                                 :test-prefix test-prefix
+                                 :src-dir src-dir
+                                 :test-dir test-dir
+                                 :related-files-fn related-files-fn))
+                projectile-project-types)))
+
+(cl-defun projectile-update-project-type
+    (project-type &key marker-files project-file compilation-dir configure compile install package test run test-suffix test-prefix src-dir test-dir related-files-fn)
+    "Update an existing projectile project type.
+
+Non-nil passed items will override existing values for the project type given
+by PROJECT-TYPE.  Raise an error if PROJECT-TYPE is not already registered
+with projectile.  The arguments to this function are as for
+projectile-register-project-type:
+
+A project type is defined by PROJECT-TYPE, a set of MARKER-FILES,
+and optional keyword arguments:
+MARKER-FILES a set of indicator files for PROJECT-TYPE.
+PROJECT-FILE the main project file in the root project directory.
+COMPILATION-DIR the directory to run the tests- and compilations in,
+CONFIGURE which specifies a command that configures the project
+          `%s' in the command will be substituted with (projectile-project-root)
+          before the command is run,
+COMPILE which specifies a command that builds the project,
+INSTALL which specifies a command to install the project.
+PACKAGE which specifies a command to package the project.
+TEST which specified a command that tests the project,
+RUN which specifies a command that runs the project,
+TEST-SUFFIX which specifies test file suffix, and
+TEST-PREFIX which specifies test file prefix.
+SRC-DIR which specifies the path to the source relative to the project root.
+TEST-DIR which specifies the path to the tests relative to the project root.
+RELATED-FILES-FN which specifies a custom function to find the related files such as
+test/impl/other files as below:
+    CUSTOM-FUNCTION accepts FILE as relative path from the project root and returns
+    a plist containing :test, :impl or :other as key and the relative path/paths or
+    predicate as value.  PREDICATE accepts a relative path as the input."
+    (if-let ((existing-project-plist
+              (cl-find-if
+               (lambda (p) (eq project-type (car p))) projectile-project-types))
+             (new-plist
+              (projectile--build-project-plist
+               marker-files
+               :project-file project-file
+               :compilation-dir compilation-dir
+               :configure configure
+               :compile compile
+               :install install
+               :package package
+               :test test
+               :run run
+               :test-suffix test-suffix
+               :test-prefix test-prefix
+               :src-dir src-dir
+               :test-dir test-dir
+               :related-files-fn related-files-fn))
+             (merged-plist
+              (projectile--combine-plists
+               (cdr existing-project-plist) new-plist))
+             (project-type-elt (cons project-type merged-plist)))
+        (setq projectile-project-types
+              (mapcar (lambda (p) (if (eq project-type (car p))
+                                      project-type-elt
+                                    p))
+                      projectile-project-types))
+      (error "No existing project found for: %s" project-type)))
 
 (defun projectile-cabal-project-p ()
   "Check if a project contains *.cabal files but no stack.yaml file."
@@ -2521,6 +2771,7 @@ test/impl/other files as below:
        (not (projectile-verify-file "stack.yaml"))))
 
 (defun projectile-dotnet-project-p ()
+  "Check if a project contains a .NET project marker."
   (or (projectile-verify-file-wildcard "?*.csproj")
       (projectile-verify-file-wildcard "?*.fsproj")))
 
@@ -2529,11 +2780,155 @@ test/impl/other files as below:
   (or (projectile-verify-file "go.mod")
       (projectile-verify-file-wildcard "*.go")))
 
-(define-obsolete-variable-alias 'projectile-go-function 'projectile-go-project-test-function "1.0.0")
 (defcustom projectile-go-project-test-function #'projectile-go-project-p
   "Function to determine if project's type is go."
   :group 'projectile
-  :type 'function)
+  :type 'function
+  :package-version '(projectile . "1.0.0"))
+
+;;;; Constant signifying opting out of CMake preset commands.
+(defconst projectile--cmake-no-preset "*no preset*")
+
+(defun projectile--cmake-version ()
+  "Compute CMake version."
+  (let* ((string (shell-command-to-string "cmake --version"))
+         (match (string-match "^cmake version \\(.*\\)$" string)))
+    (when match
+      (version-to-list (match-string 1 string)))))
+
+(defun projectile--cmake-check-version (version)
+  "Check if CMake version is at least VERSION."
+  (and
+   (version-list-<= version (projectile--cmake-version))))
+
+(defconst projectile--cmake-command-presets-minimum-version-alist
+    '((:configure-command . (3 19))
+      (:compile-command . (3 20))
+      (:test-command . (3 20))))
+
+(defun projectile--cmake-command-presets-supported (command-type)
+  "Check if CMake supports presets for COMMAND-TYPE."
+  (let ((minimum-version
+         (cdr (assoc command-type projectile--cmake-command-presets-minimum-version-alist))))
+    (projectile--cmake-check-version minimum-version)))
+
+(defun projectile--cmake-read-preset (filename)
+  "Read CMake preset from FILENAME."
+  (when (file-exists-p filename)
+        (with-temp-buffer
+          (insert-file-contents filename)
+          (when (functionp 'json-parse-buffer)
+            (json-parse-buffer :array-type 'list)))))
+
+(defconst projectile--cmake-command-preset-array-id-alist
+  '((:configure-command . "configurePresets")
+    (:compile-command . "buildPresets")
+    (:test-command . "testPresets")))
+
+(defun projectile--cmake-command-preset-array-id (command-type)
+  "Map from COMMAND-TYPE to id of command preset array in CMake preset."
+  (cdr (assoc command-type projectile--cmake-command-preset-array-id-alist)))
+
+(defun projectile--cmake-command-presets (filename command-type)
+  "Get CMake COMMAND-TYPE presets from FILENAME."
+  (when-let ((preset (projectile--cmake-read-preset (projectile-expand-root filename))))
+    (cl-remove-if
+     (lambda (preset) (equal (gethash "hidden" preset) t))
+     (gethash (projectile--cmake-command-preset-array-id command-type) preset))))
+
+(defun projectile--cmake-all-command-presets (command-type)
+  "Get CMake user and system COMMAND-TYPE presets."
+  (projectile-flatten
+   (mapcar (lambda (filename) (projectile--cmake-command-presets filename command-type))
+           '("CMakeUserPresets.json" "CMakePresets.json"))))
+
+(defun projectile--cmake-command-preset-names (command-type)
+  "Get names of CMake user and system COMMAND-TYPE presets."
+  (mapcar (lambda (preset)
+            (gethash "name" preset))
+          (projectile--cmake-all-command-presets command-type)))
+
+(defcustom projectile-enable-cmake-presets nil
+  "Enables configuration with CMake presets.
+
+When `projectile-enable-cmake-presets' is non-nil, CMake projects can
+be configured, built and tested using presets."
+  :group 'projectile
+  :type 'boolean
+  :package-version '(projectile . "2.4.0"))
+
+(defun projectile--cmake-use-command-presets (command-type)
+  "Test whether or not to use command presets for COMMAND-TYPE.
+
+Presets are used if `projectile-enable-cmake-presets' is non-nil, and CMake
+supports presets for COMMAND-TYPE, and `json-parse-buffer' is available."
+  (and projectile-enable-cmake-presets
+       (projectile--cmake-command-presets-supported command-type)
+       (functionp 'json-parse-buffer)))
+
+(defun projectile--cmake-select-command (command-type)
+  "Select a CMake command preset or a manual CMake command.
+
+The selection is done like this:
+
+- If `projectile--cmake-use-commands-presets' for COMMAND-TYPE returns true, and
+there is at least one preset available for COMMAND-TYPE, the user is prompted to
+select a name of a command preset, or opt a manual command by selecting
+`projectile--cmake-no-preset'.
+
+- Else `projectile--cmake-no-preset' is used."
+  (if-let ((use-presets (projectile--cmake-use-command-presets command-type))
+           (preset-names (projectile--cmake-command-preset-names command-type)))
+      (projectile-completing-read
+       "Use preset: "
+       (append preset-names `(,projectile--cmake-no-preset)))
+    projectile--cmake-no-preset))
+
+(defconst projectile--cmake-manual-command-alist
+  '((:configure-command . "cmake -S . -B build")
+    (:compile-command . "cmake --build build")
+    (:test-command . "cmake --build build --target test")))
+
+(defun projectile--cmake-manual-command (command-type)
+  "Create maunual CMake COMMAND-TYPE command."
+  (cdr (assoc command-type projectile--cmake-manual-command-alist)))
+
+(defconst projectile--cmake-preset-command-alist
+  '((:configure-command . "cmake . --preset %s")
+    (:compile-command . "cmake --build --preset %s")
+    (:test-command . "ctest --preset %s")))
+
+(defun projectile--cmake-preset-command (command-type preset)
+  "Create CMake COMMAND-TYPE command using PRESET."
+  (format (cdr (assoc command-type projectile--cmake-preset-command-alist)) preset))
+
+(defun projectile--cmake-command (command-type)
+  "Create a CMake COMMAND-TYPE command.
+
+The command is created like this:
+
+- If `projectile--cmake-select-command' returns `projectile--cmake-no-preset'
+a manual COMMAND-TYPE command is created with
+`projectile--cmake-manual-command'.
+
+- Else a preset COMMAND-TYPE command using the selected preset is created with
+`projectile--cmake-preset-command'."
+  (let ((maybe-preset (projectile--cmake-select-command command-type)))
+    (if (equal maybe-preset projectile--cmake-no-preset)
+        (projectile--cmake-manual-command command-type)
+      (projectile--cmake-preset-command command-type maybe-preset))))
+
+(defun projectile--cmake-configure-command ()
+  "CMake configure command."
+  (projectile--cmake-command :configure-command))
+
+(defun projectile--cmake-compile-command ()
+  "CMake compile command."
+  (projectile--cmake-command :compile-command))
+
+(defun projectile--cmake-test-command ()
+  "CMake test command."
+  (projectile--cmake-command :test-command))
 
 ;;; Project type registration
 ;;
@@ -2550,6 +2945,7 @@ test/impl/other files as below:
 (projectile-register-project-type 'haskell-cabal #'projectile-cabal-project-p
                                   :compile "cabal build"
                                   :test "cabal test"
+                                  :run "cabal run"
                                   :test-suffix "Spec")
 (projectile-register-project-type 'dotnet #'projectile-dotnet-project-p
                                   :compile "dotnet build"
@@ -2563,120 +2959,175 @@ test/impl/other files as below:
 
 ;; Universal
 (projectile-register-project-type 'scons '("SConstruct")
+                                  :project-file "SConstruct"
                                   :compile "scons"
                                   :test "scons test"
                                   :test-suffix "test")
 (projectile-register-project-type 'meson '("meson.build")
+                                  :project-file "meson.build"
                                   :compilation-dir "build"
                                   :configure "meson %s"
                                   :compile "ninja"
                                   :test "ninja test")
 (projectile-register-project-type 'nix '("default.nix")
+                                  :project-file "default.nix"
                                   :compile "nix-build"
                                   :test "nix-build")
+(projectile-register-project-type 'bazel '("WORKSPACE")
+                                  :project-file "WORKSPACE"
+                                  :compile "bazel build"
+                                  :test "bazel test"
+                                  :run "bazel run")
+(projectile-register-project-type 'debian '("debian/control")
+                                  :project-file "debian/control"
+                                  :compile "debuild -uc -us")
+
 ;; Make & CMake
 (projectile-register-project-type 'make '("Makefile")
+                                  :project-file "Makefile"
                                   :compile "make"
-                                  :test "make test")
+                                  :test "make test"
+                                  :install "make install")
 (projectile-register-project-type 'cmake '("CMakeLists.txt")
-                                  :configure "cmake %s"
-                                  :compile "cmake --build ."
-                                  :test "ctest")
+                                  :project-file "CMakeLists.txt"
+                                  :configure #'projectile--cmake-configure-command
+                                  :compile #'projectile--cmake-compile-command
+                                  :test #'projectile--cmake-test-command
+                                  :install "cmake --build build --target install"
+                                  :package "cmake --build build --target package")
 ;; PHP
 (projectile-register-project-type 'php-symfony '("composer.json" "app" "src" "vendor")
+                                  :project-file "composer.json"
                                   :compile "app/console server:run"
                                   :test "phpunit -c app "
                                   :test-suffix "Test")
 ;; Erlang & Elixir
 (projectile-register-project-type 'rebar '("rebar.config")
-                                  :compile "rebar"
-                                  :test "rebar eunit"
+                                  :project-file "rebar.config"
+                                  :compile "rebar3 compile"
+                                  :test "rebar3 do eunit,ct"
                                   :test-suffix "_SUITE")
 (projectile-register-project-type 'elixir '("mix.exs")
+                                  :project-file "mix.exs"
                                   :compile "mix compile"
                                   :src-dir "lib/"
                                   :test "mix test"
                                   :test-suffix "_test")
 ;; JavaScript
 (projectile-register-project-type 'grunt '("Gruntfile.js")
+                                  :project-file "Gruntfile.js"
                                   :compile "grunt"
                                   :test "grunt test")
 (projectile-register-project-type 'gulp '("gulpfile.js")
+                                  :project-file "gulpfile.js"
                                   :compile "gulp"
                                   :test "gulp test")
 (projectile-register-project-type 'npm '("package.json")
+                                  :project-file "package.json"
                                   :compile "npm install"
                                   :test "npm test"
                                   :test-suffix ".test")
 ;; Angular
 (projectile-register-project-type 'angular '("angular.json" ".angular-cli.json")
+                                  :project-file "angular.json"
                                   :compile "ng build"
                                   :run "ng serve"
-                                  :test "ng test")
+                                  :test "ng test"
+                                  :test-suffix ".spec")
 ;; Python
 (projectile-register-project-type 'django '("manage.py")
+                                  :project-file "manage.py"
                                   :compile "python manage.py runserver"
                                   :test "python manage.py test"
                                   :test-prefix "test_"
                                   :test-suffix"_test")
 (projectile-register-project-type 'python-pip '("requirements.txt")
+                                  :project-file "requirements.txt"
                                   :compile "python setup.py build"
                                   :test "python -m unittest discover"
                                   :test-prefix "test_"
                                   :test-suffix"_test")
 (projectile-register-project-type 'python-pkg '("setup.py")
+                                  :project-file "setup.py"
                                   :compile "python setup.py build"
                                   :test "python -m unittest discover"
                                   :test-prefix "test_"
                                   :test-suffix"_test")
 (projectile-register-project-type 'python-tox '("tox.ini")
+                                  :project-file "tox.ini"
                                   :compile "tox -r --notest"
                                   :test "tox"
                                   :test-prefix "test_"
                                   :test-suffix"_test")
 (projectile-register-project-type 'python-pipenv '("Pipfile")
+                                  :project-file "Pipfile"
                                   :compile "pipenv run build"
                                   :test "pipenv run test"
                                   :test-prefix "test_"
                                   :test-suffix "_test")
+(projectile-register-project-type 'python-poetry '("poetry.lock")
+                                  :project-file "poetry.lock"
+                                  :compile "poetry build"
+                                  :test "poetry run python -m unittest discover"
+                                  :test-prefix "test_"
+                                  :test-suffix "_test")
 ;; Java & friends
 (projectile-register-project-type 'maven '("pom.xml")
-                                  :compile "mvn clean install"
-                                  :test "mvn test"
+                                  :project-file "pom.xml"
+                                  :compile "mvn -B clean install"
+                                  :test "mvn -B test"
                                   :test-suffix "Test"
                                   :src-dir "main/src/"
                                   :test-dir "main/test/")
 (projectile-register-project-type 'gradle '("build.gradle")
+                                  :project-file "build.gradle"
                                   :compile "gradle build"
                                   :test "gradle test"
                                   :test-suffix "Spec")
 (projectile-register-project-type 'gradlew '("gradlew")
+                                  :project-file "gradlew"
                                   :compile "./gradlew build"
                                   :test "./gradlew test"
                                   :test-suffix "Spec")
 (projectile-register-project-type 'grails '("application.properties" "grails-app")
+                                  :project-file "application.properties"
                                   :compile "grails package"
                                   :test "grails test-app"
                                   :test-suffix "Spec")
+;; Scala
 (projectile-register-project-type 'sbt '("build.sbt")
+                                  :project-file "build.sbt"
                                   :compile "sbt compile"
                                   :test "sbt test"
                                   :test-suffix "Spec")
+
+(projectile-register-project-type 'mill '("build.sc")
+                                  :project-file "build.sc"
+                                  :compile "mill all __.compile"
+                                  :test "mill all __.test"
+                                  :test-suffix "Test")
+
+;; Clojure
 (projectile-register-project-type 'lein-test '("project.clj")
+                                  :project-file "project.clj"
                                   :compile "lein compile"
                                   :test "lein test"
                                   :test-suffix "_test")
 (projectile-register-project-type 'lein-midje '("project.clj" ".midje.clj")
+                                  :project-file "project.clj"
                                   :compile "lein compile"
                                   :test "lein midje"
                                   :test-prefix "t_")
 (projectile-register-project-type 'boot-clj '("build.boot")
+                                  :project-file "build.boot"
                                   :compile "boot aot"
                                   :test "boot test"
                                   :test-suffix "_test")
 (projectile-register-project-type 'clojure-cli '("deps.edn")
+                                  :project-file "deps.edn"
                                   :test-suffix "_test")
 (projectile-register-project-type 'bloop '(".bloop")
+                                  :project-file ".bloop"
                                   :compile "bloop compile root"
                                   :test "bloop test --propagate --reporter scalac root"
                                   :src-dir "src/main/"
@@ -2684,12 +3135,14 @@ test/impl/other files as below:
                                   :test-suffix "Spec")
 ;; Ruby
 (projectile-register-project-type 'ruby-rspec '("Gemfile" "lib" "spec")
+                                  :project-file "Gemfile"
                                   :compile "bundle exec rake"
                                   :src-dir "lib/"
                                   :test "bundle exec rspec"
                                   :test-dir "spec/"
                                   :test-suffix "_spec")
 (projectile-register-project-type 'ruby-test '("Gemfile" "lib" "test")
+                                  :project-file "Gemfile"
                                   :compile"bundle exec rake"
                                   :src-dir "lib/"
                                   :test "bundle exec rake test"
@@ -2697,11 +3150,13 @@ test/impl/other files as below:
 ;; Rails needs to be registered after npm, otherwise `package.json` makes it `npm`.
 ;; https://github.com/bbatsov/projectile/pull/1191
 (projectile-register-project-type 'rails-test '("Gemfile" "app" "lib" "db" "config" "test")
+                                  :project-file "Gemfile"
                                   :compile "bundle exec rails server"
                                   :src-dir "lib/"
                                   :test "bundle exec rake test"
                                   :test-suffix "_test")
 (projectile-register-project-type 'rails-rspec '("Gemfile" "app" "lib" "db" "config" "spec")
+                                  :project-file "Gemfile"
                                   :compile "bundle exec rails server"
                                   :src-dir "lib/"
                                   :test "bundle exec rspec"
@@ -2709,6 +3164,7 @@ test/impl/other files as below:
                                   :test-suffix "_spec")
 ;; Crystal
 (projectile-register-project-type 'crystal-spec '("shard.yml")
+                                  :project-file "shard.yml"
                                   :src-dir "src/"
                                   :test "crystal spec"
                                   :test-dir "spec/"
@@ -2716,31 +3172,58 @@ test/impl/other files as below:
 
 ;; Emacs
 (projectile-register-project-type 'emacs-cask '("Cask")
+                                  :project-file "Cask"
                                   :compile "cask install"
                                   :test-prefix "test-"
                                   :test-suffix "-test")
+(projectile-register-project-type 'emacs-eldev (lambda () (or (projectile-verify-file "Eldev")
+                                                              (projectile-verify-file "Eldev-local")))
+                                  :project-file "Eldev"
+                                  :compile "eldev compile"
+                                  :test "eldev test"
+                                  :run "eldev emacs"
+                                  :package "eldev package")
 
 ;; R
 (projectile-register-project-type 'r '("DESCRIPTION")
+                                  :project-file "DESCRIPTION"
                                   :compile "R CMD INSTALL --with-keep.source ."
                                   :test (concat "R CMD check -o " temporary-file-directory " ."))
 
 ;; Haskell
 (projectile-register-project-type 'haskell-stack '("stack.yaml")
+                                  :project-file "stack.yaml"
                                   :compile "stack build"
                                   :test "stack build --test"
                                   :test-suffix "Spec")
 
 ;; Rust
 (projectile-register-project-type 'rust-cargo '("Cargo.toml")
+                                  :project-file "Cargo.toml"
                                   :compile "cargo build"
                                   :test "cargo test"
                                   :run "cargo run")
 
 ;; Racket
 (projectile-register-project-type 'racket '("info.rkt")
-                                  :test "raco test .")
-
+                                  :project-file "info.rkt"
+                                  :test "raco test ."
+                                  :install "raco pkg install"
+                                  :package "raco pkg create --source $(pwd)")
+
+;; Dart
+(projectile-register-project-type 'dart '("pubspec.yaml")
+                                  :project-file "pubspec.yaml"
+                                  :compile "pub get"
+                                  :test "pub run test"
+                                  :run "dart"
+                                  :test-suffix "_test.dart")
+
+;; OCaml
+(projectile-register-project-type 'ocaml-dune '("dune-project")
+                                  :project-file "dune-project"
+                                  :compile "dune build"
+                                  :test "dune runtest")
 
 (defvar-local projectile-project-type nil
   "Buffer local var for overriding the auto-detected project type.
@@ -2755,9 +3238,9 @@ Fallsback to a generic project type when
                    (lambda (project-type-record)
                      (let ((project-type (car project-type-record))
                            (marker (plist-get (cdr project-type-record) 'marker-files)))
-                       (if (listp marker)
-                           (and (projectile-verify-files marker) project-type)
-                         (and (funcall marker) project-type))))
+                       (if (functionp marker)
+                           (and (funcall marker) project-type)
+                         (and (projectile-verify-files marker) project-type))))
                    projectile-project-types))
              'generic)))
     (puthash (projectile-project-root) project-type projectile-project-type-cache)
@@ -2784,7 +3267,7 @@ The project type is cached for improved
   "Display info for current project."
   (interactive)
   (message "Project dir: %s ## Project VCS: %s ## Project type: %s"
-           (projectile-project-root)
+           (projectile-acquire-root)
            (projectile-project-vcs)
            (projectile-project-type)))
 
@@ -2805,8 +3288,9 @@ Expands wildcards using `file-expand-wil
   "Determine the VCS used by the project if any.
 PROJECT-ROOT is the targeted directory.  If nil, use
 `projectile-project-root'."
-  (or project-root (setq project-root (projectile-project-root)))
+  (or project-root (setq project-root (projectile-acquire-root)))
   (cond
+   ;; first we check for a VCS marker in the project root itself
    ((projectile-file-exists-p (expand-file-name ".git" project-root)) 'git)
    ((projectile-file-exists-p (expand-file-name ".hg" project-root)) 'hg)
    ((projectile-file-exists-p (expand-file-name ".fslckout" project-root)) 'fossil)
@@ -2814,6 +3298,10 @@ PROJECT-ROOT is the targeted directory.
    ((projectile-file-exists-p (expand-file-name ".bzr" project-root)) 'bzr)
    ((projectile-file-exists-p (expand-file-name "_darcs" project-root)) 'darcs)
    ((projectile-file-exists-p (expand-file-name ".svn" project-root)) 'svn)
+   ;; then we check if there's a VCS marker up the directory tree
+   ;; that covers the case when a project is part of a multi-project repository
+   ;; in those cases you can still the VCS to get a list of files for
+   ;; the project in question
    ((projectile-locate-dominating-file project-root ".git") 'git)
    ((projectile-locate-dominating-file project-root ".hg") 'hg)
    ((projectile-locate-dominating-file project-root ".fslckout") 'fossil)
@@ -2824,7 +3312,9 @@ PROJECT-ROOT is the targeted directory.
    (t 'none)))
 
 (defun projectile--test-name-for-impl-name (impl-file-path)
-  "Determine the name of the test file for IMPL-FILE-PATH."
+  "Determine the name of the test file for IMPL-FILE-PATH.
+
+IMPL-FILE-PATH may be a absolute path, relative path or a file name."
   (let* ((project-type (projectile-project-type))
          (impl-file-name (file-name-sans-extension (file-name-nondirectory impl-file-path)))
          (impl-file-ext (file-name-extension impl-file-path))
@@ -2835,19 +3325,58 @@ PROJECT-ROOT is the targeted directory.
      (test-suffix (concat impl-file-name test-suffix "." impl-file-ext))
      (t (error "Project type `%s' not supported!" project-type)))))
 
-(defun projectile-create-test-file-for (impl-file-path)
-  "Create a test file for IMPL-FILE-PATH."
-  (let* ((test-file (projectile--test-name-for-impl-name impl-file-path))
-         (project-root (projectile-project-root))
-         (relative-dir (file-name-directory (file-relative-name impl-file-path project-root)))
-         (src-dir-name (projectile-src-directory (projectile-project-type)))
-         (test-dir-name (projectile-test-directory (projectile-project-type)))
-         (test-dir (expand-file-name (replace-regexp-in-string src-dir-name test-dir-name relative-dir) project-root))
-         (test-path (expand-file-name test-file test-dir)))
-    (unless (file-exists-p test-path)
-      (progn (unless (file-exists-p test-dir)
-               (make-directory test-dir :create-parents))
-             test-path))))
+(defun projectile--impl-name-for-test-name (test-file-path)
+  "Determine the name of the implementation file for TEST-FILE-PATH.
+
+TEST-FILE-PATH may be a absolute path, relative path or a file name."
+  (let* ((project-type (projectile-project-type))
+         (test-file-name (file-name-sans-extension (file-name-nondirectory test-file-path)))
+         (test-file-ext (file-name-extension test-file-path))
+         (test-prefix (funcall projectile-test-prefix-function project-type))
+         (test-suffix (funcall projectile-test-suffix-function project-type)))
+    (cond
+     (test-prefix
+      (concat (string-remove-prefix test-prefix test-file-name) "." test-file-ext))
+     (test-suffix
+      (concat (string-remove-suffix test-suffix test-file-name) "." test-file-ext))
+     (t (error "Project type `%s' not supported!" project-type)))))
+
+(defun projectile--impl-to-test-dir (impl-dir-path)
+  "Return the directory path of a test whose impl file resides in IMPL-DIR-PATH.
+
+Occurrences of the current project type's src-dir property (which should be a
+string) are replaced with the current project type's test-dir property
+ (which should be a string) to obtain the new directory.
+
+An error is signalled if either the src-dir or test-dir properties are not
+strings."
+  (let ((test-dir (projectile-test-directory (projectile-project-type)))
+        (impl-dir (projectile-src-directory (projectile-project-type))))
+    (if (and (stringp test-dir) (stringp impl-dir))
+        (projectile-complementary-dir impl-dir-path impl-dir test-dir)
+      (error "Expected the current project's :test-dir and :impl-dir properties to be strings but found %s and %s" test-dir impl-dir))))
+
+(defun projectile-complementary-dir (dir-path string replacement)
+  "Return the \"complementary\" directory of DIR-PATH by replacing STRING in DIR-PATH with REPLACEMENT."
+  (let* ((project-root (projectile-project-root))
+         (relative-dir (file-name-directory (file-relative-name dir-path project-root))))
+    (projectile-expand-root
+     (replace-regexp-in-string string replacement relative-dir))))
+
+(defun projectile--create-directories-for (path)
+  "Create directories necessary for PATH."
+  (unless (file-exists-p path)
+    (make-directory (if (file-directory-p path)
+                        path
+                      (file-name-directory path))
+                    :create-parents)))
+
+(defun projectile--test-file-fallback (file-name)
+  "Attempt to build a path for the test file of FILE-NAME using the src-dir and test-dir properties of the current project type which should be strings, an error is signalled if this is not the case."
+  (projectile--complementary-file
+   file-name
+   #'projectile--impl-to-test-dir
+   #'projectile--test-name-for-impl-name))
 
 (defun projectile-find-implementation-or-test (file-name)
   "Given a FILE-NAME return the matching implementation or test filename.
@@ -2864,13 +3393,15 @@ test file."
            "No matching source file found for project type `%s'"
            (projectile-project-type))))
     ;; find the matching test file
-    (let ((test-file (projectile-find-matching-test file-name)))
-      (if test-file
-          (projectile-expand-root test-file)
-        (if projectile-create-missing-test-files
-            (projectile-create-test-file-for file-name)
-          (error "No matching test file found for project type `%s'"
-                 (projectile-project-type)))))))
+    (let* ((test-file (projectile-find-matching-test file-name))
+           (test-file-or-fallback (or test-file (projectile--test-file-fallback file-name)))
+           (expanded-test-file (projectile-expand-root test-file-or-fallback)))
+      (cond ((file-exists-p expanded-test-file) expanded-test-file)
+            (projectile-create-missing-test-files
+             (projectile--create-directories-for expanded-test-file)
+             expanded-test-file)
+            (t (error "No matching test file found for project type `%s'"
+                      (projectile-project-type)))))))
 
 ;;;###autoload
 (defun projectile-find-implementation-or-test-other-window ()
@@ -2923,7 +3454,7 @@ Fallback to DEFAULT-VALUE for missing at
   (projectile-project-type-attribute project-type 'test-dir "test/"))
 
 (defun projectile-dirname-matching-count (a b)
-  "Count matching dirnames ascending file paths."
+  "Count matching dirnames ascending file paths in A and B."
   (setq a (reverse (split-string (or (file-name-directory a) "") "/" t))
         b (reverse (split-string (or (file-name-directory b) "") "/" t)))
   (let ((common 0))
@@ -2965,13 +3496,48 @@ Fallback to DEFAULT-VALUE for missing at
         (or (string-equal prefix-name name)
             (string-equal suffix-name name))))))
 
+(defun projectile--complementary-file (file-path dir-fn filename-fn)
+  "Apply DIR-FN and FILENAME-FN to the directory and name of FILE-PATH.
+
+More specifically, return DIR-FN applied to the directory of FILE-PATH
+concatenated with FILENAME-FN applied to the file name of FILE-PATH."
+  (let* ((filename (file-name-nondirectory file-path))
+         (complementary-filename (funcall filename-fn filename))
+         (dir (funcall dir-fn (file-name-directory file-path))))
+    (concat (file-name-as-directory dir) complementary-filename)))
+
+(defun projectile--impl-file-from-src-dir-fn (test-file)
+  "Return the implementation file path for the absolute path TEST-FILE relative to the project root in the case the current project type's src-dir has been set to a custom function, return nil if this is not the case or the path points to a file that does not exist."
+  (when-let ((src-dir (projectile-src-directory (projectile-project-type))))
+    (when (functionp src-dir)
+      (let ((impl-file (projectile--complementary-file
+                        test-file
+                        src-dir
+                        #'projectile--impl-name-for-test-name)))
+        (when (file-exists-p impl-file)
+          (file-relative-name impl-file (projectile-project-root)))))))
+
+(defun projectile--test-file-from-test-dir-fn (impl-file)
+  "Return the test file path for the absolute path IMPL-FILE relative to the project root, in the case the current project type's test-dir has been set to a custom function, else return nil."
+  (when-let ((test-dir (projectile-test-directory (projectile-project-type))))
+    (when (functionp test-dir)
+      (file-relative-name
+       (projectile--complementary-file
+        impl-file
+        test-dir
+        #'projectile--test-name-for-impl-name)
+       (projectile-project-root)))))
+
 (defun projectile--find-matching-test (impl-file)
   "Return a list of test files for IMPL-FILE."
-  (if-let ((plist (projectile--related-files-plist-by-kind impl-file :test)))
-      (projectile--related-files-from-plist plist)
-    (if-let ((predicate (projectile--impl-to-test-predicate impl-file)))
+  (if-let ((test-file-from-test-dir-fn
+            (projectile--test-file-from-test-dir-fn impl-file)))
+      (list test-file-from-test-dir-fn)
+    (if-let ((plist (projectile--related-files-plist-by-kind impl-file :test)))
+        (projectile--related-files-from-plist plist)
+      (when-let ((predicate (projectile--impl-to-test-predicate impl-file)))
         (projectile--best-or-all-candidates-based-on-parents-dirs
-         impl-file (cl-remove-if-not predicate (projectile-current-project-files))))))
+         impl-file (cl-remove-if-not predicate (projectile-current-project-files)))))))
 
 (defun projectile--test-to-impl-predicate (test-file)
   "Return a predicate, which returns t for any impl files for TEST-FILE."
@@ -2985,11 +3551,14 @@ Fallback to DEFAULT-VALUE for missing at
 
 (defun projectile--find-matching-file (test-file)
   "Return a list of impl files tested by TEST-FILE."
-  (if-let ((plist (projectile--related-files-plist-by-kind test-file :impl)))
-      (projectile--related-files-from-plist plist)
-    (if-let ((predicate (projectile--test-to-impl-predicate test-file)))
-        (projectile--best-or-all-candidates-based-on-parents-dirs
-         test-file (cl-remove-if-not predicate (projectile-current-project-files))))))
+  (if-let ((impl-file-from-src-dir-fn
+            (projectile--impl-file-from-src-dir-fn test-file)))
+      (list impl-file-from-src-dir-fn)
+    (if-let ((plist (projectile--related-files-plist-by-kind test-file :impl)))
+        (projectile--related-files-from-plist plist)
+      (if-let ((predicate (projectile--test-to-impl-predicate test-file)))
+          (projectile--best-or-all-candidates-based-on-parents-dirs
+           test-file (cl-remove-if-not predicate (projectile-current-project-files)))))))
 
 (defun projectile--choose-from-candidates (candidates)
   "Choose one item from CANDIDATES."
@@ -3179,7 +3748,7 @@ to `projectile-grep-default-files'.
 With REGEXP given, don't query the user for a regexp."
   (interactive "i\nP")
   (require 'grep) ;; for `rgrep'
-  (let* ((roots (projectile-get-project-directories (projectile-project-root)))
+  (let* ((roots (projectile-get-project-directories (projectile-acquire-root)))
          (search-regexp (or regexp
                             (projectile--read-search-string-with-default "Grep for")))
          (files (and arg (or (and (equal current-prefix-arg '-)
@@ -3248,7 +3817,7 @@ regular expression."
                                               '()))))))
             ;; reset the prefix arg, otherwise it will affect the ag-command
             (current-prefix-arg nil))
-        (funcall ag-command search-term (projectile-project-root)))
+        (funcall ag-command search-term (projectile-acquire-root)))
     (error "Package 'ag' is not available")))
 
 ;;;###autoload
@@ -3266,7 +3835,7 @@ regular expression."
                           (append projectile-globally-ignored-files
                                   projectile-globally-ignored-directories))))
         (ripgrep-regexp search-term
-                        (projectile-project-root)
+                        (projectile-acquire-root)
                         (if arg
                             args
                           (cons "--fixed-strings" args))))
@@ -3276,7 +3845,9 @@ regular expression."
   "Return a string with exclude patterns for ctags."
   (mapconcat (lambda (pattern) (format "--exclude=\"%s\""
                                        (directory-file-name pattern)))
-             (projectile-ignored-directories-rel) " "))
+             (append
+              (projectile-ignored-directories-rel)
+              (projectile-patterns-to-ignore)) " "))
 
 ;;;###autoload
 (defun projectile-regenerate-tags ()
@@ -3285,19 +3856,22 @@ regular expression."
   (if (and (boundp 'ggtags-mode)
            (memq projectile-tags-backend '(auto ggtags)))
       (progn
-        (let* ((ggtags-project-root (projectile-project-root))
+        (let* ((ggtags-project-root (projectile-acquire-root))
                (default-directory ggtags-project-root))
           (ggtags-ensure-project)
           (ggtags-update-tags t)))
-    (let* ((project-root (projectile-project-root))
+    (let* ((project-root (projectile-acquire-root))
            (tags-exclude (projectile-tags-exclude-patterns))
            (default-directory project-root)
            (tags-file (expand-file-name projectile-tags-file-name))
-           (command (format projectile-tags-command tags-file tags-exclude default-directory))
+           (command (format projectile-tags-command
+                            (or (file-remote-p tags-file 'localname) tags-file)
+                            tags-exclude
+                            "."))
            shell-output exit-code)
       (with-temp-buffer
         (setq exit-code
-              (call-process-shell-command command nil (current-buffer))
+              (process-file-shell-command command nil (current-buffer))
               shell-output (string-trim
                             (buffer-substring (point-min) (point-max)))))
       (unless (zerop exit-code)
@@ -3355,56 +3929,65 @@ regular expression."
 (defun projectile-run-command-in-root ()
   "Invoke `execute-extended-command' in the project's root."
   (interactive)
-  (projectile-with-default-dir (projectile-ensure-project (projectile-project-root))
+  (projectile-with-default-dir (projectile-acquire-root)
     (call-interactively #'execute-extended-command)))
 
 ;;;###autoload
-(defun projectile-run-shell-command-in-root ()
+(defun projectile-run-shell-command-in-root (command &optional output-buffer error-buffer)
   "Invoke `shell-command' in the project's root."
-  (interactive)
-  (projectile-with-default-dir (projectile-ensure-project (projectile-project-root))
-    (call-interactively #'shell-command)))
+  (interactive "sShell command: ")
+  (projectile-with-default-dir (projectile-acquire-root)
+    (shell-command command output-buffer error-buffer)))
 
 ;;;###autoload
-(defun projectile-run-async-shell-command-in-root ()
+(defun projectile-run-async-shell-command-in-root (command &optional output-buffer error-buffer)
   "Invoke `async-shell-command' in the project's root."
+  (interactive "sAsync shell command: ")
+  (projectile-with-default-dir (projectile-acquire-root)
+    (async-shell-command command output-buffer error-buffer)))
+
+;;;###autoload
+(defun projectile-run-gdb ()
+  "Invoke `gdb' in the project's root."
   (interactive)
-  (projectile-with-default-dir (projectile-ensure-project (projectile-project-root))
-    (call-interactively #'async-shell-command)))
+  (projectile-with-default-dir (projectile-acquire-root)
+    (call-interactively 'gdb)))
 
 ;;;###autoload
-(defun projectile-run-shell (arg)
+(defun projectile-run-shell (&optional arg)
   "Invoke `shell' in the project's root.
 
 Switch to the project specific shell buffer if it already exists.
 
 Use a prefix argument ARG to indicate creation of a new process instead."
   (interactive "P")
-  (projectile-with-default-dir (projectile-ensure-project (projectile-project-root))
-    (shell (projectile-generate-process-name "shell" arg))))
+  (let ((project (projectile-acquire-root)))
+    (projectile-with-default-dir project
+      (shell (projectile-generate-process-name "shell" arg project)))))
 
 ;;;###autoload
-(defun projectile-run-eshell (arg)
+(defun projectile-run-eshell (&optional arg)
   "Invoke `eshell' in the project's root.
 
 Switch to the project specific eshell buffer if it already exists.
 
 Use a prefix argument ARG to indicate creation of a new process instead."
   (interactive "P")
-  (projectile-with-default-dir (projectile-ensure-project (projectile-project-root))
-    (let ((eshell-buffer-name (projectile-generate-process-name "eshell" arg)))
-      (eshell))))
+  (let ((project (projectile-acquire-root)))
+    (projectile-with-default-dir project
+      (let ((eshell-buffer-name (projectile-generate-process-name "eshell" arg project)))
+        (eshell)))))
 
 ;;;###autoload
-(defun projectile-run-ielm (arg)
+(defun projectile-run-ielm (&optional arg)
   "Invoke `ielm' in the project's root.
 
 Switch to the project specific ielm buffer if it already exists.
 
 Use a prefix argument ARG to indicate creation of a new process instead."
   (interactive "P")
-  (let* ((project (projectile-ensure-project (projectile-project-root)))
-         (ielm-buffer-name (projectile-generate-process-name "ielm" arg)))
+  (let* ((project (projectile-acquire-root))
+         (ielm-buffer-name (projectile-generate-process-name "ielm" arg project)))
     (if (get-buffer ielm-buffer-name)
         (switch-to-buffer ielm-buffer-name)
       (projectile-with-default-dir project
@@ -3413,19 +3996,19 @@ Use a prefix argument ARG to indicate cr
       (rename-buffer ielm-buffer-name))))
 
 ;;;###autoload
-(defun projectile-run-term (arg)
+(defun projectile-run-term (&optional arg)
   "Invoke `term' in the project's root.
 
 Switch to the project specific term buffer if it already exists.
 
 Use a prefix argument ARG to indicate creation of a new process instead."
   (interactive "P")
-  (let ((project (projectile-ensure-project (projectile-project-root)))
-        (buffer-name (projectile-generate-process-name "term" arg))
-        (default-program (or explicit-shell-file-name
-                             (getenv "ESHELL")
-                             (getenv "SHELL")
-                             "/bin/sh")))
+  (let* ((project (projectile-acquire-root))
+         (buffer-name (projectile-generate-process-name "term" arg project))
+         (default-program (or explicit-shell-file-name
+                              (getenv "ESHELL")
+                              (getenv "SHELL")
+                              "/bin/sh")))
     (unless (get-buffer buffer-name)
       (require 'term)
       (let ((program (read-from-minibuffer "Run program: " default-program)))
@@ -3443,19 +4026,18 @@ Switch to the project specific term buff
 
 Use a prefix argument ARG to indicate creation of a new process instead."
   (interactive "P")
-  (let* ((project (projectile-ensure-project (projectile-project-root)))
-         (buffer (projectile-generate-process-name "vterm" arg)))
+  (let* ((project (projectile-acquire-root))
+         (buffer (projectile-generate-process-name "vterm" arg project)))
     (unless (buffer-live-p (get-buffer buffer))
       (unless (require 'vterm nil 'noerror)
         (error "Package 'vterm' is not available"))
-      (vterm buffer)
-      (vterm-send-string (concat "cd " project))
-      (vterm-send-return))
+      (projectile-with-default-dir project
+        (vterm buffer)))
     (switch-to-buffer buffer)))
 
 (defun projectile-files-in-project-directory (directory)
   "Return a list of files in DIRECTORY."
-  (let* ((project (projectile-ensure-project (projectile-project-root)))
+  (let* ((project (projectile-acquire-root))
          (dir (file-relative-name (expand-file-name directory)
                                   project)))
     (cl-remove-if-not
@@ -3479,34 +4061,45 @@ Returns a list of expanded filenames."
              "\n+"
              t))))
 
+(defvar projectile-files-with-string-commands
+  '((rg . "rg -lF --no-heading --color never -- ")
+    (ag . "ag --literal --nocolor --noheading -l -- ")
+    (ack . "ack --literal --nocolor -l -- ")
+    (git . "git grep -HlI ")
+    ;; -r: recursive
+    ;; -H: show filename for each match
+    ;; -l: show only file names with matches
+    ;; -I: no binary files
+    (grep . "grep -rHlI %s .")))
+
 (defun projectile-files-with-string (string directory)
   "Return a list of all files containing STRING in DIRECTORY.
 
-Tries to use ag, ack, git-grep, and grep in that order.  If those
+Tries to use rg, ag, ack, git-grep, and grep in that order.  If those
 are impossible (for instance on Windows), returns a list of all
 files in the project."
   (if (projectile-unixy-system-p)
       (let* ((search-term (shell-quote-argument string))
-             (cmd (cond ((executable-find "ag")
-                         (concat "ag --literal --nocolor --noheading -l -- "
+             (cmd (cond ((executable-find "rg")
+                         (concat (cdr (assoc 'rg projectile-files-with-string-commands))
+                                 search-term))
+                        ((executable-find "ag")
+                         (concat (cdr (assoc 'ag projectile-files-with-string-commands))
                                  search-term))
                         ((executable-find "ack")
-                         (concat "ack --literal --noheading --nocolor -l -- "
+                         (concat (cdr (assoc 'ack projectile-files-with-string-commands))
                                  search-term))
                         ((and (executable-find "git")
                               (eq (projectile-project-vcs) 'git))
-                         (concat "git grep -HlI " search-term))
+                         (concat (cdr (assoc 'git projectile-files-with-string-commands)) search-term))
                         (t
-                         ;; -r: recursive
-                         ;; -H: show filename for each match
-                         ;; -l: show only file names with matches
-                         ;; -I: no binary files
-                         (format "grep -rHlI %s ." search-term)))))
+                         (format (cdr (assoc 'grep projectile-files-with-string-commands)) search-term)))))
         (projectile-files-from-cmd cmd directory))
     ;; we have to reject directories as a workaround to work with git submodules
     (cl-remove-if
      #'file-directory-p
-     (mapcar #'projectile-expand-root (projectile-dir-files directory)))))
+     (mapcar #'(lambda (file) (expand-file-name file directory))
+             (projectile-dir-files directory)))))
 
 ;;;###autoload
 (defun projectile-replace (&optional arg)
@@ -3518,7 +4111,7 @@ to run the replacement."
   (let* ((directory (if arg
                         (file-name-as-directory
                          (read-directory-name "Replace in directory: "))
-                      (projectile-ensure-project (projectile-project-root))))
+                      (projectile-acquire-root)))
          (old-text (read-string
                     (projectile-prepend-project-name "Replace: ")
                     (projectile-symbol-or-selection-at-point)))
@@ -3533,16 +4126,19 @@ to run the replacement."
       ;; Emacs 25 and 26
       ;;
       ;; Adapted from `tags-query-replace' for literal strings (not regexp)
-      (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))))
-            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)))))
+      (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))))))
 
 ;;;###autoload
 (defun projectile-replace-regexp (&optional arg)
@@ -3554,7 +4150,7 @@ to run the replacement."
   (let* ((directory (if arg
                         (file-name-as-directory
                          (read-directory-name "Replace regexp in directory: "))
-                      (projectile-ensure-project (projectile-project-root))))
+                      (projectile-acquire-root)))
          (old-text (read-string
                     (projectile-prepend-project-name "Replace regexp: ")
                     (projectile-symbol-or-selection-at-point)))
@@ -3569,8 +4165,10 @@ to run the replacement."
           ;; don't support Emacs regular expressions.
           (cl-remove-if
            #'file-directory-p
-           (mapcar #'projectile-expand-root (projectile-dir-files directory)))))
-    (tags-query-replace old-text new-text nil (cons 'list files))))
+           (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)))))
 
 ;;;###autoload
 (defun projectile-kill-buffers ()
@@ -3579,7 +4177,7 @@ to run the replacement."
 The buffer are killed according to the value of
 `projectile-kill-buffers-filter'."
   (interactive)
-  (let* ((project (projectile-ensure-project (projectile-project-root)))
+  (let* ((project (projectile-acquire-root))
          (project-name (projectile-project-name project))
          (buffers (projectile-project-buffers project)))
     (when (yes-or-no-p
@@ -3602,7 +4200,7 @@ The buffer are killed according to the v
 (defun projectile-save-project-buffers ()
   "Save all project buffers."
   (interactive)
-  (let* ((project (projectile-ensure-project (projectile-project-root)))
+  (let* ((project (projectile-acquire-root))
          (project-name (projectile-project-name project))
          (modified-buffers (cl-remove-if-not (lambda (buf)
                                                (and (buffer-file-name buf)
@@ -3619,19 +4217,19 @@ The buffer are killed according to the v
 (defun projectile-dired ()
   "Open `dired' at the root of the project."
   (interactive)
-  (dired (projectile-ensure-project (projectile-project-root))))
+  (dired (projectile-acquire-root)))
 
 ;;;###autoload
 (defun projectile-dired-other-window ()
   "Open `dired'  at the root of the project in another window."
   (interactive)
-  (dired-other-window (projectile-ensure-project (projectile-project-root))))
+  (dired-other-window (projectile-acquire-root)))
 
 ;;;###autoload
 (defun projectile-dired-other-frame ()
   "Open `dired' at the root of the project in another frame."
   (interactive)
-  (dired-other-frame (projectile-ensure-project (projectile-project-root))))
+  (dired-other-frame (projectile-acquire-root)))
 
 ;;;###autoload
 (defun projectile-vc (&optional project-root)
@@ -3649,7 +4247,8 @@ directory to open."
                      (projectile-completing-read
                       "Open project VC in: "
                       projectile-known-projects))))
-  (or project-root (setq project-root (projectile-project-root)))
+  (unless project-root
+    (setq project-root (projectile-acquire-root)))
   (let ((vcs (projectile-project-vcs project-root)))
     (cl-case vcs
       (git
@@ -3679,7 +4278,7 @@ directory to open."
 (defun projectile-recentf-files ()
   "Return a list of recently visited files in a project."
   (and (boundp 'recentf-list)
-       (let ((project-root (projectile-ensure-project (projectile-project-root))))
+       (let ((project-root (projectile-acquire-root)))
          (mapcar
           (lambda (f) (file-relative-name f project-root))
           (cl-remove-if-not
@@ -3698,6 +4297,14 @@ directory to open."
   (make-hash-table :test 'equal)
   "A mapping between projects and the last compilation command used on them.")
 
+(defvar projectile-install-cmd-map
+  (make-hash-table :test 'equal)
+  "A mapping between projects and the last install command used on them.")
+
+(defvar projectile-package-cmd-map
+  (make-hash-table :test 'equal)
+  "A mapping between projects and the last package command used on them.")
+
 (defvar projectile-test-cmd-map
   (make-hash-table :test 'equal)
   "A mapping between projects and the last test command used on them.")
@@ -3726,6 +4333,16 @@ Should be set via .dir-locals.el.")
 It takes precedence over the default command for the project type when set.
 Should be set via .dir-locals.el.")
 
+(defvar projectile-project-install-cmd nil
+  "The command to use with `projectile-install-project'.
+It takes precedence over the default command for the project type when set.
+Should be set via .dir-locals.el.")
+
+(defvar projectile-project-package-cmd nil
+  "The command to use with `projectile-package-project'.
+It takes precedence over the default command for the project type when set.
+Should be set via .dir-locals.el.")
+
 (defvar projectile-project-run-cmd nil
   "The command to use with `projectile-run-project'.
 It takes precedence over the default command for the project type when set.
@@ -3763,6 +4380,14 @@ be string to be executed as command."
   "Retrieve default test command for PROJECT-TYPE."
   (projectile-default-generic-command project-type 'test-command))
 
+(defun projectile-default-install-command (project-type)
+  "Retrieve default install command for PROJECT-TYPE."
+  (projectile-default-generic-command project-type 'install-command))
+
+(defun projectile-default-package-command (project-type)
+  "Retrieve default package command for PROJECT-TYPE."
+  (projectile-default-generic-command project-type 'package-command))
+
 (defun projectile-default-run-command (project-type)
   "Retrieve default run command for PROJECT-TYPE."
   (projectile-default-generic-command project-type 'run-command))
@@ -3784,7 +4409,21 @@ project of that type"
       projectile-project-configure-cmd
       (let ((cmd-format-string (projectile-default-configure-command (projectile-project-type))))
         (when cmd-format-string
-          (format cmd-format-string (projectile-project-root))))))
+          (format cmd-format-string (projectile-project-root) compile-dir)))))
+
+(defun projectile-compilation-buffer-name (compilation-mode)
+  "Meant to be used for `compilation-buffer-name-function`.
+Argument COMPILATION-MODE is the name of the major mode used for the compilation buffer."
+  (concat "*" (downcase compilation-mode) "*"
+          (if (projectile-project-p) (concat "<" (projectile-project-name) ">") "")))
+
+(defun projectile-current-project-buffer-p ()
+  "Meant to be used for `compilation-save-buffers-predicate`.
+This indicates whether the current buffer is in the same project as the current
+window (including returning true if neither is in a project)."
+  (let ((root (with-current-buffer (window-buffer) (projectile-project-root))))
+    (or (not root)
+        (projectile-project-buffer-p (current-buffer) root))))
 
 (defun projectile-compilation-command (compile-dir)
   "Retrieve the compilation command for COMPILE-DIR.
@@ -3820,6 +4459,40 @@ project of that type"
       projectile-project-test-cmd
       (projectile-default-test-command (projectile-project-type))))
 
+(defun projectile-install-command (compile-dir)
+  "Retrieve the install command for COMPILE-DIR.
+
+The command is determined like this:
+
+- first we check `projectile-install-cmd-map' for the last
+install command that was invoked on the project
+
+- then we check for `projectile-project-install-cmd' supplied
+via .dir-locals.el
+
+- finally we check for the default install command for a
+project of that type"
+  (or (gethash compile-dir projectile-install-cmd-map)
+      projectile-project-install-cmd
+      (projectile-default-install-command (projectile-project-type))))
+
+(defun projectile-package-command (compile-dir)
+  "Retrieve the pacakge command for COMPILE-DIR.
+
+The command is determined like this:
+
+- first we check `projectile-packgage-cmd-map' for the last
+install command that was invoked on the project
+
+- then we check for `projectile-project-package-cmd' supplied
+via .dir-locals.el
+
+- finally we check for the default package command for a
+project of that type"
+  (or (gethash compile-dir projectile-package-cmd-map)
+      projectile-project-package-cmd
+      (projectile-default-package-command (projectile-project-type))))
+
 (defun projectile-run-command (compile-dir)
   "Retrieve the run command for COMPILE-DIR.
 
@@ -3839,10 +4512,13 @@ project of that type"
 
 (defun projectile-read-command (prompt command)
   "Adapted from `compilation-read-command'."
-  (read-shell-command prompt command
-                      (if (equal (car compile-history) command)
-                          '(compile-history . 1)
-                        'compile-history)))
+  (let ((compile-history
+         ;; fetch the command history for the current project
+         (ring-elements (projectile--get-command-history (projectile-acquire-root)))))
+    (read-shell-command prompt command
+                        (if (equal (car compile-history) command)
+                            '(compile-history . 1)
+                          'compile-history))))
 
 (defun projectile-compilation-dir ()
   "Retrieve the compilation directory for this project."
@@ -3862,11 +4538,11 @@ project of that type"
       (projectile-read-command prompt default-cmd)
     default-cmd))
 
-(defun projectile-run-compilation (cmd)
+(defun projectile-run-compilation (cmd &optional use-comint-mode)
   "Run external or Elisp compilation command CMD."
   (if (functionp cmd)
       (funcall cmd)
-    (compile cmd)))
+    (compile cmd use-comint-mode)))
 
 (defvar projectile-project-command-history (make-hash-table :test 'equal)
   "The history of last executed project commands, per project.
@@ -3880,7 +4556,7 @@ Projects are indexed by their project-ro
                projectile-project-command-history)))
 
 (cl-defun projectile--run-project-cmd
-    (command command-map &key show-prompt prompt-prefix save-buffers)
+    (command command-map &key show-prompt prompt-prefix save-buffers use-comint-mode)
   "Run a project COMMAND, typically a test- or compile command.
 
 Cache the COMMAND for later use inside the hash-table COMMAND-MAP.
@@ -3908,9 +4584,45 @@ The command actually run is returned."
                                                         project-root))))
     (unless (file-directory-p default-directory)
       (mkdir default-directory))
-    (projectile-run-compilation command)
+    (projectile-run-compilation command use-comint-mode)
     command))
 
+(defcustom projectile-configure-use-comint-mode nil
+  "Make the output buffer of projectile-configure-project interactive."
+  :group 'projectile
+  :type 'boolean
+  :package-version '(projectile . "2.5.0"))
+
+(defcustom projectile-compile-use-comint-mode nil
+  "Make the output buffer of projectile-compile-project interactive."
+  :group 'projectile
+  :type 'boolean
+  :package-version '(projectile . "2.5.0"))
+
+(defcustom projectile-test-use-comint-mode nil
+  "Make the output buffer of projectile-test-project interactive."
+  :group 'projectile
+  :type 'boolean
+  :package-version '(projectile . "2.5.0"))
+
+(defcustom projectile-install-use-comint-mode nil
+  "Make the output buffer of projectile-install-project interactive."
+  :group 'projectile
+  :type 'boolean
+  :package-version '(projectile . "2.5.0"))
+
+(defcustom projectile-package-use-comint-mode nil
+  "Make the output buffer of projectile-package-project interactive."
+  :group 'projectile
+  :type 'boolean
+  :package-version '(projectile . "2.5.0"))
+
+(defcustom projectile-run-use-comint-mode nil
+  "Make the output buffer of projectile-run-project interactive."
+  :group 'projectile
+  :type 'boolean
+  :package-version '(projectile . "2.5.0"))
+
 ;;;###autoload
 (defun projectile-configure-project (arg)
   "Run project configure command.
@@ -3923,7 +4635,8 @@ with a prefix ARG."
     (projectile--run-project-cmd command projectile-configure-cmd-map
                                  :show-prompt arg
                                  :prompt-prefix "Configure command: "
-                                 :save-buffers t)))
+                                 :save-buffers t
+                                 :use-comint-mode projectile-configure-use-comint-mode)))
 
 ;;;###autoload
 (defun projectile-compile-project (arg)
@@ -3937,7 +4650,8 @@ with a prefix ARG."
     (projectile--run-project-cmd command projectile-compilation-cmd-map
                                  :show-prompt arg
                                  :prompt-prefix "Compile command: "
-                                 :save-buffers t)))
+                                 :save-buffers t
+                                 :use-comint-mode projectile-compile-use-comint-mode)))
 
 ;;;###autoload
 (defun projectile-test-project (arg)
@@ -3951,7 +4665,38 @@ with a prefix ARG."
     (projectile--run-project-cmd command projectile-test-cmd-map
                                  :show-prompt arg
                                  :prompt-prefix "Test command: "
-                                 :save-buffers t)))
+                                 :save-buffers t
+                                 :use-comint-mode projectile-test-use-comint-mode)))
+
+;;;###autoload
+(defun projectile-install-project (arg)
+  "Run project install command.
+
+Normally you'll be prompted for a compilation command, unless
+variable `compilation-read-command'.  You can force the prompt
+with a prefix ARG."
+  (interactive "P")
+  (let ((command (projectile-install-command (projectile-compilation-dir))))
+    (projectile--run-project-cmd command projectile-install-cmd-map
+                                 :show-prompt arg
+                                 :prompt-prefix "Install command: "
+                                 :save-buffers t
+                                 :use-comint-mode projectile-install-use-comint-mode)))
+
+;;;###autoload
+(defun projectile-package-project (arg)
+  "Run project package command.
+
+Normally you'll be prompted for a compilation command, unless
+variable `compilation-read-command'.  You can force the prompt
+with a prefix ARG."
+  (interactive "P")
+  (let ((command (projectile-package-command (projectile-compilation-dir))))
+    (projectile--run-project-cmd command projectile-package-cmd-map
+                                 :show-prompt arg
+                                 :prompt-prefix "Package command: "
+                                 :save-buffers t
+                                 :use-comint-mode projectile-package-use-comint-mode)))
 
 ;;;###autoload
 (defun projectile-run-project (arg)
@@ -3964,20 +4709,21 @@ with a prefix ARG."
   (let ((command (projectile-run-command (projectile-compilation-dir))))
     (projectile--run-project-cmd command projectile-run-cmd-map
                                  :show-prompt arg
-                                 :prompt-prefix "Run command: ")))
+                                 :prompt-prefix "Run command: "
+                                 :use-comint-mode projectile-run-use-comint-mode)))
 
 ;;;###autoload
 (defun projectile-repeat-last-command (show-prompt)
   "Run last projectile external command.
 
 External commands are: `projectile-configure-project',
-`projectile-compile-project', `projectile-test-project' and
-`projectile-run-project'.
+`projectile-compile-project', `projectile-test-project',
+`projectile-install-project', `projectile-package-project',
+and `projectile-run-project'.
 
 If the prefix argument SHOW_PROMPT is non nil, the command can be edited."
   (interactive "P")
-  (let* ((project-root
-          (projectile-ensure-project (projectile-project-root)))
+  (let* ((project-root (projectile-acquire-root))
          (command-history (projectile--get-command-history project-root))
          (command (car-safe (ring-elements command-history)))
          (compilation-read-command show-prompt)
@@ -3993,24 +4739,18 @@ If the prefix argument SHOW_PROMPT is no
       (ring-insert command-history executed-command))))
 
 (defun compilation-find-file-projectile-find-compilation-buffer (orig-fun marker filename directory &rest formats)
-  "Try to find a buffer for FILENAME, if we cannot find it,
-fallback to the original function."
-  (when (and (not (file-exists-p (expand-file-name filename)))
-             (projectile-project-p))
-    (let* ((root (projectile-project-root))
-           (dirs (cons "" (projectile-current-project-dirs)))
-           (new-filename (car (cl-remove-if-not
-                               #'file-exists-p
-                               (mapcar
-                                (lambda (f)
-                                  (expand-file-name
-                                   filename
-                                   (expand-file-name f root)))
-                                dirs)))))
-      (when new-filename
-        (setq filename new-filename))))
-
-  (apply orig-fun `(,marker ,filename ,directory ,@formats)))
+  "Advice around compilation-find-file. We enhance its functionality by
+appending the current project's directories to its search path. This way
+when filenames in compilation buffers can't be found by compilation's
+normal logic they are searched for in project directories."
+  (let* ((root (projectile-project-root))
+         (compilation-search-path
+          (if (projectile-project-p)
+              (append compilation-search-path (list root)
+                      (mapcar (lambda (f) (expand-file-name f root))
+                              (projectile-current-project-dirs)))
+            compilation-search-path)))
+    (apply orig-fun `(,marker ,filename ,directory ,@formats))))
 
 (defun projectile-open-projects ()
   "Return a list of all open projects.
@@ -4041,17 +4781,17 @@ An open project is a project with any op
 (defun projectile-relevant-known-projects ()
   "Return a list of known projects."
   (pcase projectile-current-project-on-switch
-   ('remove (projectile--remove-current-project projectile-known-projects))
-   ('move-to-end (projectile--move-current-project-to-end projectile-known-projects))
-   ('keep projectile-known-projects)))
+    ('remove (projectile--remove-current-project projectile-known-projects))
+    ('move-to-end (projectile--move-current-project-to-end projectile-known-projects))
+    ('keep projectile-known-projects)))
 
 (defun projectile-relevant-open-projects ()
   "Return a list of open projects."
   (let ((open-projects (projectile-open-projects)))
     (pcase projectile-current-project-on-switch
-     ('remove (projectile--remove-current-project open-projects))
-     ('move-to-end (projectile--move-current-project-to-end open-projects))
-     ('keep open-projects))))
+      ('remove (projectile--remove-current-project open-projects))
+      ('move-to-end (projectile--move-current-project-to-end open-projects))
+      ('keep open-projects))))
 
 ;;;###autoload
 (defun projectile-switch-project (&optional arg)
@@ -4088,27 +4828,36 @@ With a prefix ARG invokes `projectile-co
 Invokes the command referenced by `projectile-switch-project-action' on switch.
 With a prefix ARG invokes `projectile-commander' instead of
 `projectile-switch-project-action.'"
-  (unless (projectile-project-p project-to-switch)
+  ;; let's make sure that the target directory exists and is actually a project
+  ;; we ignore remote folders, as the check breaks for TRAMP unless already connected
+  (unless (or (file-remote-p project-to-switch) (projectile-project-p project-to-switch))
     (projectile-remove-known-project project-to-switch)
     (error "Directory %s is not a project" project-to-switch))
   (let ((switch-project-action (if arg
                                    'projectile-commander
                                  projectile-switch-project-action)))
     (run-hooks 'projectile-before-switch-project-hook)
-    (let ((default-directory project-to-switch))
-      ;; use a temporary buffer to load PROJECT-TO-SWITCH's dir-locals before calling SWITCH-PROJECT-ACTION
-      (with-temp-buffer
-        (hack-dir-local-variables-non-file-buffer))
-      ;; Normally the project name is determined from the current
-      ;; buffer. However, when we're switching projects, we want to
-      ;; show the name of the project being switched to, rather than
-      ;; the current project, in the minibuffer. This is a simple hack
-      ;; to tell the `projectile-project-name' function to ignore the
-      ;; current buffer and the caching mechanism, and just return the
-      ;; value of the `projectile-project-name' variable.
-      (let ((projectile-project-name (funcall projectile-project-name-function
-                                              project-to-switch)))
-        (funcall switch-project-action)))
+    (let* ((default-directory project-to-switch)
+           (switched-buffer
+            ;; use a temporary buffer to load PROJECT-TO-SWITCH's dir-locals
+            ;; before calling SWITCH-PROJECT-ACTION
+            (with-temp-buffer
+              (hack-dir-local-variables-non-file-buffer)
+              ;; Normally the project name is determined from the current
+              ;; buffer. However, when we're switching projects, we want to
+              ;; show the name of the project being switched to, rather than
+              ;; the current project, in the minibuffer. This is a simple hack
+              ;; to tell the `projectile-project-name' function to ignore the
+              ;; current buffer and the caching mechanism, and just return the
+              ;; value of the `projectile-project-name' variable.
+              (let ((projectile-project-name (funcall projectile-project-name-function
+                                                      project-to-switch)))
+                (funcall switch-project-action)
+                (current-buffer)))))
+      ;; If switch-project-action switched buffers then with-temp-buffer will
+      ;; have lost that change, so switch back to the correct buffer.
+      (when (buffer-live-p switched-buffer)
+        (switch-to-buffer switched-buffer)))
     (run-hooks 'projectile-after-switch-project-hook)))
 
 ;;;###autoload
@@ -4182,6 +4931,13 @@ See `projectile--cleanup-known-projects'
   (projectile-save-known-projects))
 
 ;;;###autoload
+(defun projectile-reset-known-projects ()
+  "Clear known projects and rediscover."
+  (interactive)
+  (projectile-clear-known-projects)
+  (projectile-discover-projects-in-search-path))
+
+;;;###autoload
 (defun projectile-remove-known-project (&optional project)
   "Remove PROJECT from the list of known projects."
   (interactive (list (projectile-completing-read
@@ -4200,7 +4956,7 @@ See `projectile--cleanup-known-projects'
 (defun projectile-remove-current-project-from-known-projects ()
   "Remove the current project from the list of known projects."
   (interactive)
-  (projectile-remove-known-project (abbreviate-file-name (projectile-project-root))))
+  (projectile-remove-known-project (abbreviate-file-name (projectile-acquire-root))))
 
 (defun projectile-ignored-projects ()
   "A list of projects that should not be save in `projectile-known-projects'."
@@ -4266,8 +5022,10 @@ overwriting each other's changes."
   (:reader (read-directory-name "Project root: " (projectile-project-root))
            :description nil)
   (with-current-buffer buf
-    (equal (file-name-as-directory (expand-file-name qualifier))
-           (projectile-project-root))))
+    (let ((directory (file-name-as-directory (expand-file-name qualifier))))
+      (and (projectile-project-buffer-p buf directory)
+           (equal directory
+                  (projectile-project-root))))))
 
 (defun projectile-ibuffer-by-project (project-root)
   "Open an IBuffer window showing all buffers in PROJECT-ROOT."
@@ -4285,8 +5043,7 @@ Let user choose another project when PRO
                           (projectile-completing-read
                            "Project name: "
                            (projectile-relevant-known-projects))
-                        (projectile-project-root))))
-
+                        (projectile-acquire-root))))
     (projectile-ibuffer-by-project project-root)))
 
 
@@ -4413,7 +5170,7 @@ is chosen."
 (defun projectile-check-vcs-status (&optional project-path)
   "Check the status of the current project.
 If PROJECT-PATH is a project, check this one instead."
-  (let ((project-path (or project-path (projectile-project-root)))
+  (let ((project-path (or project-path (projectile-acquire-root)))
         (project-status nil))
     (save-excursion
       (vc-dir project-path)
@@ -4506,7 +5263,7 @@ If the current buffer does not belong to
   (completing-read "Variable: "
                    obarray
                    (lambda (v)
-                      (and (boundp v) (not (keywordp v))))
+                     (and (boundp v) (not (keywordp v))))
                    t))
 
 (define-skeleton projectile-skel-variable-cons
@@ -4530,7 +5287,7 @@ If the current buffer does not belong to
 (defun projectile-edit-dir-locals ()
   "Edit or create a .dir-locals.el file of the project."
   (interactive)
-  (let ((file (expand-file-name ".dir-locals.el" (projectile-project-root))))
+  (let ((file (expand-file-name ".dir-locals.el" (projectile-acquire-root))))
     (find-file file)
     (when (not (file-exists-p file))
       (unwind-protect
@@ -4539,7 +5296,7 @@ If the current buffer does not belong to
 
 
 ;;; Projectile Minor mode
-(define-obsolete-variable-alias 'projectile-mode-line-lighter 'projectile-mode-line-prefix)
+(define-obsolete-variable-alias 'projectile-mode-line-lighter 'projectile-mode-line-prefix "0.12.0")
 (defcustom projectile-mode-line-prefix
   " Projectile"
   "Mode line lighter prefix for Projectile.
@@ -4590,8 +5347,6 @@ thing shown in the mode line otherwise."
     (define-key map (kbd "&") #'projectile-run-async-shell-command-in-root)
     (define-key map (kbd "a") #'projectile-find-other-file)
     (define-key map (kbd "b") #'projectile-switch-to-buffer)
-    (define-key map (kbd "C") #'projectile-configure-project)
-    (define-key map (kbd "c") #'projectile-compile-project)
     (define-key map (kbd "d") #'projectile-find-dir)
     (define-key map (kbd "D") #'projectile-dired)
     (define-key map (kbd "e") #'projectile-recentf)
@@ -4608,7 +5363,6 @@ thing shown in the mode line otherwise."
     (define-key map (kbd "o") #'projectile-multi-occur)
     (define-key map (kbd "p") #'projectile-switch-project)
     (define-key map (kbd "q") #'projectile-switch-open-project)
-    (define-key map (kbd "P") #'projectile-test-project)
     (define-key map (kbd "r") #'projectile-replace)
     (define-key map (kbd "R") #'projectile-regenerate-tags)
     (define-key map (kbd "s g") #'projectile-grep)
@@ -4617,13 +5371,22 @@ thing shown in the mode line otherwise."
     (define-key map (kbd "S") #'projectile-save-project-buffers)
     (define-key map (kbd "t") #'projectile-toggle-between-implementation-and-test)
     (define-key map (kbd "T") #'projectile-find-test-file)
-    (define-key map (kbd "u") #'projectile-run-project)
     (define-key map (kbd "v") #'projectile-vc)
     (define-key map (kbd "V") #'projectile-browse-dirty-projects)
+    ;; project lifecycle external commands
+    ;; TODO: Bundle those under some prefix key
+    (define-key map (kbd "C") #'projectile-configure-project)
+    (define-key map (kbd "c") #'projectile-compile-project)
+    (define-key map (kbd "K") #'projectile-package-project)
+    (define-key map (kbd "L") #'projectile-install-project)
+    (define-key map (kbd "P") #'projectile-test-project)
+    (define-key map (kbd "u") #'projectile-run-project)
+    ;; utilities
     (define-key map (kbd "x e") #'projectile-run-eshell)
     (define-key map (kbd "x i") #'projectile-run-ielm)
     (define-key map (kbd "x t") #'projectile-run-term)
     (define-key map (kbd "x s") #'projectile-run-shell)
+    (define-key map (kbd "x g") #'projectile-run-gdb)
     (define-key map (kbd "x v") #'projectile-run-vterm)
     (define-key map (kbd "z") #'projectile-cache-current-file)
     (define-key map (kbd "<left>") #'projectile-previous-project-buffer)
@@ -4660,6 +5423,8 @@ thing shown in the mode line otherwise."
         ["Switch to project" projectile-switch-project]
         ["Switch to open project" projectile-switch-open-project]
         ["Discover projects in directory" projectile-discover-projects-in-directory]
+        ["Clear known projects" projectile-clear-known-projects]
+        ["Reset known projects" projectile-reset-known-projects]
         ["Browse dirty projects" projectile-browse-dirty-projects]
         ["Open project in dired" projectile-dired]
         "--"
@@ -4668,6 +5433,8 @@ thing shown in the mode line otherwise."
         ["Replace in project" projectile-replace]
         ["Multi-occur in project" projectile-multi-occur]
         "--"
+        ["Run GDB" projectile-run-gdb]
+        "--"
         ["Run shell" projectile-run-shell]
         ["Run eshell" projectile-run-eshell]
         ["Run ielm" projectile-run-ielm]
@@ -4680,6 +5447,8 @@ thing shown in the mode line otherwise."
         ["Configure project" projectile-configure-project]
         ["Compile project" projectile-compile-project]
         ["Test project" projectile-test-project]
+        ["Install project" projectile-install-project]
+        ["Package project" projectile-package-project]
         ["Run project" projectile-run-project]
         ["Repeat last external command" projectile-repeat-last-command]
         "--"
@@ -4694,6 +5463,7 @@ thing shown in the mode line otherwise."
 The function does pretty much nothing when triggered on remote files
 as all the operations it normally performs are extremely slow over
 tramp."
+  (projectile-maybe-limit-project-file-buffers)
   (unless (file-remote-p default-directory)
     (when projectile-dynamic-mode-line
       (projectile-update-mode-line))
@@ -4702,6 +5472,16 @@ tramp."
     (projectile-track-known-projects-find-file-hook)
     (projectile-visit-project-tags-table)))
 
+(defun projectile-maybe-limit-project-file-buffers ()
+  "Limit the opened file buffers for a project.
+
+The function simply kills the last buffer, as it's normally called
+when opening new files."
+  (when projectile-max-file-buffer-count
+    (let ((project-buffers (projectile-project-buffer-files)))
+      (when (> (length project-buffers) projectile-max-file-buffer-count)
+        (kill-buffer (car (last project-buffers)))))))
+
 ;;;###autoload
 (define-minor-mode projectile-mode
   "Minor mode to assist project management and navigation.
@@ -4736,7 +5516,8 @@ Otherwise behave as if called interactiv
     (projectile-load-known-projects)
     ;; update the list of known projects
     (projectile--cleanup-known-projects)
-    (projectile-discover-projects-in-search-path)
+    (when projectile-auto-discover
+      (projectile-discover-projects-in-search-path))
     (add-hook 'find-file-hook 'projectile-find-file-hook-function)
     (add-hook 'projectile-find-dir-hook #'projectile-track-known-projects-find-file-hook t)
     (add-hook 'dired-before-readin-hook #'projectile-track-known-projects-find-file-hook t t)
@@ -4748,6 +5529,15 @@ Otherwise behave as if called interactiv
     (advice-remove 'compilation-find-file #'compilation-find-file-projectile-find-compilation-buffer)
     (advice-remove 'delete-file #'delete-file-projectile-remove-from-cache))))
 
+;;; savehist-mode - When `savehist-mode' is t, projectile-project-command-history will be saved.
+;; See https://github.com/bbatsov/projectile/issues/1637 for more details
+(if (bound-and-true-p savehist-loaded)
+    (add-to-list 'savehist-additional-variables 'projectile-project-command-history)
+  (defvar savehist-additional-variables nil)
+  (add-hook 'savehist-mode-hook
+            (lambda()
+              (add-to-list 'savehist-additional-variables 'projectile-project-command-history))))
+
 ;;;###autoload
 (define-obsolete-function-alias 'projectile-global-mode 'projectile-mode "1.0")
 
diff -pruN 2.1.0-1.1/README.md 2.5.0-1/README.md
--- 2.1.0-1.1/README.md	2020-02-04 18:30:35.000000000 +0000
+++ 2.5.0-1/README.md	2021-08-10 10:11:43.000000000 +0000
@@ -1,8 +1,9 @@
+# Projectile
+
 [![License GPL 3][badge-license]](http://www.gnu.org/licenses/gpl-3.0.txt)
 [![MELPA](http://melpa.org/packages/projectile-badge.svg)](http://melpa.org/#/projectile)
 [![MELPA Stable](http://stable.melpa.org/packages/projectile-badge.svg)](http://stable.melpa.org/#/projectile)
-[![Build Status](https://travis-ci.org/bbatsov/projectile.png?branch=master)](https://travis-ci.org/bbatsov/projectile)
-[![Patreon](https://img.shields.io/badge/patreon-donate-orange.svg)](https://www.patreon.com/bbatsov)
+[![Build Status](https://github.com/bbatsov/projectile/workflows/CI/badge.svg)](https://github.com/bbatsov/projectile/actions?query=workflow%3ACI)
 
 ## Synopsis
 
@@ -17,48 +18,57 @@ Projectile tries to be practical - porta
 external tools could speed up some task substantially and the tools
 are available, Projectile will leverage them.
 
-This library provides easy project management and navigation. The
-concept of a project is pretty basic - just a folder containing
-special file. Currently `git`, `mercurial`, `darcs` and `bazaar` repos
-are considered projects by default. So are `lein`, `maven`, `sbt`,
-`scons`, `rebar` and `bundler` projects. If you want to mark a folder
-manually as a project just create an empty `.projectile` file in
-it. Some of Projectile's features:
+This library provides easy project management and navigation. The concept of a
+project is pretty basic - just a folder containing some special file (e.g. a VCS
+marker or a project descriptor file like `pom.xml` or `Gemfile`). Projectile
+will auto-detect pretty much every popular project type out of the box
+and you can easily extend it with additional project types.
+
+Here are some of Projectile's features:
 
 * jump to a file in project
-* jump to files at point in project
-* jump to a directory in project
-* jump to a file in a directory
 * jump to a project buffer
 * jump to a test in project
 * toggle between files with same names but different extensions (e.g. `.h` <-> `.c/.cpp`, `Gemfile` <-> `Gemfile.lock`)
 * toggle between code and its test (e.g. `main.service.js` <-> `main.service.spec.js`)
 * jump to recently visited files in the project
 * switch between projects you have worked on
-* kill all project buffers
+* kill (close) all project buffers
 * replace in project
-* multi-occur in project buffers
-* grep in project
-* regenerate project etags or gtags (requires [ggtags](https://github.com/leoliu/ggtags)).
-* visit project in dired
-* run make in a project with a single key chord
-* check for dirty repositories
-* toggle read-only mode for the entire project
+* grep (search) in project
+* run shell commands in a project (e.g. `make`, `lein`)
+* support for multiple minibuffer completion/selection libraries (`ido`, `ivy`, `helm` and the default completion system)
 
-Here's a glimpse of Projectile in action:
+---------------
+[![Patreon](https://img.shields.io/badge/patreon-donate-orange.svg)](https://www.patreon.com/bbatsov)
+[![Paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=GRQKNBM6P8VRQ)
 
-![Projectile Screenshot](doc/screenshots/projectile.png)
+I've been developing Projectile for a decade now. While it's a fun
+project to work on, it still requires a lot of time and energy to
+maintain.
 
 You can support my work on Projectile via
  [PayPal](https://www.paypal.me/bbatsov),
  [Patreon](https://www.patreon.com/bbatsov) and
  [GitHub Sponsors](https://github.com/sponsors/bbatsov).
 
+## Projectile in Action
+
+Here's a glimpse of Projectile in action (using `ivy`):
+
+![Projectile Demo](doc/modules/ROOT/assets/images/projectile-demo.gif)
+
+In this short demo you can see:
+
+* finding files in a project
+* switching between implementation and test
+* switching between projects
+
 ## Quickstart
 
 The instructions that follow are meant to get you from zero to a running Projectile setup
 in a minute.  Visit the
-[user manual](https://docs.projectile.mx) for (way) more
+[online documentation](https://docs.projectile.mx) for (way) more
 details.
 
 ### Installation
@@ -79,9 +89,11 @@ simply `apt-get install elpa-projectile`
 
 Finally add this to your Emacs config:
 
-```el
+```elisp
 (projectile-mode +1)
+;; Recommended keymap prefix on macOS
 (define-key projectile-mode-map (kbd "s-p") 'projectile-command-map)
+;; Recommended keymap prefix on Windows/Linux
 (define-key projectile-mode-map (kbd "C-c p") 'projectile-command-map)
 ```
 
@@ -91,12 +103,13 @@ Those keymap prefixes are just a suggest
 
 Enable `projectile-mode`, open a file in one of your projects and type a command such as <kbd>C-c p f</kbd>.
 
-See the user manual for more details.
+See the [online documentation](https://docs.projectile.mx) for more details.
 
 ## Caveats
 
 * Some operations like search (grep) depend (presently) on external
   utilities such as `find`.
+* Commands depending on external utilities might misbehave on the `fish` shell.
 * Using Projectile over TRAMP might be slow in certain cases.
 * Some commands might misbehave on complex project setups (e.g. a git project with submodules)
 * Projectile was mostly tested on Unix OS-es (e.g. GNU/Linux and macOS), so some functionality might not work well on Windows
@@ -106,7 +119,7 @@ See the user manual for more details.
 Check out the project's
 [issue list](https://github.com/bbatsov/projectile/issues?sort=created&direction=desc&state=open)
 a list of unresolved issues. By the way - feel free to fix any of them
-and sent me a pull request. :-)
+and send me a pull request. :-)
 
 ## Contributors
 
@@ -121,7 +134,7 @@ A fairly extensive changelog is availabl
 
 ## License
 
-Copyright © 2011-2020 Bozhidar Batsov and
+Copyright © 2011-2021 Bozhidar Batsov and
 [contributors](https://github.com/bbatsov/projectile/contributors).
 
 Distributed under the GNU General Public License, version 3
diff -pruN 2.1.0-1.1/test/elpa.el 2.5.0-1/test/elpa.el
--- 2.1.0-1.1/test/elpa.el	2020-02-04 18:30:35.000000000 +0000
+++ 2.5.0-1/test/elpa.el	1970-01-01 00:00:00.000000000 +0000
@@ -1,5 +0,0 @@
-(setq package-user-dir
-      (expand-file-name (format ".elpa/%s/elpa" emacs-version)))
-(package-initialize)
-(add-to-list 'load-path default-directory)
-
diff -pruN 2.1.0-1.1/test/make-compile.el 2.5.0-1/test/make-compile.el
--- 2.1.0-1.1/test/make-compile.el	2020-02-04 18:30:35.000000000 +0000
+++ 2.5.0-1/test/make-compile.el	1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-(setq files '("projectile.el"))
-(setq byte-compile--use-old-handlers nil)
-(mapc #'byte-compile-file files)
diff -pruN 2.1.0-1.1/test/make-update.el 2.5.0-1/test/make-update.el
--- 2.1.0-1.1/test/make-update.el	2020-02-04 18:30:35.000000000 +0000
+++ 2.5.0-1/test/make-update.el	1970-01-01 00:00:00.000000000 +0000
@@ -1,26 +0,0 @@
-(setq package-user-dir
-      (expand-file-name (format ".elpa/%s/elpa" emacs-version)))
-(message "installing in %s ...\n" package-user-dir)
-(package-initialize)
-(setq package-archives
-      '(("melpa" . "http://melpa.org/packages/")
-        ("gnu" . "http://elpa.gnu.org/packages/")))
-(package-refresh-contents)
-
-(defconst dev-packages
-  '(helm noflet ag))
-
-(dolist (package dev-packages)
-  (unless (package-installed-p package)
-    (ignore-errors
-     (package-install package))))
-
-(save-window-excursion
-  (package-list-packages t)
-  (condition-case nil
-      (progn
-        (package-menu-mark-upgrades)
-        (package-menu-execute t))
-    (error
-     (message "All packages up to date"))))
-
diff -pruN 2.1.0-1.1/test/projectile-test.el 2.5.0-1/test/projectile-test.el
--- 2.1.0-1.1/test/projectile-test.el	2020-02-04 18:30:35.000000000 +0000
+++ 2.5.0-1/test/projectile-test.el	2021-08-10 10:11:43.000000000 +0000
@@ -1,6 +1,6 @@
-;;; projectile-test.el
+;;; projectile-test.el --- Projectile's test suite -*- lexical-binding: t -*-
 
-;; Copyright © 2011-2020 Bozhidar Batsov
+;; Copyright © 2011-2021 Bozhidar Batsov
 
 ;; Author: Bozhidar Batsov <bozhidar@batsov.com>
 
@@ -21,24 +21,25 @@
 
 ;;; Commentary:
 
-;; This file is part of Projectile.
+;; Projectile's Buttercup-powered test suite.  You can run it either
+;; interactively or via the command-line (e.g. via eldev test).
 
 ;;; Code:
 
 (require 'projectile)
 (require 'buttercup)
 
-
+;; Useful debug information
 (message "Running tests on Emacs %s" emacs-version)
 
 ;; TODO: Revise this init logic
-(let* ((current-file (if load-in-progress load-file-name (buffer-file-name)))
-       (source-directory (locate-dominating-file current-file "Cask"))
-       ;; Do not load outdated byte code for tests
-       (load-prefer-newer t))
-  ;; Load the file under test
-  (load (expand-file-name "projectile" source-directory))
-  (setq projectile-test-path (expand-file-name "test" source-directory)))
+(defvar projectile-test-path (let* ((current-file (if load-in-progress load-file-name (buffer-file-name)))
+                                    (source-directory (locate-dominating-file current-file "Eldev"))
+                                    ;; Do not load outdated byte code for tests
+                                    (load-prefer-newer t))
+                               ;; Load the file under test
+                               (load (expand-file-name "projectile" source-directory))
+                               (expand-file-name "test" source-directory)))
 
 ;;; Test Utilities
 (defmacro projectile-test-with-sandbox (&rest body)
@@ -87,12 +88,54 @@ You'd normally combine this with `projec
      (spy-on 'projectile-project-root :and-return-value (file-truename (expand-file-name "project/")))
      ,@body))
 
+;;; To avoid a macro, we could write a single "it" and iterate over a list of
+;;; functions. However, it would require manually rescuing the error and manually
+;;; re-throwing the error to include the function name in the error string, to
+;;; make it clear which function we're dealing with.  That could be avoided if
+;;; buttercup allowed us to specify a custom error message like this:
+;;;
+;;; (expect (funcall 'foo) :to-throw 'error nil "Custom error message here")
+(defmacro assert-friendly-error-when-no-project (fn)
+  "Write a test that ensures FN throws a friendly error when called without a project."
+  (let ((description (concat "when calling " (symbol-name fn) " without a project")))
+    `(describe
+      ,description
+      :var ((fn ',fn))
+      (it "throws a friendly error"
+          (projectile-test-with-sandbox
+           (projectile-test-with-files
+            ("index.html")
+            (find-file-noselect "index.html" t)
+            ;; Avoid "the current buffer is not visiting a file" error
+            (write-file "index.html")
+            (spy-on 'projectile-project-root :and-return-value nil)
+            (let ((projectile-require-project-root t))
+              (expect (call-interactively fn)
+                      :to-throw
+                      'error
+                      (list (concat "Projectile cannot find a project definition in "
+                                    default-directory))))))))))
+
 (defun projectile-test-tmp-file-path ()
   "Return a filename suitable to save data to in the test temp directory."
   (concat projectile-test-path
           "/tmp/temporary-file-" (format "%d" (random))
           ".eld"))
 
+(defun file-handler-for-tests (operation &rest args)
+  "Handler for # files.
+Just delegates OPERATION and ARGS for all operations except for`shell-command`'."
+  (let ((inhibit-file-name-handlers
+         (cons 'file-handler-for-tests
+               (and (eq inhibit-file-name-operation operation)
+                  inhibit-file-name-handlers)))
+        (inhibit-file-name-operation operation))
+    (cond ((eq operation 'shell-command) (let ((default-directory ""))
+                                           (shell-command "echo magic" t)))
+          (t (apply operation args)))))
+
+(add-to-list 'file-name-handler-alist (cons "^#" 'file-handler-for-tests))
+
 ;;; Tests
 (describe "projectile-project-name"
   (it "return projectile-project-name when present"
@@ -119,6 +162,20 @@ You'd normally combine this with `projec
     (expect (projectile-expand-root "foo/bar") :to-equal "/path/to/project/foo/bar")
     (expect (projectile-expand-root "./foo/bar") :to-equal "/path/to/project/foo/bar")))
 
+(describe "projectile--combine-plists"
+ (it "Items in second plist override elements in first"
+   (expect (projectile--combine-plists
+            '(:foo "foo" :bar "bar")
+            '(:foo "foo" :bar "foo" :foobar "foobar"))
+           :to-equal
+           '(:foo "foo" :bar "foo" :foobar "foobar")))
+ (it "Nil elements in second plist do not override elements in first"
+   (expect (projectile--combine-plists
+            '(:foo "foo" :bar "bar")
+            '(:foo "foo" :bar nil :foobar "foobar"))
+           :to-equal
+           '(:foo "foo" :bar "bar" :foobar "foobar"))))
+
 (describe "projectile-register-project-type"
   (it "prepends new projects to projectile-project-types"
     (projectile-register-project-type 'foo '("Foo"))
@@ -126,11 +183,47 @@ You'd normally combine this with `projec
     (projectile-register-project-type 'bar '("Bar"))
     (expect (caar projectile-project-types) :to-equal 'bar)))
 
+(describe "projectile-update-project-type"
+  :var ((mock-projectile-project-types
+           '((foo marker-files "marker-file"
+                  project-file "project-file"
+                  compilation-dir "compilation-dir"
+                  configure-command "configure"
+                  compile-command "compile"
+                  test-command "test"
+                  install-command "install"
+                  package-command "package"
+                  run-command "run"))))
+  (it "Updates existing project in projectile-project-types"
+    (let ((projectile-project-types mock-projectile-project-types))
+      (projectile-update-project-type
+       'foo
+       :marker-files "marker-file2"
+       :test-suffix "suffix")
+      (expect projectile-project-types :to-equal
+              '((foo marker-files "marker-file2"
+                     project-file "project-file"
+                     compilation-dir "compilation-dir"
+                     configure-command "configure"
+                     compile-command "compile"
+                     test-command "test"
+                     install-command "install"
+                     package-command "package"
+                     run-command "run"
+                     test-suffix "suffix")))))
+  (it "Error when attempt to update nonexistant project type"
+    (let ((projectile-project-types mock-projectile-project-types))
+      (expect (projectile-update-project-type
+               'bar
+               :marker-files "marker-file"
+               :test-suffix "suffix")
+              :to-throw))))
+
 (describe "projectile-project-type"
   (it "detects the type of Projectile's project"
-    (expect (projectile-project-type) :to-equal 'emacs-cask))
+    (expect (projectile-project-type) :to-equal 'emacs-eldev))
   (it "caches the project type"
-    (expect (gethash (projectile-project-root) projectile-project-type-cache) :to-equal 'emacs-cask)))
+    (expect (gethash (projectile-project-root) projectile-project-type-cache) :to-equal 'emacs-eldev)))
 
 (describe "projectile-ignored-directory-p"
   (it "checks if directory should be ignored"
@@ -150,11 +243,11 @@ You'd normally combine this with `projec
     (spy-on 'projectile-project-root :and-return-value "/path/to/project")
     (spy-on 'projectile-project-name :and-return-value "project")
     (spy-on 'projectile-project-ignored-files :and-return-value '("foo.js" "bar.rb"))
-    (let ((files'("/path/to/project/TAGS"
-                  "/path/to/project/foo.js"
-                  "/path/to/project/bar.rb"
-                  "/path/to/project/file1.log"
-                  "/path/to/project/file2.log"))
+    (let ((files '("/path/to/project/TAGS"
+                   "/path/to/project/foo.js"
+                   "/path/to/project/bar.rb"
+                   "/path/to/project/file1.log"
+                   "/path/to/project/file2.log"))
           (projectile-ignored-files '("TAGS" "file\d+\\.log")))
       (expect (projectile-ignored-files) :not :to-equal files)
       (expect (projectile-ignored-files) :to-equal '("/path/to/project/TAGS"
@@ -251,10 +344,23 @@ You'd normally combine this with `projec
     (spy-on 'file-truename :and-call-fake (lambda (filename) filename))
     (spy-on 'insert-file-contents :and-call-fake
             (lambda (filename)
-              (save-excursion (insert "\n-exclude\n+include\nno-prefix\n left-wspace\nright-wspace\t\n"))))
+              (save-excursion (insert "\n-exclude\n+include\n#may-be-a-comment\nno-prefix\n left-wspace\nright-wspace\t\n"))))
     (expect (projectile-parse-dirconfig-file) :to-equal '(("include/")
-                                                          ("exclude" "no-prefix" "left-wspace" "right-wspace")
-                                                          nil))))
+                                                          ("exclude"
+							   "#may-be-a-comment"
+							   "no-prefix"
+							   "left-wspace"
+							   "right-wspace")
+                                                          nil))
+    ;; same test - but with comment lines enabled using prefix '#'
+    (let ((projectile-dirconfig-comment-prefix ?#))
+      (expect (projectile-parse-dirconfig-file) :to-equal '(("include/")
+							    ("exclude"
+							     "no-prefix"
+							     "left-wspace"
+							     "right-wspace")
+							    nil)))
+    ))
 
 (describe "projectile-get-project-directories"
   (it "gets the list of project directories"
@@ -292,18 +398,34 @@ You'd normally combine this with `projec
     (expect (string-empty-p (projectile-get-sub-projects-command 'none)) :to-be-truthy)))
 
 (describe "projectile-files-via-ext-command"
-  (it "returns nil when command is nil or empty"
-    (expect (projectile-files-via-ext-command "" "") :not :to-be-truthy)
-    (expect (projectile-files-via-ext-command "" nil) :not :to-be-truthy)))
+          (it "returns nil when command is nil or empty or fails"
+              (expect (projectile-files-via-ext-command "" "") :not :to-be-truthy)
+              (expect (projectile-files-via-ext-command "" nil) :not :to-be-truthy)
+              (expect (projectile-files-via-ext-command "" "echo Not a file name! > &2") :not :to-be-truthy)
+              (expect (projectile-files-via-ext-command "" "echo filename") :to-equal '("filename")))
+
+          (it "supports magic file handlers"
+              (expect (projectile-files-via-ext-command "#magic#" "echo filename") :to-equal '("magic"))))
 
 (describe "projectile-mode"
-  (it "sets up hook functions"
+  (before-each
     (spy-on 'projectile--cleanup-known-projects)
-    (spy-on 'projectile-discover-projects-in-search-path)
+    (spy-on 'projectile-discover-projects-in-search-path))
+  (it "sets up hook functions"
     (projectile-mode 1)
     (expect (memq 'projectile-find-file-hook-function find-file-hook) :to-be-truthy)
     (projectile-mode -1)
-    (expect (memq 'projectile-find-file-hook-function find-file-hook) :not :to-be-truthy)))
+    (expect (memq 'projectile-find-file-hook-function find-file-hook) :not :to-be-truthy))
+  (it "respects projectile-auto-discover setting"
+    (unwind-protect
+        (progn
+          (let ((projectile-auto-discover nil))
+            (projectile-mode 1)
+            (expect 'projectile-discover-projects-in-search-path :not :to-have-been-called))
+          (let ((projectile-auto-discover t))
+            (projectile-mode 1)
+            (expect 'projectile-discover-projects-in-search-path :to-have-been-called)))
+      (projectile-mode -1))))
 
 (describe "projectile-relevant-known-projects"
   (it "returns a list of known projects"
@@ -455,16 +577,16 @@ You'd normally combine this with `projec
       (let ((projectile-project-root-files-bottom-up '("somefile" ".projectile"))
             (projectile-project-root-files '("otherfile" "framework.conf" "requirements.txt"))
             (projectile-project-root-files-top-down-recurring '(".svn" ".foo"))
-            (projectile-project-root-files-functions '(projectile-root-bottom-up
-                                                       projectile-root-top-down
-                                                       projectile-root-top-down-recurring)))
+            (projectile-project-root-functions '(projectile-root-bottom-up
+                                                 projectile-root-top-down
+                                                 projectile-root-top-down-recurring)))
         (projectile-test-should-root-in "projectA" "projectA/requirements/a/b/c/d/e/f/g")
         (projectile-test-should-root-in "projectA" "projectA/src/framework/lib")
         (projectile-test-should-root-in "projectA" "projectA/src/html")
 
-        (setq projectile-project-root-files-functions '(projectile-root-top-down
-                                                        projectile-root-top-down-recurring
-                                                        projectile-root-bottom-up))
+        (setq projectile-project-root-functions '(projectile-root-top-down
+                                                  projectile-root-top-down-recurring
+                                                  projectile-root-bottom-up))
         (projectile-test-should-root-in "projectA/requirements/a/b/c"
                                         "projectA/requirements/a/b/c/d/e/f/g")
         (projectile-test-should-root-in "projectA/src/framework"
@@ -475,9 +597,9 @@ You'd normally combine this with `projec
       (let ((projectile-project-root-files-bottom-up '("somefile" ".projectile"))
             (projectile-project-root-files '("otherfile" "noframework.conf"))
             (projectile-project-root-files-top-down-recurring '(".svn" ".foo"))
-            (projectile-project-root-files-functions '(projectile-root-top-down-recurring
-                                                       projectile-root-bottom-up
-                                                       projectile-root-top-down)))
+            (projectile-project-root-functions '(projectile-root-top-down-recurring
+                                                 projectile-root-bottom-up
+                                                 projectile-root-top-down)))
         (projectile-test-should-root-in "projectA/src" "projectA/src/framework/lib")
         (projectile-test-should-root-in "projectA/src" "projectA/src/html")
         (projectile-test-should-root-in "projectA/" "projectA/build/framework/lib"))
@@ -485,18 +607,18 @@ You'd normally combine this with `projec
       (let ((projectile-project-root-files-bottom-up '("somefile" "override"))
             (projectile-project-root-files '("otherfile" "anotherfile"))
             (projectile-project-root-files-top-down-recurring '("someotherfile" "yetanotherfile"))
-            (projectile-project-root-files-functions '(projectile-root-bottom-up
-                                                       projectile-root-top-down
-                                                       projectile-root-top-down-recurring)))
+            (projectile-project-root-functions '(projectile-root-bottom-up
+                                                 projectile-root-top-down
+                                                 projectile-root-top-down-recurring)))
         (projectile-test-should-root-in default-directory "projectA/src/framework/lib")
         (projectile-test-should-root-in default-directory "projectA/src/html"))
 
       (let ((projectile-project-root-files-bottom-up '("somecoolfile"))
             (projectile-project-root-files nil)
             (projectile-project-root-files-top-down-recurring '(".svn"))
-            (projectile-project-root-files-functions '(projectile-root-bottom-up
-                                                       projectile-root-top-down
-                                                       projectile-root-top-down-recurring)))
+            (projectile-project-root-functions '(projectile-root-bottom-up
+                                                 projectile-root-top-down
+                                                 projectile-root-top-down-recurring)))
         (projectile-test-should-root-in "projectA/src/" "projectA/src/")
         (projectile-test-should-root-in "projectA/src/" "projectA/src/html"))))))
 
@@ -620,7 +742,7 @@ You'd normally combine this with `projec
                  0 ;; Cached 1st of January 1970.
                  projectile-projects-cache-time)
 
-        (spy-on 'projectile-project-root :and-call-fake (lambda () (file-truename default-directory)))
+        (spy-on 'projectile-acquire-root :and-call-fake (lambda () (file-truename default-directory)))
         (spy-on 'projectile-project-vcs :and-return-value 'none)
         ;; After listing all the files, the cache should have been updated.
         (projectile-current-project-files)
@@ -761,6 +883,54 @@ You'd normally combine this with `projec
     (let ((projectile-known-projects nil))
       (expect (projectile-switch-project) :to-throw))))
 
+(describe "projectile-switch-project-by-name"
+  (it "calls the switch project action with project-to-switch's dir-locals loaded"
+    (defvar switch-project-foo)
+    (let ((foo 'bar)
+          (switch-project-foo)
+          (safe-local-variable-values '((foo . baz)))
+          (projectile-switch-project-action (lambda () (setq switch-project-foo foo))))
+      (projectile-test-with-sandbox
+        (projectile-test-with-files
+            ("project/"
+             "project/.dir-locals.el"
+             "project/.projectile")
+          (append-to-file
+           "((nil . ((foo . baz))))" nil "project/.dir-locals.el")
+          (projectile-add-known-project (file-name-as-directory (expand-file-name "project")))
+          (projectile-switch-project-by-name (file-name-as-directory (expand-file-name "project")))
+
+          (expect switch-project-foo :to-be 'baz)))))
+
+  (it "runs hooks from the project root directory"
+      (defvar hook-dir)
+      (let ((projectile-switch-project-action
+             (lambda () (switch-to-buffer (find-file-noselect "file" t))))
+            (hook (lambda () (setq hook-dir default-directory))))
+        (add-hook 'projectile-after-switch-project-hook hook)
+        (projectile-test-with-sandbox
+         (projectile-test-with-files
+          ("project/"
+           "project/file")
+          (let ((project-dir (file-name-as-directory (expand-file-name "project"))))
+            (projectile-add-known-project project-dir)
+            (projectile-switch-project-by-name project-dir)
+            (remove-hook 'projectile-after-switch-project-hook hook)
+
+            (expect hook-dir :to-equal project-dir))))))
+
+  (it "ensures the buffer is switched immediately"
+      (let ((projectile-switch-project-action
+             (lambda () (switch-to-buffer (find-file-noselect "file" t)))))
+        (projectile-test-with-sandbox
+         (projectile-test-with-files
+          ("project/"
+           "project/file")
+          (projectile-add-known-project (file-name-as-directory (expand-file-name "project")))
+          (projectile-switch-project-by-name (file-name-as-directory (expand-file-name "project")))
+
+          (expect (current-buffer) :to-be (get-file-buffer "project/file")))))))
+
 (describe "projectile-ignored-buffer-p"
   (it "checks if buffer should be ignored"
     (let ((projectile-globally-ignored-buffers '("*nrepl messages*" "*something*")))
@@ -956,7 +1126,16 @@ You'd normally combine this with `projec
        "project/package.json")
       (let ((projectile-indexing-method 'native))
         (spy-on 'projectile-project-root :and-return-value (file-truename (expand-file-name "project/")))
-        (expect (projectile-detect-project-type) :to-equal 'rails-rspec))))))
+        (expect (projectile-detect-project-type) :to-equal 'rails-rspec)))))
+  (it "detects project-type for elisp eldev projects"
+    (projectile-test-with-sandbox
+     (projectile-test-with-files
+      ("project/"
+       "project/Eldev"
+       "project/project.el")
+      (let ((projectile-indexing-method 'native))
+        (spy-on 'projectile-project-root :and-return-value (file-truename (expand-file-name "project/")))
+        (expect (projectile-detect-project-type) :to-equal 'emacs-eldev))))))
 
 (describe "projectile-dirname-matching-count"
   (it "counts matching dirnames ascending file paths"
@@ -1033,7 +1212,37 @@ You'd normally combine this with `projec
         (expect (projectile-test-file-p "src/Foo.cpp") :to-equal nil)
         (expect (projectile--find-matching-test "src/Foo.cpp") :to-equal '("test/Foo.cpp"))
         (expect (projectile--find-matching-test "src/Foo.cpp") :to-equal '("test/Foo.cpp"))
-        (expect (projectile--find-matching-file "test/Foo.cpp") :to-equal '("src/Foo.cpp"))))))
+        (expect (projectile--find-matching-file "test/Foo.cpp") :to-equal '("src/Foo.cpp")))))
+
+  (it "defers to test-dir property when it's set to a function"
+    (projectile-test-with-sandbox
+     (projectile-test-with-files-using-custom-project
+          ("src/foo/Foo.cpp"
+           "src/bar/Foo.cpp"
+           "test/foo/FooTest.cpp")
+          (:test-dir
+           (lambda (file-path)
+             (projectile-complementary-dir file-path "src" "test"))
+           :test-suffix "Test")
+          (expect (projectile--find-matching-test
+                   (projectile-expand-root "src/bar/Foo.cpp"))
+                  :to-equal
+                  (list "test/bar/FooTest.cpp")))))
+
+  (it "defers to src-dir property when it's set to a function"
+    (projectile-test-with-sandbox
+     (projectile-test-with-files-using-custom-project
+          ("src/foo/Foo.cpp"
+           "src/bar/Foo.cpp"
+           "test/foo/FooTest.cpp")
+          (:src-dir
+           (lambda (file-path)
+             (projectile-complementary-dir file-path "test" "src"))
+           :test-suffix "Test")
+          (expect (projectile--find-matching-file
+                   (projectile-expand-root "test/foo/FooTest.cpp"))
+                  :to-equal
+                  (list "src/foo/Foo.cpp"))))))
 
 (describe "projectile--related-files"
   (it "returns related files for the given file"
@@ -1330,6 +1539,14 @@ You'd normally combine this with `projec
       (projectile-clear-known-projects)
       (expect projectile-known-projects :to-equal nil))))
 
+(describe "projectile-reset-known-projects"
+  (it "resets known projects"
+    (spy-on 'projectile-clear-known-projects)
+    (spy-on 'projectile-discover-projects-in-search-path)
+    (projectile-reset-known-projects)
+    (expect 'projectile-clear-known-projects :to-have-been-called)
+    (expect 'projectile-discover-projects-in-search-path :to-have-been-called)))
+
 (describe "projectile-test-ignored-directory-p"
   (it "ignores specified literal directory values"
     (spy-on 'projectile-ignored-directories :and-return-value '("/path/to/project/tmp"))
@@ -1414,3 +1631,240 @@ You'd normally combine this with `projec
 (describe "projectile-find-file-in-directory"
   (it "fails when called in a non-existing directory"
     (expect (projectile-find-file-in-directory "asdf") :to-throw)))
+
+(describe "projectile-dir-files-native"
+  (it "calculates ignored files and directories only once during recursion"
+    (projectile-test-with-sandbox
+     (projectile-test-with-files
+      ("projectA/"
+       "projectA/.svn/"
+       "projectA/src/.svn/"
+       "projectA/src/html/.svn/"
+       "projectA/.git/"
+       "projectA/src/html/"
+       "projectA/src/framework/lib/"
+       "projectA/src/framework.conf"
+       "projectA/src/html/index.html"
+       "projectA/.projectile")
+
+      ;; verify that indexing only invokes these funcs once during recursion
+      (spy-on 'projectile-ignored-files :and-call-through)
+      (spy-on 'projectile-ignored-directories :and-call-through)
+      (spy-on 'projectile-globally-ignored-directory-names :and-call-through)
+
+      (projectile-dir-files-native "projectA/")
+      (expect 'projectile-ignored-files :to-have-been-called-times 1)
+      (expect 'projectile-globally-ignored-directory-names :to-have-been-called-times 1)
+      (expect 'projectile-ignored-directories :to-have-been-called-times 1))))
+  (it "ignores globally ignored directories when using native indexing"
+      (projectile-test-with-sandbox
+       (projectile-test-with-files
+        ("project/"
+         "project/.ignoreme/"
+         "project/.ignoreme/should_ignore"
+         "project/src/"
+         "project/src/.ignoreme/"
+         "project/src/.ignoreme/should_ignore"
+         "project/config.conf")
+
+        (setq projectile-globally-ignored-directories '(".ignoreme"))
+        (expect (projectile-dir-files-native "project") :to-equal '("config.conf"))))))
+
+(describe "projectile-process-current-project-buffers-current"
+  (it "expects projectile-process-current-project-buffers and
+projectile-process-current-project-buffers-current to have similar behaviour"
+    (projectile-test-with-sandbox
+     (projectile-test-with-files
+      ("projectA/"
+       "projectA/.projectile"
+       "projectA/bufferA"
+       "projectA/fileA"
+       "projectA/dirA/"
+       "projectA/dirA/fileC")
+      (let ((list-a '())
+            (list-b '()))
+        (projectile-process-current-project-buffers (lambda (b) (push b list-a)))
+        (projectile-process-current-project-buffers-current (lambda () (push (current-buffer) list-b)))
+        (expect list-a :to-equal list-b))))))
+
+(describe "projectile--impl-name-for-test-name"
+  :var ((mock-projectile-project-types
+         '((foo test-suffix "Test")
+           (bar test-prefix "Test"))))
+  (it "removes suffix from test file"
+    (cl-letf (((symbol-function 'projectile-project-type) (lambda () 'foo))
+              (projectile-project-types mock-projectile-project-types))
+      (expect (projectile--impl-name-for-test-name "FooTest.cpp")
+              :to-equal
+              "Foo.cpp")))
+  (it "removes prefix from test file"
+    (cl-letf (((symbol-function 'projectile-project-type) (lambda () 'bar))
+              (projectile-project-types mock-projectile-project-types))
+      (expect (projectile--impl-name-for-test-name "TestFoo.cpp")
+              :to-equal
+              "Foo.cpp"))))
+
+(describe "projectile-find-implementation-or-test"
+  (it "error when test file does not exist and projectile-create-missing-test-files is nil"
+    (cl-letf (((symbol-function 'projectile-test-file-p) #'ignore)
+              ((symbol-function 'file-exists-p) #'ignore)
+              ((symbol-function 'projectile-expand-root) #'identity)
+              ((symbol-function 'projectile-find-matching-test) (lambda (file) "dir/foo"))
+              (projectile-create-missing-test-files nil))
+      (expect (projectile-find-implementation-or-test "foo") :to-throw))))
+
+(describe "projectile--impl-file-from-src-dir-fn"
+  :var ((mock-projectile-project-types
+         '((foo src-dir (lambda (impl-file) "/outer/foo/test/dir"))
+           (bar src-dir "not a function"))))
+  (it "returns result of projectile--complementary-file when src-dir property is a function"
+    (cl-letf (((symbol-function 'projectile--complementary-file)
+               (lambda (impl-file dir-fn file-fn) (funcall dir-fn impl-file)))
+              ((symbol-function 'projectile-project-type) (lambda () 'foo))
+              ((symbol-function 'projectile-project-root) (lambda () "foo"))
+              ((symbol-function 'file-relative-name) (lambda (f rel) f))
+              ((symbol-function 'file-exists-p) (lambda (file) t))
+              (projectile-project-types mock-projectile-project-types))
+      (expect (projectile--impl-file-from-src-dir-fn "foo") :to-equal "/outer/foo/test/dir")))
+  (it "returns file relative to project root"
+    (cl-letf (((symbol-function 'projectile--complementary-file)
+               (lambda (impl-file dir-fn file-fn) (funcall dir-fn impl-file)))
+              ((symbol-function 'projectile-project-type) (lambda () 'foo))
+              ((symbol-function 'projectile-project-root) (lambda () "/outer/foo"))
+              ((symbol-function 'file-exists-p) (lambda (file) t))
+              (projectile-project-types mock-projectile-project-types))
+      (expect (projectile--impl-file-from-src-dir-fn "/outer/foo/bar")
+              :to-equal
+              "test/dir")))
+  (it "returns nil when src-dir property is a not function"
+    (cl-letf (((symbol-function 'projectile-project-type) (lambda () 'bar))
+              ((symbol-function 'projectile-project-root) (lambda () "foo"))
+              (projectile-project-types mock-projectile-project-types))
+      (expect (projectile--impl-file-from-src-dir-fn "bar") :to-equal nil)))
+  (it "returns nil when src-dir function result is not an existing file"
+    (cl-letf (((symbol-function 'projectile--complementary-file)
+               (lambda (impl-file dir-fn file-fn) (funcall dir-fn impl-file)))
+              ((symbol-function 'projectile-project-type) (lambda () 'foo))
+              ((symbol-function 'projectile-project-root) (lambda () "/outer/foo"))
+              ((symbol-function 'file-exists-p) #'ignore)
+              (projectile-project-types mock-projectile-project-types))
+      (expect (projectile--impl-file-from-src-dir-fn "bar") :to-equal nil))))
+
+(describe "projectile--test-file-from-test-dir-fn"
+  :var ((mock-projectile-project-types
+         '((foo test-dir (lambda (impl-file) "/outer/foo/test/dir"))
+           (bar test-dir "not a function"))))
+  (it "returns result of projectile--complementary-file when test-dir property is a function"
+    (cl-letf (((symbol-function 'projectile--complementary-file)
+               (lambda (impl-file dir-fn file-fn) (funcall dir-fn impl-file)))
+              ((symbol-function 'projectile-project-type) (lambda () 'foo))
+              ((symbol-function 'projectile-project-root) (lambda () "foo"))
+              ((symbol-function 'file-relative-name) (lambda (f rel) f))
+              (projectile-project-types mock-projectile-project-types))
+      (expect (projectile--test-file-from-test-dir-fn "foo") :to-equal "/outer/foo/test/dir")))
+  (it "returns file relative to project root"
+    (cl-letf (((symbol-function 'projectile-project-type) (lambda () 'foo))
+              ((symbol-function 'projectile-project-root) (lambda () "/outer/foo"))
+              ((symbol-function 'projectile--complementary-file)
+               (lambda (impl-file dir-fn file-fn) (funcall dir-fn impl-file)))
+              (projectile-project-types mock-projectile-project-types))
+      (expect (projectile--test-file-from-test-dir-fn "/outer/foo/bar")
+              :to-equal
+              "test/dir")))
+  (it "returns nil when test-dir property is a not function"
+    (cl-letf (((symbol-function 'projectile-project-type) (lambda () 'bar))
+              (projectile-project-types mock-projectile-project-types)
+              ((symbol-function 'projectile-project-root) (lambda () "foo")))
+      (expect (projectile--test-file-from-test-dir-fn "bar") :to-equal nil))))
+
+(describe "projectile--complementary-file"
+  (it "dir-fn and filename-fn applied correctly"
+    (cl-letf (((symbol-function 'file-exists-p) (lambda (file) t))
+              ((symbol-function 'dir-fn) (lambda (dir) "foo/test/dir"))
+              ((symbol-function 'filename-fn) (lambda (filename) "Foo.test")))
+      (expect (projectile--complementary-file
+               "foo/src/dir/Foo.impl"
+               #'dir-fn
+               #'filename-fn)
+              :to-equal "foo/test/dir/Foo.test"))))
+
+(describe "projectile--impl-to-test-dir"
+    :var ((mock-projectile-project-types
+           '((foo test-dir "test" src-dir "src")
+             (bar test-dir identity src-dir "src"))))
+    (it "replaces occurrences of src-dir with test-dir"
+      (cl-letf (((symbol-function 'projectile-project-root) (lambda () "foo"))
+                ((symbol-function 'projectile-project-type) (lambda () 'foo))
+                (projectile-project-types mock-projectile-project-types))
+        (expect (projectile--impl-to-test-dir "/foo/src/Foo") :to-equal "/foo/test/")))
+    (it "error signalled when test dir property is not a string"
+      (cl-letf (((symbol-function 'projectile-project-root) (lambda () "bar"))
+                ((symbol-function 'projectile-project-type) (lambda () 'bar))
+                (projectile-project-types mock-projectile-project-types))
+        (expect (projectile--impl-to-test-dir "/bar/src/bar") :to-throw))))
+
+(describe "projectile-run-shell-command-in-root"
+  (describe "when called directly in elisp"
+    (before-each (spy-on 'shell-command))
+    (describe "when called with all three paramters"
+      (it "expects to call shell-command with the same parameters"
+        (projectile-run-shell-command-in-root "cmd" "output-buffer" "error-buffer")
+        (expect 'shell-command :to-have-been-called-with "cmd" "output-buffer" "error-buffer")))
+    (describe "when called with only one optional paramter"
+      (it "expects to call shell-command with the same parameters"
+        (projectile-run-shell-command-in-root "cmd" "output-buffer")
+        (expect 'shell-command :to-have-been-called-with "cmd" "output-buffer" nil)))
+    (describe "when called with no optional paramters"
+      (it "expects to call shell-command with the same parameters"
+        (projectile-run-shell-command-in-root "cmd")
+        (expect 'shell-command :to-have-been-called-with "cmd" nil nil))))
+  (describe "when called interactively"
+    (before-each (spy-on 'shell-command))
+    (it "expects to be interactive"
+      (expect (interactive-form 'projectile-run-shell-command-in-root) :not :to-be nil))
+    (it "expects to call shell-command with the given command"
+      (funcall-interactively 'projectile-run-shell-command-in-root "cmd")
+      (expect 'shell-command :to-have-been-called-with "cmd" nil nil))))
+
+(describe "projectile-run-async-shell-command-in-root"
+  (describe "when called directly in elisp"
+    (before-each (spy-on 'async-shell-command))
+    (describe "when called with all three paramters"
+      (it "expects to call async-shell-command with the same parameters"
+        (projectile-run-async-shell-command-in-root "cmd" "output-buffer" "error-buffer")
+        (expect 'async-shell-command :to-have-been-called-with "cmd" "output-buffer" "error-buffer")))
+    (describe "when called with only one optional paramter"
+      (it "expects to call async-shell-command with the same parameters"
+        (projectile-run-async-shell-command-in-root "cmd" "output-buffer")
+        (expect 'async-shell-command :to-have-been-called-with "cmd" "output-buffer" nil)))
+    (describe "when called with no optional paramters"
+      (it "expects to call async-shell-command with the same parameters"
+        (projectile-run-async-shell-command-in-root "cmd")
+        (expect 'async-shell-command :to-have-been-called-with "cmd" nil nil))))
+  (describe "when called interactively"
+    (before-each (spy-on 'async-shell-command))
+    (it "expects to be interactive"
+      (expect (interactive-form 'projectile-run-async-shell-command-in-root) :not :to-be nil))
+    (it "expects to call async-shell-command with the given command"
+      (funcall-interactively 'projectile-run-async-shell-command-in-root "cmd")
+      (expect 'async-shell-command :to-have-been-called-with "cmd" nil nil))))
+
+;; A bunch of tests that make sure Projectile commands handle
+;; gracefully the case of being run outside of a project.
+(assert-friendly-error-when-no-project projectile-project-info)
+(assert-friendly-error-when-no-project projectile-display-buffer)
+(assert-friendly-error-when-no-project projectile-find-implementation-or-test-other-frame)
+(assert-friendly-error-when-no-project projectile-find-implementation-or-test-other-window)
+(assert-friendly-error-when-no-project projectile-find-other-file)
+(assert-friendly-error-when-no-project projectile-find-other-file-other-frame)
+(assert-friendly-error-when-no-project projectile-find-other-file-other-window)
+(assert-friendly-error-when-no-project projectile-find-test-file)
+(assert-friendly-error-when-no-project projectile-grep)
+(assert-friendly-error-when-no-project projectile-ibuffer)
+(assert-friendly-error-when-no-project projectile-project-buffers-other-buffer)
+(assert-friendly-error-when-no-project projectile-project-info)
+(assert-friendly-error-when-no-project projectile-regenerate-tags)
+(assert-friendly-error-when-no-project projectile-remove-current-project-from-known-projects)
+(assert-friendly-error-when-no-project projectile-switch-to-buffer)
+(assert-friendly-error-when-no-project projectile-switch-to-buffer-other-frame)
+(assert-friendly-error-when-no-project projectile-switch-to-buffer-other-window)
diff -pruN 2.1.0-1.1/.travis.yml 2.5.0-1/.travis.yml
--- 2.1.0-1.1/.travis.yml	2020-02-04 18:30:35.000000000 +0000
+++ 2.5.0-1/.travis.yml	1970-01-01 00:00:00.000000000 +0000
@@ -1,19 +0,0 @@
-sudo: false
-language: emacs-lisp
-dist: xenial
-env:
-  - EMACS_BINARY=emacs-25.1-travis MAKE_TEST=test
-  - EMACS_BINARY=emacs-25.2-travis MAKE_TEST=test
-  - EMACS_BINARY=emacs-26.3-travis-linux-xenial MAKE_TEST=test
-  - EMACS_BINARY=emacs-git-snapshot-travis-linux-xenial MAKE_TEST=test
-matrix:
-  allow_failures:
-    - env: EMACS_BINARY=emacs-git-snapshot-travis
-  fast_finish: true
-before_script:
-  - curl -fsSkL https://gist.github.com/rejeep/ebcd57c3af83b049833b/raw > x.sh && source ./x.sh
-  - evm install $EMACS_BINARY --use --skip
-  - make elpa
-script:
-  - emacs --version
-  - make $MAKE_TEST
