config

Personal configuration.
git clone git://code.dwrz.net/config
Log | Files | Refs

magit-git.el (124015B)


      1 ;;; magit-git.el --- Git functionality  -*- lexical-binding:t -*-
      2 
      3 ;; Copyright (C) 2008-2024 The Magit Project Contributors
      4 
      5 ;; Author: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
      6 ;; Maintainer: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
      7 
      8 ;; SPDX-License-Identifier: GPL-3.0-or-later
      9 
     10 ;; Magit is free software: you can redistribute it and/or modify it
     11 ;; under the terms of the GNU General Public License as published by
     12 ;; the Free Software Foundation, either version 3 of the License, or
     13 ;; (at your option) any later version.
     14 ;;
     15 ;; Magit is distributed in the hope that it will be useful, but WITHOUT
     16 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     17 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
     18 ;; License for more details.
     19 ;;
     20 ;; You should have received a copy of the GNU General Public License
     21 ;; along with Magit.  If not, see <https://www.gnu.org/licenses/>.
     22 
     23 ;;; Commentary:
     24 
     25 ;; This library implements wrappers for various Git plumbing commands.
     26 
     27 ;;; Code:
     28 
     29 (require 'magit-base)
     30 
     31 (require 'format-spec)
     32 
     33 ;; From `magit-branch'.
     34 (defvar magit-branch-prefer-remote-upstream)
     35 (defvar magit-published-branches)
     36 
     37 ;; From `magit-margin'.
     38 (declare-function magit-maybe-make-margin-overlay "magit-margin" ())
     39 
     40 ;; From `magit-mode'.
     41 (declare-function magit-get-mode-buffer "magit-mode"
     42                   (mode &optional value frame))
     43 (declare-function magit-refresh "magit-mode" ())
     44 (defvar magit-buffer-diff-type)
     45 (defvar magit-buffer-diff-args)
     46 (defvar magit-buffer-file-name)
     47 (defvar magit-buffer-log-args)
     48 (defvar magit-buffer-log-files)
     49 (defvar magit-buffer-refname)
     50 (defvar magit-buffer-revision)
     51 
     52 ;; From `magit-process'.
     53 (declare-function magit-call-git "magit-process" (&rest args))
     54 (declare-function magit-git "magit-process" (&rest args))
     55 (declare-function magit-process-buffer "magit-process" (&optional nodisplay))
     56 (declare-function magit-process-file "magit-process"
     57                   (process &optional infile buffer display &rest args))
     58 (declare-function magit-process-git "magit-process" (destination &rest args))
     59 (declare-function magit-process-insert-section "magit-process"
     60                   (pwd program args &optional errcode errlog))
     61 (defvar magit-this-error)
     62 (defvar magit-process-error-message-regexps)
     63 
     64 (eval-when-compile
     65   (cl-pushnew 'orig-rev eieio--known-slot-names)
     66   (cl-pushnew 'number eieio--known-slot-names))
     67 
     68 ;;; Options
     69 
     70 ;; For now this is shared between `magit-process' and `magit-git'.
     71 (defgroup magit-process nil
     72   "Git and other external processes used by Magit."
     73   :group 'magit)
     74 
     75 (defvar magit-git-environment
     76   (list (format "INSIDE_EMACS=%s,magit" emacs-version))
     77   "Prepended to `process-environment' while running git.")
     78 
     79 (defcustom magit-git-output-coding-system
     80   (and (eq system-type 'windows-nt) 'utf-8)
     81   "Coding system for receiving output from Git.
     82 
     83 If non-nil, the Git config value `i18n.logOutputEncoding' should
     84 be set via `magit-git-global-arguments' to value consistent with
     85 this."
     86   :package-version '(magit . "2.9.0")
     87   :group 'magit-process
     88   :type '(choice (coding-system :tag "Coding system to decode Git output")
     89                  (const :tag "Use system default" nil)))
     90 
     91 (defvar magit-git-w32-path-hack nil
     92   "Alist of (EXE . (PATHENTRY)).
     93 This specifies what additional PATH setting needs to be added to
     94 the environment in order to run the non-wrapper git executables
     95 successfully.")
     96 
     97 (defcustom magit-git-executable
     98   (or (and (eq system-type 'windows-nt)
     99            ;; Avoid the wrappers "cmd/git.exe" and "cmd/git.cmd",
    100            ;; which are much slower than using "bin/git.exe" directly.
    101            (and-let* ((exec (executable-find "git")))
    102              (ignore-errors
    103                ;; Git for Windows 2.x provides cygpath so we can
    104                ;; ask it for native paths.
    105                (let* ((core-exe
    106                        (car
    107                         (process-lines
    108                          exec "-c"
    109                          "alias.X=!x() { which \"$1\" | cygpath -mf -; }; x"
    110                          "X" "git")))
    111                       (hack-entry (assoc core-exe magit-git-w32-path-hack))
    112                       ;; Running the libexec/git-core executable
    113                       ;; requires some extra PATH entries.
    114                       (path-hack
    115                        (list (concat "PATH="
    116                                      (car (process-lines
    117                                            exec "-c"
    118                                            "alias.P=!cygpath -wp \"$PATH\""
    119                                            "P"))))))
    120                  ;; The defcustom STANDARD expression can be
    121                  ;; evaluated many times, so make sure it is
    122                  ;; idempotent.
    123                  (if hack-entry
    124                      (setcdr hack-entry path-hack)
    125                    (push (cons core-exe path-hack) magit-git-w32-path-hack))
    126                  core-exe))))
    127       (and (eq system-type 'darwin)
    128            (executable-find "git"))
    129       "git")
    130   "The Git executable used by Magit on the local host.
    131 On remote machines `magit-remote-git-executable' is used instead."
    132   :package-version '(magit . "3.2.0")
    133   :group 'magit-process
    134   :type 'string)
    135 
    136 (defcustom magit-remote-git-executable "git"
    137   "The Git executable used by Magit on remote machines.
    138 On the local host `magit-git-executable' is used instead.
    139 Consider customizing `tramp-remote-path' instead of this
    140 option."
    141   :package-version '(magit . "3.2.0")
    142   :group 'magit-process
    143   :type 'string)
    144 
    145 (defcustom magit-git-global-arguments
    146   `("--no-pager" "--literal-pathspecs"
    147     "-c" "core.preloadindex=true"
    148     "-c" "log.showSignature=false"
    149     "-c" "color.ui=false"
    150     "-c" "color.diff=false"
    151     ,@(and (eq system-type 'windows-nt)
    152            (list "-c" "i18n.logOutputEncoding=UTF-8")))
    153   "Global Git arguments.
    154 
    155 The arguments set here are used every time the git executable is
    156 run as a subprocess.  They are placed right after the executable
    157 itself and before the git command - as in `git HERE... COMMAND
    158 REST'.  See the manpage `git(1)' for valid arguments.
    159 
    160 Be careful what you add here, especially if you are using Tramp
    161 to connect to servers with ancient Git versions.  Never remove
    162 anything that is part of the default value, unless you really
    163 know what you are doing.  And think very hard before adding
    164 something; it will be used every time Magit runs Git for any
    165 purpose."
    166   :package-version '(magit . "2.9.0")
    167   :group 'magit-commands
    168   :group 'magit-process
    169   :type '(repeat string))
    170 
    171 (defcustom magit-prefer-remote-upstream nil
    172   "Whether to favor remote branches when reading the upstream branch.
    173 
    174 This controls whether commands that read a branch from the user
    175 and then set it as the upstream branch, offer a local or a remote
    176 branch as default completion candidate, when they have the choice.
    177 
    178 This affects all commands that use `magit-read-upstream-branch'
    179 or `magit-read-starting-point', which includes most commands
    180 that change the upstream and many that create new branches."
    181   :package-version '(magit . "2.4.2")
    182   :group 'magit-commands
    183   :type 'boolean)
    184 
    185 (defcustom magit-list-refs-namespaces
    186   '("refs/heads"
    187     "refs/remotes"
    188     "refs/tags"
    189     "refs/pullreqs")
    190   "List of ref namespaces considered when reading a ref.
    191 
    192 This controls the order of refs returned by `magit-list-refs',
    193 which is called by functions like `magit-list-branch-names' to
    194 generate the collection of refs."
    195   :package-version '(magit . "3.1.0")
    196   :group 'magit-commands
    197   :type '(repeat string))
    198 
    199 (defcustom magit-list-refs-sortby nil
    200   "How to sort the ref collection in the prompt.
    201 
    202 This affects commands that read a ref.  More specifically, it
    203 controls the order of refs returned by `magit-list-refs', which
    204 is called by functions like `magit-list-branch-names' to generate
    205 the collection of refs.  By default, refs are sorted according to
    206 their full refname (i.e., \"refs/...\").
    207 
    208 Any value accepted by the `--sort' flag of \"git for-each-ref\" can
    209 be used.  For example, \"-creatordate\" places refs with more
    210 recent committer or tagger dates earlier in the list.  A list of
    211 strings can also be given in order to pass multiple sort keys to
    212 \"git for-each-ref\".
    213 
    214 Note that, depending on the completion framework you use, this
    215 may not be sufficient to change the order in which the refs are
    216 displayed.  It only controls the order of the collection passed
    217 to `magit-completing-read' or, for commands that support reading
    218 multiple strings, `read-from-minibuffer'.  The completion
    219 framework ultimately determines how the collection is displayed."
    220   :package-version '(magit . "2.11.0")
    221   :group 'magit-miscellaneous
    222   :type '(choice string (repeat string)))
    223 
    224 ;;; Git
    225 
    226 (defvar magit-git-debug nil
    227   "Whether to enable additional reporting of git errors.
    228 
    229 Magit basically calls git for one of these two reasons: for
    230 side-effects or to do something with its standard output.
    231 
    232 When git is run for side-effects then its output, including error
    233 messages, go into the process buffer which is shown when using \
    234 \\<magit-status-mode-map>\\[magit-process-buffer].
    235 
    236 When git's output is consumed in some way, then it would be too
    237 expensive to also insert it into this buffer, but when this
    238 option is non-nil and git returns with a non-zero exit status,
    239 then at least its standard error is inserted into this buffer.
    240 
    241 This is only intended for debugging purposes.  Do not enable this
    242 permanently, that would negatively affect performance.  Also note
    243 that just because git exits with a non-zero exit status and prints
    244 an error message that usually doesn't mean that it is an error as
    245 far as Magit is concerned, which is another reason we usually hide
    246 these error messages.  Whether some error message is relevant in
    247 the context of some unexpected behavior has to be judged on a case
    248 by case basis.
    249 
    250 The command `magit-toggle-git-debug' changes the value of this
    251 variable.
    252 
    253 Also see `magit-process-extreme-logging'.")
    254 
    255 (defun magit-toggle-git-debug ()
    256   "Toggle whether additional git errors are reported.
    257 See info node `(magit)Debugging Tools' for more information."
    258   (interactive)
    259   (setq magit-git-debug (not magit-git-debug))
    260   (message "Additional reporting of Git errors %s"
    261            (if magit-git-debug "enabled" "disabled")))
    262 
    263 (defvar magit--refresh-cache nil)
    264 
    265 (defmacro magit--with-refresh-cache (key &rest body)
    266   (declare (indent 1) (debug (form body)))
    267   (let ((k (cl-gensym))
    268         (hit (cl-gensym)))
    269     `(if magit--refresh-cache
    270          (let ((,k ,key))
    271            (if-let ((,hit (assoc ,k (cdr magit--refresh-cache))))
    272                (progn (cl-incf (caar magit--refresh-cache))
    273                       (cdr ,hit))
    274              (cl-incf (cdar magit--refresh-cache))
    275              (let ((value ,(macroexp-progn body)))
    276                (push (cons ,k value)
    277                      (cdr magit--refresh-cache))
    278                value)))
    279        ,@body)))
    280 
    281 (defvar magit-with-editor-envvar "GIT_EDITOR"
    282   "The environment variable exported by `magit-with-editor'.
    283 Set this to \"GIT_SEQUENCE_EDITOR\" if you do not want to use
    284 Emacs to edit commit messages but would like to do so to edit
    285 rebase sequences.")
    286 
    287 (defmacro magit-with-editor (&rest body)
    288   "Like `with-editor*' but let-bind some more variables.
    289 Also respect the value of `magit-with-editor-envvar'."
    290   (declare (indent 0) (debug (body)))
    291   `(let ((magit-process-popup-time -1)
    292          ;; The user may have customized `shell-file-name' to
    293          ;; something which results in `w32-shell-dos-semantics' nil
    294          ;; (which changes the quoting style used by
    295          ;; `shell-quote-argument'), but Git for Windows expects shell
    296          ;; quoting in the dos style.
    297          (shell-file-name (if (and (eq system-type 'windows-nt)
    298                                    ;; If we have Cygwin mount points,
    299                                    ;; the git flavor is cygwin, so dos
    300                                    ;; shell quoting is probably wrong.
    301                                    (not magit-cygwin-mount-points))
    302                               "cmdproxy"
    303                             shell-file-name)))
    304      (with-editor* magit-with-editor-envvar
    305        ,@body)))
    306 
    307 (defmacro magit--with-temp-process-buffer (&rest body)
    308   "Like `with-temp-buffer', but always propagate `process-environment'.
    309 When that var is buffer-local in the calling buffer, it is not
    310 propagated by `with-temp-buffer', so we explicitly ensure that
    311 happens, so that processes will be invoked consistently.  BODY is
    312 as for that macro."
    313   (declare (indent 0) (debug (body)))
    314   (let ((p (cl-gensym)))
    315     `(let ((,p process-environment))
    316        (with-temp-buffer
    317          (setq-local process-environment ,p)
    318          ,@body))))
    319 
    320 (defsubst magit-git-executable ()
    321   "Return value of `magit-git-executable' or `magit-remote-git-executable'.
    322 The variable is chosen depending on whether `default-directory'
    323 is remote."
    324   (if (file-remote-p default-directory)
    325       magit-remote-git-executable
    326     magit-git-executable))
    327 
    328 (defun magit-process-git-arguments (args)
    329   "Prepare ARGS for a function that invokes Git.
    330 
    331 Magit has many specialized functions for running Git; they all
    332 pass arguments through this function before handing them to Git,
    333 to do the following.
    334 
    335 * Flatten ARGS, removing nil arguments.
    336 * Prepend `magit-git-global-arguments' to ARGS.
    337 * On w32 systems, encode to `w32-ansi-code-page'."
    338   (setq args (append magit-git-global-arguments (flatten-tree args)))
    339   (if (and (eq system-type 'windows-nt) (boundp 'w32-ansi-code-page))
    340       ;; On w32, the process arguments *must* be encoded in the
    341       ;; current code-page (see #3250).
    342       (mapcar (lambda (arg)
    343                 (encode-coding-string
    344                  arg (intern (format "cp%d" w32-ansi-code-page))))
    345               args)
    346     args))
    347 
    348 (defun magit-git-exit-code (&rest args)
    349   "Execute Git with ARGS, returning its exit code."
    350   (magit-process-git nil args))
    351 
    352 (defun magit-git-success (&rest args)
    353   "Execute Git with ARGS, returning t if its exit code is 0."
    354   (= (magit-git-exit-code args) 0))
    355 
    356 (defun magit-git-failure (&rest args)
    357   "Execute Git with ARGS, returning t if its exit code is 1."
    358   (= (magit-git-exit-code args) 1))
    359 
    360 (defun magit-git-string-p (&rest args)
    361   "Execute Git with ARGS, returning the first line of its output.
    362 If the exit code isn't zero or if there is no output, then return
    363 nil.  Neither of these results is considered an error; if that is
    364 what you want, then use `magit-git-string-ng' instead.
    365 
    366 This is an experimental replacement for `magit-git-string', and
    367 still subject to major changes."
    368   (magit--with-refresh-cache (cons default-directory args)
    369     (magit--with-temp-process-buffer
    370       (and (zerop (magit-process-git t args))
    371            (not (bobp))
    372            (progn
    373              (goto-char (point-min))
    374              (buffer-substring-no-properties (point) (line-end-position)))))))
    375 
    376 (defun magit-git-string-ng (&rest args)
    377   "Execute Git with ARGS, returning the first line of its output.
    378 If the exit code isn't zero or if there is no output, then that
    379 is considered an error, but instead of actually signaling an
    380 error, return nil.  Additionally the output is put in the process
    381 buffer (creating it if necessary) and the error message is shown
    382 in the status buffer (provided it exists).
    383 
    384 This is an experimental replacement for `magit-git-string', and
    385 still subject to major changes.  Also see `magit-git-string-p'."
    386   (magit--with-refresh-cache
    387       (list default-directory 'magit-git-string-ng args)
    388     (magit--with-temp-process-buffer
    389       (let* ((args (magit-process-git-arguments args))
    390              (status (magit-process-git t args)))
    391         (if (zerop status)
    392             (and (not (bobp))
    393                  (progn
    394                    (goto-char (point-min))
    395                    (buffer-substring-no-properties
    396                     (point) (line-end-position))))
    397           (let ((buf (current-buffer)))
    398             (with-current-buffer (magit-process-buffer t)
    399               (magit-process-insert-section default-directory
    400                                             magit-git-executable args
    401                                             status buf)))
    402           (when-let ((status-buf (magit-get-mode-buffer 'magit-status-mode)))
    403             (let ((msg (magit--locate-error-message)))
    404               (with-current-buffer status-buf
    405                 (setq magit-this-error msg))))
    406           nil)))))
    407 
    408 (defun magit-git-str (&rest args)
    409   "Execute Git with ARGS, returning the first line of its output.
    410 If there is no output, return nil.  If the output begins with a
    411 newline, return an empty string.  Like `magit-git-string' but
    412 ignore `magit-git-debug'."
    413   (setq args (flatten-tree args))
    414   (magit--with-refresh-cache (cons default-directory args)
    415     (magit--with-temp-process-buffer
    416       (magit-process-git (list t nil) args)
    417       (unless (bobp)
    418         (goto-char (point-min))
    419         (buffer-substring-no-properties (point) (line-end-position))))))
    420 
    421 (defun magit-git-output (&rest args)
    422   "Execute Git with ARGS, returning its output."
    423   (setq args (flatten-tree args))
    424   (magit--with-refresh-cache (cons default-directory args)
    425     (magit--with-temp-process-buffer
    426       (magit-process-git (list t nil) args)
    427       (buffer-substring-no-properties (point-min) (point-max)))))
    428 
    429 (define-error 'magit-invalid-git-boolean "Not a Git boolean")
    430 
    431 (defun magit-git-true (&rest args)
    432   "Execute Git with ARGS, returning t if it prints \"true\".
    433 If it prints \"false\", then return nil.  For any other output
    434 signal `magit-invalid-git-boolean'."
    435   (pcase (magit-git-output args)
    436     ((or "true"  "true\n")  t)
    437     ((or "false" "false\n") nil)
    438     (output (signal 'magit-invalid-git-boolean (list output)))))
    439 
    440 (defun magit-git-false (&rest args)
    441   "Execute Git with ARGS, returning t if it prints \"false\".
    442 If it prints \"true\", then return nil.  For any other output
    443 signal `magit-invalid-git-boolean'."
    444   (pcase (magit-git-output args)
    445     ((or "true"  "true\n")  nil)
    446     ((or "false" "false\n") t)
    447     (output (signal 'magit-invalid-git-boolean (list output)))))
    448 
    449 (defun magit-git-config-p (variable &optional default)
    450   "Return the boolean value of the Git variable VARIABLE.
    451 VARIABLE has to be specified as a string.  Return DEFAULT (which
    452 defaults to nil) if VARIABLE is unset.  If VARIABLE's value isn't
    453 a boolean, then raise an error."
    454   (let ((args (list "config" "--bool" "--default" (if default "true" "false")
    455                     variable)))
    456     (magit--with-refresh-cache (cons default-directory args)
    457       (magit--with-temp-process-buffer
    458         (let ((status (magit-process-git t args))
    459               (output (buffer-substring (point-min) (1- (point-max)))))
    460           (if (zerop status)
    461               (equal output "true")
    462             (signal 'magit-invalid-git-boolean (list output))))))))
    463 
    464 (defun magit-git-insert (&rest args)
    465   "Execute Git with ARGS, inserting its output at point.
    466 If Git exits with a non-zero exit status, then show a message and
    467 add a section in the respective process buffer."
    468   (apply #'magit--git-insert nil args))
    469 
    470 (defun magit--git-insert (return-error &rest args)
    471   (setq args (magit-process-git-arguments args))
    472   (if (or return-error magit-git-debug)
    473       (let (log)
    474         (unwind-protect
    475             (let (exit errmsg)
    476               (setq log (make-temp-file "magit-stderr"))
    477               (delete-file log)
    478               (setq exit (magit-process-git (list t log) args))
    479               (when (> exit 0)
    480                 (when (file-exists-p log)
    481                   (with-temp-buffer
    482                     (insert-file-contents log)
    483                     (goto-char (point-max))
    484                     (setq errmsg
    485                           (if (functionp magit-git-debug)
    486                               (funcall magit-git-debug (buffer-string))
    487                             (magit--locate-error-message))))
    488                   (unless return-error
    489                     (let ((magit-git-debug nil))
    490                       (with-current-buffer (magit-process-buffer t)
    491                         (magit-process-insert-section default-directory
    492                                                       magit-git-executable
    493                                                       args exit log)))))
    494                 (unless return-error
    495                   (if errmsg
    496                       (message "%s" errmsg)
    497                     (message "Git returned with exit-code %s" exit))))
    498               (or errmsg exit))
    499           (ignore-errors (delete-file log))))
    500     (magit-process-git (list t nil) args)))
    501 
    502 (defun magit--locate-error-message ()
    503   (goto-char (point-max))
    504   (and (run-hook-wrapped 'magit-process-error-message-regexps
    505                          (lambda (re) (re-search-backward re nil t)))
    506        (match-string-no-properties 1)))
    507 
    508 (defun magit-git-string (&rest args)
    509   "Execute Git with ARGS, returning the first line of its output.
    510 If there is no output, return nil.  If the output begins with a
    511 newline, return an empty string."
    512   (setq args (flatten-tree args))
    513   (magit--with-refresh-cache (cons default-directory args)
    514     (magit--with-temp-process-buffer
    515       (apply #'magit-git-insert args)
    516       (unless (bobp)
    517         (goto-char (point-min))
    518         (buffer-substring-no-properties (point) (line-end-position))))))
    519 
    520 (defun magit-git-lines (&rest args)
    521   "Execute Git with ARGS, returning its output as a list of lines.
    522 Empty lines anywhere in the output are omitted.
    523 
    524 If Git exits with a non-zero exit status, then report show a
    525 message and add a section in the respective process buffer."
    526   (magit--with-temp-process-buffer
    527     (apply #'magit-git-insert args)
    528     (split-string (buffer-string) "\n" t)))
    529 
    530 (defun magit-git-items (&rest args)
    531   "Execute Git with ARGS, returning its null-separated output as a list.
    532 Empty items anywhere in the output are omitted.
    533 
    534 If Git exits with a non-zero exit status, then report show a
    535 message and add a section in the respective process buffer."
    536   (magit--with-temp-process-buffer
    537     (apply #'magit-git-insert args)
    538     (split-string (buffer-string) "\0" t)))
    539 
    540 (defvar magit--git-wash-keep-error nil) ; experimental
    541 
    542 (defun magit-git-wash (washer &rest args)
    543   "Execute Git with ARGS, inserting washed output at point.
    544 Actually first insert the raw output at point.  If there is no
    545 output, call `magit-cancel-section'.  Otherwise temporarily narrow
    546 the buffer to the inserted text, move to its beginning, and then
    547 call function WASHER with ARGS as its sole argument."
    548   (declare (indent 1))
    549   (apply #'magit--git-wash washer magit--git-wash-keep-error args))
    550 
    551 (defun magit--git-wash (washer keep-error &rest args)
    552   (declare (indent 2))
    553   (setq args (flatten-tree args))
    554   (let ((beg (point))
    555         (exit (magit--git-insert keep-error args)))
    556     (when (stringp exit)
    557       (goto-char beg)
    558       (insert (propertize exit 'face 'error))
    559       (unless (bolp)
    560         (insert "\n")))
    561     (if (= (point) beg)
    562         (magit-cancel-section)
    563       (unless (bolp)
    564         (insert "\n"))
    565       (when (or (equal exit 0)
    566                 (eq keep-error 'wash-anyway))
    567         (save-restriction
    568           (narrow-to-region beg (point))
    569           (goto-char beg)
    570           (funcall washer args))
    571         (when (or (= (point) beg)
    572                   (= (point) (1+ beg)))
    573           (magit-cancel-section))
    574         (magit-maybe-make-margin-overlay)))
    575     exit))
    576 
    577 (defun magit-git-executable-find (command)
    578   "Search for COMMAND in Git's exec path, falling back to `exec-path'.
    579 Like `executable-find', return the absolute file name of the
    580 executable."
    581   (or (locate-file command
    582                    (list (concat
    583                           (file-remote-p default-directory)
    584                           (or (magit-git-string "--exec-path")
    585                               (error "`git --exec-path' failed"))))
    586                    exec-suffixes
    587                    #'file-executable-p)
    588       (compat-call executable-find command t)))
    589 
    590 ;;; Git Version
    591 
    592 (defconst magit--git-version-regexp
    593   "\\`git version \\([0-9]+\\(\\.[0-9]+\\)\\{1,2\\}\\)")
    594 
    595 (defvar magit--host-git-version-cache nil)
    596 
    597 (defun magit-git-version>= (n)
    598   "Return t if `magit-git-version's value is greater than or equal to N."
    599   (magit--version>= (magit-git-version) n))
    600 
    601 (defun magit-git-version< (n)
    602   "Return t if `magit-git-version's value is smaller than N."
    603   (version< (magit-git-version) n))
    604 
    605 (defun magit-git-version ()
    606   "Return the Git version used for `default-directory'.
    607 Raise an error if Git cannot be found, if it exits with a
    608 non-zero status, or the output does not have the expected
    609 format."
    610   (magit--with-refresh-cache default-directory
    611     (let ((host (file-remote-p default-directory)))
    612       (or (cdr (assoc host magit--host-git-version-cache))
    613           (magit--with-temp-process-buffer
    614             ;; Unset global arguments for ancient Git versions.
    615             (let* ((magit-git-global-arguments nil)
    616                    (status (magit-process-git t "version"))
    617                    (output (buffer-string)))
    618               (cond
    619                ((not (zerop status))
    620                 (display-warning
    621                  'magit
    622                  (format "%S\n\nRunning \"%s --version\" failed with output:\n\n%s"
    623                          (if host
    624                              (format "Magit cannot find Git on host %S.\n
    625 Check the value of `magit-remote-git-executable' using
    626 `magit-debug-git-executable' and consult the info node
    627 `(tramp)Remote programs'." host)
    628                            "Magit cannot find Git.\n
    629 Check the values of `magit-git-executable' and `exec-path'
    630 using `magit-debug-git-executable'.")
    631                          (magit-git-executable)
    632                          output)))
    633                ((save-match-data
    634                   (and (string-match magit--git-version-regexp output)
    635                        (let ((version (match-string 1 output)))
    636                          (push (cons host version)
    637                                magit--host-git-version-cache)
    638                          version))))
    639                ((error "Unexpected \"%s --version\" output: %S"
    640                        (magit-git-executable)
    641                        output)))))))))
    642 
    643 (defun magit-git-version-assert (&optional minimal who)
    644   "Assert that the used Git version is greater than or equal to MINIMAL.
    645 If optional MINIMAL is nil, compare with `magit--minimal-git'
    646 instead.  Optional WHO if non-nil specifies what functionality
    647 needs at least MINIMAL, otherwise it defaults to \"Magit\"."
    648   (when (magit-git-version< (or minimal magit--minimal-git))
    649     (let* ((host (file-remote-p default-directory))
    650            (msg (format-spec
    651                  (cond (host "\
    652 %w requires Git %m or greater, but on %h the version is %v.
    653 
    654 If multiple Git versions are installed on the host, then the
    655 problem might be that TRAMP uses the wrong executable.
    656 
    657 Check the value of `magit-remote-git-executable' and consult
    658 the info node `(tramp)Remote programs'.\n")
    659                        (t "\
    660 %w requires Git %m or greater, but you are using %v.
    661 
    662 If you have multiple Git versions installed, then check the
    663 values of `magit-remote-git-executable' and `exec-path'.\n"))
    664                  `((?w . ,(or who "Magit"))
    665                    (?m . ,(or minimal magit--minimal-git))
    666                    (?v . ,(magit-git-version))
    667                    (?h . ,host)))))
    668       (display-warning 'magit msg :error))))
    669 
    670 (defun magit--safe-git-version ()
    671   "Return the Git version used for `default-directory' or an error message."
    672   (magit--with-temp-process-buffer
    673     (let* ((magit-git-global-arguments nil)
    674            (status (magit-process-git t "version"))
    675            (output (buffer-string)))
    676       (cond ((not (zerop status)) output)
    677             ((save-match-data
    678                (and (string-match magit--git-version-regexp output)
    679                     (match-string 1 output))))
    680             (t output)))))
    681 
    682 (defun magit-debug-git-executable ()
    683   "Display a buffer with information about `magit-git-executable'.
    684 Also include information about `magit-remote-git-executable'.
    685 See info node `(magit)Debugging Tools' for more information."
    686   (interactive)
    687   (with-current-buffer (get-buffer-create "*magit-git-debug*")
    688     (pop-to-buffer (current-buffer))
    689     (erase-buffer)
    690     (insert (format "magit-remote-git-executable: %S\n"
    691                     magit-remote-git-executable))
    692     (insert (concat
    693              (format "magit-git-executable: %S" magit-git-executable)
    694              (and (not (file-name-absolute-p magit-git-executable))
    695                   (format " [%S]" (executable-find magit-git-executable)))
    696              (format " (%s)\n" (magit--safe-git-version))))
    697     (insert (format "exec-path: %S\n" exec-path))
    698     (when-let ((diff (cl-set-difference
    699                       (seq-filter #'file-exists-p (remq nil (parse-colon-path
    700                                                              (getenv "PATH"))))
    701                       (seq-filter #'file-exists-p (remq nil exec-path))
    702                       :test #'file-equal-p)))
    703       (insert (format "  entries in PATH, but not in exec-path: %S\n" diff)))
    704     (dolist (execdir exec-path)
    705       (insert (format "  %s (%s)\n" execdir (car (file-attributes execdir))))
    706       (when (file-directory-p execdir)
    707         (dolist (exec (directory-files
    708                        execdir t (concat
    709                                   "\\`git" (regexp-opt exec-suffixes) "\\'")))
    710           (insert (format "    %s (%s)\n" exec
    711                           (magit--safe-git-version))))))))
    712 
    713 ;;; Variables
    714 
    715 (defun magit-config-get-from-cached-list (key)
    716   (gethash
    717    ;; `git config --list' downcases first and last components of the key.
    718    (let* ((key (replace-regexp-in-string "\\`[^.]+" #'downcase key t t))
    719           (key (replace-regexp-in-string "[^.]+\\'" #'downcase key t t)))
    720      key)
    721    (magit--with-refresh-cache (cons (magit-toplevel) 'config)
    722      (let ((configs (make-hash-table :test #'equal)))
    723        (dolist (conf (magit-git-items "config" "--list" "-z"))
    724          (let* ((nl-pos (cl-position ?\n conf))
    725                 (key (substring conf 0 nl-pos))
    726                 (val (if nl-pos (substring conf (1+ nl-pos)) "")))
    727            (puthash key (nconc (gethash key configs) (list val)) configs)))
    728        configs))))
    729 
    730 (defun magit-get (&rest keys)
    731   "Return the value of the Git variable specified by KEYS."
    732   (car (last (apply #'magit-get-all keys))))
    733 
    734 (defun magit-get-all (&rest keys)
    735   "Return all values of the Git variable specified by KEYS."
    736   (let ((magit-git-debug nil)
    737         (arg (and (or (null (car keys))
    738                       (string-prefix-p "--" (car keys)))
    739                   (pop keys)))
    740         (key (string-join keys ".")))
    741     (if (and magit--refresh-cache (not arg))
    742         (magit-config-get-from-cached-list key)
    743       (magit-git-items "config" arg "-z" "--get-all" "--include" key))))
    744 
    745 (defun magit-get-boolean (&rest keys)
    746   "Return the boolean value of the Git variable specified by KEYS.
    747 Also see `magit-git-config-p'."
    748   (let ((arg (and (or (null (car keys))
    749                       (string-prefix-p "--" (car keys)))
    750                   (pop keys)))
    751         (key (string-join keys ".")))
    752     (equal (if magit--refresh-cache
    753                (car (last (magit-config-get-from-cached-list key)))
    754              (magit-git-str "config" arg "--bool" "--include" key))
    755            "true")))
    756 
    757 (defun magit-set (value &rest keys)
    758   "Set the value of the Git variable specified by KEYS to VALUE."
    759   (let ((arg (and (or (null (car keys))
    760                       (string-prefix-p "--" (car keys)))
    761                   (pop keys)))
    762         (key (string-join keys ".")))
    763     (if value
    764         (magit-git-success "config" arg key value)
    765       (magit-git-success "config" arg "--unset" key))
    766     value))
    767 
    768 (gv-define-setter magit-get (val &rest keys)
    769   `(magit-set ,val ,@keys))
    770 
    771 (defun magit-set-all (values &rest keys)
    772   "Set all values of the Git variable specified by KEYS to VALUES."
    773   (let ((arg (and (or (null (car keys))
    774                       (string-prefix-p "--" (car keys)))
    775                   (pop keys)))
    776         (var (string-join keys ".")))
    777     (when (magit-get var)
    778       (magit-call-git "config" arg "--unset-all" var))
    779     (dolist (v values)
    780       (magit-call-git "config" arg "--add" var v))))
    781 
    782 ;;; Files
    783 
    784 (defun magit--safe-default-directory (&optional file)
    785   (catch 'unsafe-default-dir
    786     (let ((dir (file-name-as-directory
    787                 (expand-file-name (or file default-directory))))
    788           (previous nil))
    789       (while (not (file-accessible-directory-p dir))
    790         (setq dir (file-name-directory (directory-file-name dir)))
    791         (when (equal dir previous)
    792           (throw 'unsafe-default-dir nil))
    793         (setq previous dir))
    794       dir)))
    795 
    796 (defmacro magit--with-safe-default-directory (file &rest body)
    797   (declare (indent 1) (debug (form body)))
    798   `(when-let ((default-directory (magit--safe-default-directory ,file)))
    799      ,@body))
    800 
    801 (defun magit-git-dir (&optional path)
    802   "Like (expand-file-name PATH (magit-gitdir)) or just (magit-gitdir)."
    803   (declare (obsolete 'magit-gitdir "Magit 4.0.0"))
    804   (and-let* ((dir (magit-gitdir)))
    805     (if path
    806         (expand-file-name (convert-standard-filename path) dir)
    807       dir)))
    808 
    809 (defun magit-gitdir (&optional directory)
    810   "Return the absolute and resolved path of the .git directory.
    811 
    812 If the `GIT_DIR' environment variable is defined, return that.
    813 Otherwise return the .git directory for DIRECTORY, or if that is
    814 nil, then for `default-directory' instead.  If the directory is
    815 not located inside a Git repository, then return nil."
    816   (let ((default-directory (or directory default-directory)))
    817     (magit--with-refresh-cache (list default-directory 'magit-gitdir)
    818       (magit--with-safe-default-directory nil
    819         (and-let*
    820             ((dir (magit-rev-parse-safe "--git-dir"))
    821              (dir (file-name-as-directory (magit-expand-git-file-name dir))))
    822           (if (file-remote-p dir)
    823               dir
    824             (concat (file-remote-p default-directory) dir)))))))
    825 
    826 (defvar magit--separated-gitdirs nil)
    827 
    828 (defun magit--record-separated-gitdir ()
    829   (let ((topdir (magit-toplevel))
    830         (gitdir (magit-gitdir)))
    831     ;; Kludge: git-annex converts submodule gitdirs to symlinks. See #3599.
    832     (when (file-symlink-p (directory-file-name gitdir))
    833       (setq gitdir (file-truename gitdir)))
    834     ;; We want to delete the entry for `topdir' here, rather than within
    835     ;; (unless ...), in case a `--separate-git-dir' repository was switched to
    836     ;; the standard structure (i.e., "topdir/.git/").
    837     (setq magit--separated-gitdirs (cl-delete topdir
    838                                               magit--separated-gitdirs
    839                                               :key #'car :test #'equal))
    840     (unless (equal (file-name-as-directory (expand-file-name ".git" topdir))
    841                    gitdir)
    842       (push (cons topdir gitdir) magit--separated-gitdirs))))
    843 
    844 (defun magit-toplevel (&optional directory)
    845   "Return the absolute path to the toplevel of the current repository.
    846 
    847 From within the working tree or control directory of a repository
    848 return the absolute path to the toplevel directory of the working
    849 tree.  As a special case, from within a bare repository return
    850 the control directory instead.  When called outside a repository
    851 then return nil.
    852 
    853 When optional DIRECTORY is non-nil then return the toplevel for
    854 that directory instead of the one for `default-directory'.
    855 
    856 Try to respect the option `find-file-visit-truename', i.e.,  when
    857 the value of that option is nil, then avoid needlessly returning
    858 the truename.  When a symlink to a sub-directory of the working
    859 tree is involved, or when called from within a sub-directory of
    860 the gitdir or from the toplevel of a gitdir, which itself is not
    861 located within the working tree, then it is not possible to avoid
    862 returning the truename."
    863   (or
    864    (magit--with-refresh-cache
    865        (cons (or directory default-directory) 'magit-toplevel)
    866      (magit--with-safe-default-directory directory
    867        (if-let ((topdir (magit-rev-parse-safe "--show-toplevel")))
    868            (let (updir)
    869              (setq topdir (magit-expand-git-file-name topdir))
    870              (cond
    871               ((and
    872                 ;; Always honor these settings.
    873                 (not find-file-visit-truename)
    874                 (not (getenv "GIT_WORK_TREE"))
    875                 ;; `--show-cdup' is the relative path to the toplevel
    876                 ;; from `(file-truename default-directory)'.  Here we
    877                 ;; pretend it is relative to `default-directory', and
    878                 ;; go to that directory.  Then we check whether
    879                 ;; `--show-toplevel' still returns the same value and
    880                 ;; whether `--show-cdup' now is the empty string.  If
    881                 ;; both is the case, then we are at the toplevel of
    882                 ;; the same working tree, but also avoided needlessly
    883                 ;; following any symlinks.
    884                 (progn
    885                   (setq updir (file-name-as-directory
    886                                (magit-rev-parse-safe "--show-cdup")))
    887                   (setq updir (if (file-name-absolute-p updir)
    888                                   (concat (file-remote-p default-directory)
    889                                           updir)
    890                                 (expand-file-name updir)))
    891                   (and-let*
    892                       ((default-directory updir)
    893                        (top (and (string-equal
    894                                   (magit-rev-parse-safe "--show-cdup") "")
    895                                  (magit-rev-parse-safe "--show-toplevel"))))
    896                     (string-equal (magit-expand-git-file-name top) topdir))))
    897                updir)
    898               ((concat (file-remote-p default-directory)
    899                        (file-name-as-directory topdir)))))
    900          (and-let* ((gitdir (magit-rev-parse-safe "--git-dir"))
    901                     (gitdir (file-name-as-directory
    902                              (if (file-name-absolute-p gitdir)
    903                                  ;; We might have followed a symlink.
    904                                  (concat (file-remote-p default-directory)
    905                                          (magit-expand-git-file-name gitdir))
    906                                (expand-file-name gitdir)))))
    907            (if (magit-bare-repo-p)
    908                gitdir
    909              (let* ((link (expand-file-name "gitdir" gitdir))
    910                     (wtree (and (file-exists-p link)
    911                                 (magit-file-line link))))
    912                (cond
    913                 ((and wtree
    914                       ;; Ignore .git/gitdir files that result from a
    915                       ;; Git bug.  See #2364.
    916                       (not (equal wtree ".git")))
    917                  ;; Return the linked working tree.
    918                  (concat (file-remote-p default-directory)
    919                          (file-name-directory wtree)))
    920                 ;; The working directory may not be the parent
    921                 ;; directory of .git if it was set up with
    922                 ;; "git init --separate-git-dir".  See #2955.
    923                 ((car (rassoc gitdir magit--separated-gitdirs)))
    924                 (;; Step outside the control directory to enter the
    925                  ;; working tree.
    926                  (file-name-directory (directory-file-name gitdir))))))))))))
    927 
    928 (defun magit--toplevel-safe ()
    929   (or (magit-toplevel)
    930       (magit--not-inside-repository-error)))
    931 
    932 (defmacro magit-with-toplevel (&rest body)
    933   (declare (indent defun) (debug (body)))
    934   `(let ((default-directory (magit--toplevel-safe)))
    935      ,@body))
    936 
    937 (define-error 'magit-outside-git-repo "Not inside Git repository")
    938 (define-error 'magit-corrupt-git-config "Corrupt Git configuration")
    939 (define-error 'magit-git-executable-not-found
    940               (concat "Git executable cannot be found "
    941                       "(see https://magit.vc/goto/e6a78ed2)"))
    942 
    943 (defun magit--assert-usable-git ()
    944   (if (not (compat-call executable-find (magit-git-executable) t))
    945       (signal 'magit-git-executable-not-found (magit-git-executable))
    946     (let ((magit-git-debug
    947            (lambda (err)
    948              (signal 'magit-corrupt-git-config
    949                      (format "%s: %s" default-directory err)))))
    950       ;; This should always succeed unless there's a corrupt config
    951       ;; (or at least a similarly severe failing state).  Note that
    952       ;; git-config's --default is avoided because it's not available
    953       ;; until Git 2.18.
    954       (magit-git-string "config" "--get-color" "" "reset"))
    955     nil))
    956 
    957 (defun magit--not-inside-repository-error ()
    958   (magit--assert-usable-git)
    959   (signal 'magit-outside-git-repo default-directory))
    960 
    961 (defun magit-inside-gitdir-p (&optional noerror)
    962   "Return t if `default-directory' is below the repository directory.
    963 If it is below the working directory, then return nil.
    964 If it isn't below either, then signal an error unless NOERROR
    965 is non-nil, in which case return nil."
    966   (and (magit--assert-default-directory noerror)
    967        ;; Below a repository directory that is not located below the
    968        ;; working directory "git rev-parse --is-inside-git-dir" prints
    969        ;; "false", which is wrong.
    970        (let ((gitdir (magit-gitdir)))
    971          (cond (gitdir (file-in-directory-p default-directory gitdir))
    972                (noerror nil)
    973                ((signal 'magit-outside-git-repo default-directory))))))
    974 
    975 (defun magit-inside-worktree-p (&optional noerror)
    976   "Return t if `default-directory' is below the working directory.
    977 If it is below the repository directory, then return nil.
    978 If it isn't below either, then signal an error unless NOERROR
    979 is non-nil, in which case return nil."
    980   (and (magit--assert-default-directory noerror)
    981        (condition-case nil
    982            (magit-rev-parse-true "--is-inside-work-tree")
    983          (magit-invalid-git-boolean
    984           (and (not noerror)
    985                (signal 'magit-outside-git-repo default-directory))))))
    986 
    987 (cl-defgeneric magit-bare-repo-p (&optional noerror)
    988   "Return t if the current repository is bare.
    989 If it is non-bare, then return nil.  If `default-directory'
    990 isn't below a Git repository, then signal an error unless
    991 NOERROR is non-nil, in which case return nil."
    992   (and (magit--assert-default-directory noerror)
    993        (condition-case nil
    994            (magit-rev-parse-true "--is-bare-repository")
    995          (magit-invalid-git-boolean
    996           (and (not noerror)
    997                (signal 'magit-outside-git-repo default-directory))))))
    998 
    999 (defun magit--assert-default-directory (&optional noerror)
   1000   (or (file-directory-p default-directory)
   1001       (and (not noerror)
   1002            (let ((exists (file-exists-p default-directory)))
   1003              (signal (if exists 'file-error 'file-missing)
   1004                      (list "Running git in directory"
   1005                            (if exists
   1006                                "Not a directory"
   1007                              "No such file or directory")
   1008                            default-directory))))))
   1009 
   1010 (defun magit-git-repo-p (directory &optional non-bare)
   1011   "Return t if DIRECTORY is a Git repository.
   1012 When optional NON-BARE is non-nil also return nil if DIRECTORY is
   1013 a bare repository."
   1014   (and (file-directory-p directory) ; Avoid archives, see #3397.
   1015        (or (file-regular-p (expand-file-name ".git" directory))
   1016            (file-directory-p (expand-file-name ".git" directory))
   1017            (and (not non-bare)
   1018                 (file-regular-p (expand-file-name "HEAD" directory))
   1019                 (file-directory-p (expand-file-name "refs" directory))
   1020                 (file-directory-p (expand-file-name "objects" directory))))))
   1021 
   1022 (defun magit-file-relative-name (&optional file tracked)
   1023   "Return the path of FILE relative to the repository root.
   1024 
   1025 If optional FILE is nil or omitted, return the relative path of
   1026 the file being visited in the current buffer, if any, else nil.
   1027 If the file is not inside a Git repository, then return nil.
   1028 
   1029 If TRACKED is non-nil, return the path only if it matches a
   1030 tracked file."
   1031   (unless file
   1032     (with-current-buffer (or (buffer-base-buffer)
   1033                              (current-buffer))
   1034       (setq file (or magit-buffer-file-name buffer-file-name
   1035                      (and (derived-mode-p 'dired-mode) default-directory)))))
   1036   (when (and file (or (not tracked)
   1037                       (magit-file-tracked-p (file-relative-name file))))
   1038     (and-let* ((dir (magit-toplevel
   1039                      (magit--safe-default-directory
   1040                       (directory-file-name (file-name-directory file))))))
   1041       (file-relative-name file dir))))
   1042 
   1043 (defun magit-file-ignored-p (file)
   1044   (magit-git-string-p "ls-files" "--others" "--ignored" "--exclude-standard"
   1045                       "--" (magit-convert-filename-for-git file)))
   1046 
   1047 (defun magit-file-tracked-p (file)
   1048   (magit-git-success "ls-files" "--error-unmatch"
   1049                      "--" (magit-convert-filename-for-git file)))
   1050 
   1051 (defun magit-list-files (&rest args)
   1052   (apply #'magit-git-items "ls-files" "-z" "--full-name" args))
   1053 
   1054 (defun magit-tracked-files ()
   1055   (magit-list-files "--cached"))
   1056 
   1057 (defun magit-untracked-files (&optional all files compact)
   1058   (if compact
   1059       (--mapcat (and (eq (aref it 0) ??)
   1060                      (list (substring it 3)))
   1061                 (magit-git-items "status" "-z" "--porcelain"
   1062                                  (magit-ignore-submodules-p t)
   1063                                  "--" files))
   1064     (magit-list-files "--other"
   1065                       (and (not all) "--exclude-standard")
   1066                       "--" files)))
   1067 
   1068 (defun magit-modified-files (&optional nomodules files)
   1069   (magit-git-items "diff-index" "-z" "--name-only"
   1070                    ;; Work around a bug in Git v2.46.0. See #5212 and #5221.
   1071                    (if nomodules "--ignore-submodules" "--submodule=short")
   1072                    (magit-headish) "--" files))
   1073 
   1074 (defun magit-unstaged-files (&optional nomodules files)
   1075   (magit-git-items "diff-files" "-z" "--name-only" "--diff-filter=u"
   1076                    ;; Work around a bug in Git v2.46.0. See #5212 and #5221.
   1077                    (if nomodules "--ignore-submodules" "--submodule=short")
   1078                    "--" files))
   1079 
   1080 (defun magit-staged-files (&optional nomodules files)
   1081   (magit-git-items "diff-index" "-z" "--name-only" "--cached"
   1082                    ;; Work around a bug in Git v2.46.0. See #5212 and #5221.
   1083                    (if nomodules "--ignore-submodules" "--submodule=short")
   1084                    (magit-headish) "--" files))
   1085 
   1086 (defun magit-binary-files (&rest args)
   1087   (--mapcat (and (string-match "^-\t-\t\\(.+\\)" it)
   1088                  (list (match-string 1 it)))
   1089             (apply #'magit-git-items
   1090                    "diff" "-z" "--numstat" "--ignore-submodules"
   1091                    args)))
   1092 
   1093 (defun magit-unmerged-files ()
   1094   (magit-git-items "diff-files" "-z" "--name-only" "--diff-filter=U"))
   1095 
   1096 (defun magit-ignored-files ()
   1097   (magit-git-items "ls-files" "-z" "--others" "--ignored"
   1098                    "--exclude-standard" "--directory"))
   1099 
   1100 (defun magit-stashed-files (stash)
   1101   (magit-git-items "stash" "show" "-z" "--name-only" stash))
   1102 
   1103 (defun magit-skip-worktree-files ()
   1104   (--keep (and (= (aref it 0) ?S)
   1105                (substring it 2))
   1106           (magit-list-files "-t")))
   1107 
   1108 (defun magit-assume-unchanged-files ()
   1109   (--keep (and (memq (aref it 0) '(?h ?s ?m ?r ?c ?k))
   1110                (substring it 2))
   1111           (magit-list-files "-v")))
   1112 
   1113 (defun magit-revision-files (rev)
   1114   (magit-with-toplevel
   1115     (magit-git-items "ls-tree" "-z" "-r" "--name-only" rev)))
   1116 
   1117 (defun magit-revision-directories (rev)
   1118   "List directories that contain a tracked file in revision REV."
   1119   (magit-with-toplevel
   1120     (mapcar #'file-name-as-directory
   1121             (magit-git-items "ls-tree" "-z" "-r" "-d" "--name-only" rev))))
   1122 
   1123 (defun magit-changed-files (rev-or-range &optional other-rev)
   1124   "Return list of files the have changed between two revisions.
   1125 If OTHER-REV is non-nil, REV-OR-RANGE should be a revision, not a
   1126 range.  Otherwise, it can be any revision or range accepted by
   1127 \"git diff\" (i.e., <rev>, <revA>..<revB>, or <revA>...<revB>)."
   1128   (magit-with-toplevel
   1129     (magit-git-items "diff" "-z" "--name-only" rev-or-range other-rev)))
   1130 
   1131 (defun magit-renamed-files (revA revB)
   1132   (mapcar (pcase-lambda (`(,_status ,fileA ,fileB))
   1133             (cons fileA fileB))
   1134           (seq-partition (magit-git-items "diff" "-z" "--name-status"
   1135                                           "--find-renames"
   1136                                           "--diff-filter=R" revA revB)
   1137                          3)))
   1138 
   1139 (defun magit--rev-file-name (file rev other-rev)
   1140   "For FILE, potentially renamed between REV and OTHER-REV, return name in REV.
   1141 Return nil, if FILE appears neither in REV nor OTHER-REV,
   1142 or if no rename is detected."
   1143   (or (car (member file (magit-revision-files rev)))
   1144       (and-let* ((renamed (magit-renamed-files rev other-rev)))
   1145         (car (rassoc file renamed)))))
   1146 
   1147 (defun magit-file-status (&rest args)
   1148   (magit--with-temp-process-buffer
   1149     (save-excursion (magit-git-insert "status" "-z" args))
   1150     (let ((pos (point)) status)
   1151       (while (> (skip-chars-forward "[:print:]") 0)
   1152         (let ((x (char-after     pos))
   1153               (y (char-after (1+ pos)))
   1154               (file (buffer-substring (+ pos 3) (point))))
   1155           (forward-char)
   1156           (if (memq x '(?R ?C))
   1157               (progn
   1158                 (setq pos (point))
   1159                 (skip-chars-forward "[:print:]")
   1160                 (push (list file (buffer-substring pos (point)) x y) status)
   1161                 (forward-char))
   1162             (push (list file nil x y) status)))
   1163         (setq pos (point)))
   1164       status)))
   1165 
   1166 (defcustom magit-cygwin-mount-points
   1167   (and (eq system-type 'windows-nt)
   1168        (cl-sort (--map (if (string-match "^\\(.*\\) on \\(.*\\) type" it)
   1169                            (cons (file-name-as-directory (match-string 2 it))
   1170                                  (file-name-as-directory (match-string 1 it)))
   1171                          (lwarn '(magit) :error
   1172                                 "Failed to parse Cygwin mount: %S" it))
   1173                        ;; If --exec-path is not a native Windows path,
   1174                        ;; then we probably have a cygwin git.
   1175                        (let ((process-environment
   1176                               (append magit-git-environment
   1177                                       process-environment)))
   1178                          (and (not (string-match-p
   1179                                     "\\`[a-zA-Z]:"
   1180                                     (car (process-lines
   1181                                           magit-git-executable "--exec-path"))))
   1182                               (ignore-errors (process-lines "mount")))))
   1183                 #'> :key (pcase-lambda (`(,cyg . ,_win)) (length cyg))))
   1184   "Alist of (CYGWIN . WIN32) directory names.
   1185 Sorted from longest to shortest CYGWIN name."
   1186   :package-version '(magit . "2.3.0")
   1187   :group 'magit-process
   1188   :type '(alist :key-type string :value-type directory))
   1189 
   1190 (defun magit-expand-git-file-name (filename)
   1191   (unless (file-name-absolute-p filename)
   1192     (setq filename (expand-file-name filename)))
   1193   (if-let ((cyg:win (and (not (file-remote-p default-directory)) ; see #4976
   1194                          (cl-assoc filename magit-cygwin-mount-points
   1195                                    :test (lambda (f cyg) (string-prefix-p cyg f))))))
   1196       (concat (cdr cyg:win)
   1197               (substring filename (length (car cyg:win))))
   1198     filename))
   1199 
   1200 (defun magit-convert-filename-for-git (filename)
   1201   "Convert FILENAME so that it can be passed to git.
   1202 1. If it is a absolute filename, then pass it through
   1203    `expand-file-name' to replace things such as \"~/\" that
   1204    Git does not understand.
   1205 2. If it is a remote filename, then remove the remote part.
   1206 3. Deal with an `windows-nt' Emacs vs. Cygwin Git incompatibility."
   1207   (if (file-name-absolute-p filename)
   1208       (if-let ((cyg:win (cl-rassoc filename magit-cygwin-mount-points
   1209                                    :test (lambda (f win) (string-prefix-p win f)))))
   1210           (concat (car cyg:win)
   1211                   (substring filename (length (cdr cyg:win))))
   1212         (let ((expanded (expand-file-name filename)))
   1213           (or (file-remote-p expanded 'localname)
   1214               expanded)))
   1215     filename))
   1216 
   1217 (defun magit-decode-git-path (path)
   1218   (if (eq (aref path 0) ?\")
   1219       (decode-coding-string (read path)
   1220                             (or magit-git-output-coding-system
   1221                                 (car default-process-coding-system))
   1222                             t)
   1223     path))
   1224 
   1225 (defun magit-file-at-point (&optional expand assert)
   1226   (if-let ((file (magit-section-case
   1227                    (file (oref it value))
   1228                    (hunk (magit-section-parent-value it)))))
   1229       (if expand
   1230           (expand-file-name file (magit-toplevel))
   1231         file)
   1232     (when assert
   1233       (user-error "No file at point"))))
   1234 
   1235 (defun magit-current-file ()
   1236   (or (magit-file-relative-name)
   1237       (magit-file-at-point)
   1238       (and (derived-mode-p 'magit-log-mode)
   1239            (car magit-buffer-log-files))))
   1240 
   1241 ;;; Predicates
   1242 
   1243 (defun magit-no-commit-p ()
   1244   "Return t if there is no commit in the current Git repository."
   1245   (not (magit-rev-verify "HEAD")))
   1246 
   1247 (defun magit-merge-commit-p (commit)
   1248   "Return t if COMMIT is a merge commit."
   1249   (length> (magit-commit-parents commit) 1))
   1250 
   1251 (defun magit-anything-staged-p (&optional ignore-submodules &rest files)
   1252   "Return t if there are any staged changes.
   1253 If optional FILES is non-nil, then only changes to those files
   1254 are considered."
   1255   (magit-git-failure "diff" "--quiet" "--cached"
   1256                      (if ignore-submodules
   1257                          "--ignore-submodules"
   1258                        ;; Work around a bug in Git v2.46.0. See #5212 and #5221.
   1259                        "--submodule=short")
   1260                      "--" files))
   1261 
   1262 (defun magit-anything-unstaged-p (&optional ignore-submodules &rest files)
   1263   "Return t if there are any unstaged changes.
   1264 If optional FILES is non-nil, then only changes to those files
   1265 are considered."
   1266   (magit-git-failure "diff" "--quiet"
   1267                      (if ignore-submodules
   1268                          "--ignore-submodules"
   1269                        ;; Work around a bug in Git v2.46.0. See #5212 and #5221.
   1270                        "--submodule=short")
   1271                      "--" files))
   1272 
   1273 (defun magit-anything-modified-p (&optional ignore-submodules &rest files)
   1274   "Return t if there are any staged or unstaged changes.
   1275 If optional FILES is non-nil, then only changes to those files
   1276 are considered."
   1277   (or (apply #'magit-anything-staged-p   ignore-submodules files)
   1278       (apply #'magit-anything-unstaged-p ignore-submodules files)))
   1279 
   1280 (defun magit-anything-unmerged-p (&rest files)
   1281   "Return t if there are any merge conflicts.
   1282 If optional FILES is non-nil, then only conflicts in those files
   1283 are considered."
   1284   (and (magit-git-string "ls-files" "--unmerged" files) t))
   1285 
   1286 (defun magit-module-worktree-p (module)
   1287   (magit-with-toplevel
   1288     (file-exists-p (expand-file-name ".git" module))))
   1289 
   1290 (defun magit-module-no-worktree-p (module)
   1291   (not (magit-module-worktree-p module)))
   1292 
   1293 (defun magit-ignore-submodules-p (&optional return-argument)
   1294   (or (cl-find-if (lambda (arg)
   1295                     (string-prefix-p "--ignore-submodules" arg))
   1296                   magit-buffer-diff-args)
   1297       (and-let* ((value (magit-get "diff.ignoreSubmodules")))
   1298         (if return-argument
   1299             (concat "--ignore-submodules=" value)
   1300           (concat "diff.ignoreSubmodules=" value)))))
   1301 
   1302 ;;; Revisions and References
   1303 
   1304 (defun magit-rev-parse (&rest args)
   1305   "Execute `git rev-parse ARGS', returning first line of output.
   1306 If there is no output, return nil."
   1307   (apply #'magit-git-string "rev-parse" args))
   1308 
   1309 (defun magit-rev-parse-safe (&rest args)
   1310   "Execute `git rev-parse ARGS', returning first line of output.
   1311 If there is no output, return nil.  Like `magit-rev-parse' but
   1312 ignore `magit-git-debug'."
   1313   (apply #'magit-git-str "rev-parse" args))
   1314 
   1315 (defun magit-rev-parse-true (&rest args)
   1316   "Execute `git rev-parse ARGS', returning t if it prints \"true\".
   1317 If it prints \"false\", then return nil.  For any other output
   1318 signal an error."
   1319   (magit-git-true "rev-parse" args))
   1320 
   1321 (defun magit-rev-parse-false (&rest args)
   1322   "Execute `git rev-parse ARGS', returning t if it prints \"false\".
   1323 If it prints \"true\", then return nil.  For any other output
   1324 signal an error."
   1325   (magit-git-false "rev-parse" args))
   1326 
   1327 (defun magit-rev-parse-p (&rest args)
   1328   "Execute `git rev-parse ARGS', returning t if it prints \"true\".
   1329 Return t if the first (and usually only) output line is the
   1330 string \"true\", otherwise return nil."
   1331   (equal (magit-git-str "rev-parse" args) "true"))
   1332 
   1333 (defun magit-rev-verify (rev)
   1334   (magit-git-string-p "rev-parse" "--verify" rev))
   1335 
   1336 (defun magit-commit-p (rev)
   1337   "Return full hash for REV if it names an existing commit."
   1338   (magit-rev-verify (magit--rev-dereference rev)))
   1339 
   1340 (defalias 'magit-rev-verify-commit #'magit-commit-p)
   1341 
   1342 (defalias 'magit-rev-hash #'magit-commit-p)
   1343 
   1344 (defun magit--rev-dereference (rev)
   1345   "Return a rev that forces Git to interpret REV as a commit.
   1346 If REV is nil or has the form \":/TEXT\", return REV itself."
   1347   (cond ((not rev) nil)
   1348         ((string-match-p "^:/" rev) rev)
   1349         ((concat rev "^{commit}"))))
   1350 
   1351 (defun magit-rev-equal (a b)
   1352   "Return t if there are no differences between the commits A and B."
   1353   (magit-git-success "diff" "--quiet" a b))
   1354 
   1355 (defun magit-rev-eq (a b)
   1356   "Return t if A and B refer to the same commit."
   1357   (let ((a (magit-commit-p a))
   1358         (b (magit-commit-p b)))
   1359     (and a b (equal a b))))
   1360 
   1361 (defun magit-rev-ancestor-p (a b)
   1362   "Return non-nil if commit A is an ancestor of commit B."
   1363   (magit-git-success "merge-base" "--is-ancestor" a b))
   1364 
   1365 (defun magit-rev-head-p (rev)
   1366   (or (equal rev "HEAD")
   1367       (and rev
   1368            (not (string-search ".." rev))
   1369            (equal (magit-rev-parse rev)
   1370                   (magit-rev-parse "HEAD")))))
   1371 
   1372 (defun magit-rev-author-p (rev)
   1373   "Return t if the user is the author of REV.
   1374 More precisely return t if `user.name' is equal to the author
   1375 name of REV and/or `user.email' is equal to the author email
   1376 of REV."
   1377   (or (equal (magit-get "user.name")  (magit-rev-format "%an" rev))
   1378       (equal (magit-get "user.email") (magit-rev-format "%ae" rev))))
   1379 
   1380 (defun magit-rev-name (rev &optional pattern not-anchored)
   1381   "Return a symbolic name for REV using `git-name-rev'.
   1382 
   1383 PATTERN can be used to limit the result to a matching ref.
   1384 Unless NOT-ANCHORED is non-nil, the beginning of the ref must
   1385 match PATTERN.
   1386 
   1387 An anchored lookup is done using the arguments
   1388 \"--exclude=*/<PATTERN> --exclude=*/HEAD\" in addition to
   1389 \"--refs=<PATTERN>\", provided at least version v2.13 of Git is
   1390 used.  Older versions did not support the \"--exclude\" argument.
   1391 When \"--exclude\" cannot be used and `git-name-rev' returns a
   1392 ref that should have been excluded, then that is discarded and
   1393 this function returns nil instead.  This is unfortunate because
   1394 there might be other refs that do match.  To fix that, update
   1395 Git."
   1396   (if (magit-git-version< "2.13")
   1397       (and-let*
   1398           ((ref (magit-git-string "name-rev" "--name-only" "--no-undefined"
   1399                                   (and pattern (concat "--refs=" pattern))
   1400                                   rev)))
   1401         (if (and pattern
   1402                  (string-match-p "\\`refs/[^/]+/\\*\\'" pattern))
   1403             (let ((namespace (substring pattern 0 -1)))
   1404               (and (not (or (string-suffix-p "HEAD" ref)
   1405                             (and (string-match-p namespace ref)
   1406                                  (not (magit-rev-verify
   1407                                        (concat namespace ref))))))
   1408                    ref))
   1409           ref))
   1410     (magit-git-string "name-rev" "--name-only" "--no-undefined"
   1411                       (and pattern (concat "--refs=" pattern))
   1412                       (and pattern
   1413                            (not not-anchored)
   1414                            (list "--exclude=*/HEAD"
   1415                                  (concat "--exclude=*/" pattern)))
   1416                       rev)))
   1417 
   1418 (defun magit-rev-branch (rev)
   1419   (and-let* ((name (magit-rev-name rev "refs/heads/*")))
   1420     (and (not (string-match-p "[~^]" name)) name)))
   1421 
   1422 (defun magit-rev-fixup-target (rev)
   1423   (let ((msg (magit-rev-format "%s" rev)))
   1424     (save-match-data
   1425       (and (string-match "\\`\\(fixup\\|squash\\)! \\(.+\\)" msg)
   1426            (magit-rev-format
   1427             "%h" (format "%s^{/^%s}" rev
   1428                          (magit--ext-regexp-quote (match-string 2 msg))))))))
   1429 
   1430 (defun magit-get-shortname (rev)
   1431   (let* ((fn (apply-partially #'magit-rev-name rev))
   1432          (name (or (funcall fn "refs/tags/*")
   1433                    (funcall fn "refs/heads/*")
   1434                    (funcall fn "refs/remotes/*"))))
   1435     (cond ((not name)
   1436            (magit-rev-parse "--short" rev))
   1437           ((string-match "^\\(?:tags\\|remotes\\)/\\(.+\\)" name)
   1438            (if (magit-ref-ambiguous-p (match-string 1 name))
   1439                name
   1440              (match-string 1 name)))
   1441           ((magit-ref-maybe-qualify name)))))
   1442 
   1443 (defun magit-name-branch (rev &optional lax)
   1444   (or (magit-name-local-branch rev)
   1445       (magit-name-remote-branch rev)
   1446       (and lax (or (magit-name-local-branch rev t)
   1447                    (magit-name-remote-branch rev t)))))
   1448 
   1449 (defun magit-name-local-branch (rev &optional lax)
   1450   (and-let* ((name (magit-rev-name rev "refs/heads/*")))
   1451     (and (or lax (not (string-match-p "[~^]" name))) name)))
   1452 
   1453 (defun magit-name-remote-branch (rev &optional lax)
   1454   (and-let* ((name (magit-rev-name rev "refs/remotes/*")))
   1455     (and (or lax (not (string-match-p "[~^]" name)))
   1456          (substring name 8))))
   1457 
   1458 (defun magit-name-tag (rev &optional lax)
   1459   (and-let* ((name (magit-rev-name rev "refs/tags/*")))
   1460     ;; The progn is necessary to work around debbugs#31840.  This, and all
   1461     ;; the other instances, can be removed once we require at least Emacs 27.
   1462     (progn
   1463       (when (string-suffix-p "^0" name)
   1464         (setq name (substring name 0 -2)))
   1465       (and (or lax (not (string-match-p "[~^]" name)))
   1466            (substring name 5)))))
   1467 
   1468 (defun magit-ref-abbrev (refname)
   1469   "Return an unambiguous abbreviation of REFNAME."
   1470   (magit-rev-parse "--verify" "--abbrev-ref" refname))
   1471 
   1472 (defun magit-ref-fullname (refname)
   1473   "Return fully qualified refname for REFNAME.
   1474 If REFNAME is ambiguous, return nil."
   1475   (magit-rev-parse "--verify" "--symbolic-full-name" refname))
   1476 
   1477 (defun magit-ref-ambiguous-p (refname)
   1478   (save-match-data
   1479     (if (string-match "\\`\\([^^~]+\\)\\(.*\\)" refname)
   1480         (not (magit-ref-fullname (match-string 1 refname)))
   1481       (error "%S has an unrecognized format" refname))))
   1482 
   1483 (defun magit-ref-maybe-qualify (refname &optional prefix)
   1484   "If REFNAME is ambiguous, try to disambiguate it by prepend PREFIX to it.
   1485 Return an unambiguous refname, either REFNAME or that prefixed
   1486 with PREFIX, nil otherwise.  If REFNAME has an offset suffix
   1487 such as \"~1\", then that is preserved.  If optional PREFIX is
   1488 nil, then use \"heads/\".  "
   1489   (if (magit-ref-ambiguous-p refname)
   1490       (let ((refname (concat (or prefix "heads/") refname)))
   1491         (and (not (magit-ref-ambiguous-p refname)) refname))
   1492     refname))
   1493 
   1494 (defun magit-ref-exists-p (ref)
   1495   (magit-git-success "show-ref" "--verify" ref))
   1496 
   1497 (defun magit-ref-equal (a b)
   1498   "Return t if the refnames A and B are `equal'.
   1499 A symbolic-ref pointing to some ref, is `equal' to that ref,
   1500 as are two symbolic-refs pointing to the same ref.  Refnames
   1501 may be abbreviated."
   1502   (let ((a (magit-ref-fullname a))
   1503         (b (magit-ref-fullname b)))
   1504     (and a b (equal a b))))
   1505 
   1506 (defun magit-ref-eq (a b)
   1507   "Return t if the refnames A and B are `eq'.
   1508 A symbolic-ref is `eq' to itself, but not to the ref it points
   1509 to, or to some other symbolic-ref that points to the same ref."
   1510   (let ((symbolic-a (magit-symbolic-ref-p a))
   1511         (symbolic-b (magit-symbolic-ref-p b)))
   1512     (or (and symbolic-a
   1513              symbolic-b
   1514              (equal a b))
   1515         (and (not symbolic-a)
   1516              (not symbolic-b)
   1517              (magit-ref-equal a b)))))
   1518 
   1519 (defun magit-headish ()
   1520   "Return the `HEAD' or if that doesn't exist the hash of the empty tree."
   1521   (if (magit-no-commit-p)
   1522       (magit-git-string "mktree")
   1523     "HEAD"))
   1524 
   1525 (defun magit-branch-at-point ()
   1526   (magit-section-case
   1527     (branch (oref it value))
   1528     (commit (or (magit--painted-branch-at-point)
   1529                 (magit-name-branch (oref it value))))))
   1530 
   1531 (defun magit--painted-branch-at-point (&optional type)
   1532   (or (and (not (eq type 'remote))
   1533            (memq (get-text-property (magit-point) 'font-lock-face)
   1534                  (list 'magit-branch-local
   1535                        'magit-branch-current))
   1536            (and-let* ((branch (magit-thing-at-point 'git-revision t)))
   1537              (cdr (magit-split-branch-name branch))))
   1538       (and (not (eq type 'local))
   1539            (memq (get-text-property (magit-point) 'font-lock-face)
   1540                  (list 'magit-branch-remote
   1541                        'magit-branch-remote-head))
   1542            (thing-at-point 'git-revision t))))
   1543 
   1544 (defun magit-local-branch-at-point ()
   1545   (magit-section-case
   1546     (branch (let ((branch (magit-ref-maybe-qualify (oref it value))))
   1547               (when (member branch (magit-list-local-branch-names))
   1548                 branch)))
   1549     (commit (or (magit--painted-branch-at-point 'local)
   1550                 (magit-name-local-branch (oref it value))))))
   1551 
   1552 (defun magit-remote-branch-at-point ()
   1553   (magit-section-case
   1554     (branch (let ((branch (oref it value)))
   1555               (when (member branch (magit-list-remote-branch-names))
   1556                 branch)))
   1557     (commit (or (magit--painted-branch-at-point 'remote)
   1558                 (magit-name-remote-branch (oref it value))))))
   1559 
   1560 (defun magit-commit-at-point ()
   1561   (or (magit-section-value-if 'commit)
   1562       (magit-thing-at-point 'git-revision t)
   1563       (and-let* ((chunk (and (bound-and-true-p magit-blame-mode)
   1564                              (fboundp 'magit-current-blame-chunk)
   1565                              (magit-current-blame-chunk))))
   1566         (oref chunk orig-rev))
   1567       (and (derived-mode-p 'magit-stash-mode
   1568                            'magit-merge-preview-mode
   1569                            'magit-revision-mode)
   1570            magit-buffer-revision)))
   1571 
   1572 (defun magit-branch-or-commit-at-point ()
   1573   (or (magit-section-case
   1574         (branch (magit-ref-maybe-qualify (oref it value)))
   1575         (commit (or (magit--painted-branch-at-point)
   1576                     (let ((rev (oref it value)))
   1577                       (or (magit-name-branch rev) rev))))
   1578         (tag (magit-ref-maybe-qualify (oref it value) "tags/"))
   1579         (pullreq (or (and (fboundp 'forge--pullreq-branch)
   1580                           (magit-branch-p
   1581                            (forge--pullreq-branch (oref it value))))
   1582                      (magit-ref-p (format "refs/pullreqs/%s"
   1583                                           (oref (oref it value) number)))))
   1584         ((unpulled unpushed)
   1585          (magit-ref-abbrev
   1586           (replace-regexp-in-string "\\.\\.\\.?" "" (oref it value)))))
   1587       (magit-thing-at-point 'git-revision t)
   1588       (and-let* ((chunk (and (bound-and-true-p magit-blame-mode)
   1589                              (fboundp 'magit-current-blame-chunk)
   1590                              (magit-current-blame-chunk))))
   1591         (oref chunk orig-rev))
   1592       (and magit-buffer-file-name
   1593            magit-buffer-refname)
   1594       (and (derived-mode-p 'magit-stash-mode
   1595                            'magit-merge-preview-mode
   1596                            'magit-revision-mode)
   1597            magit-buffer-revision)))
   1598 
   1599 (defun magit-tag-at-point ()
   1600   (magit-section-case
   1601     (tag    (oref it value))
   1602     (commit (magit-name-tag (oref it value)))))
   1603 
   1604 (defun magit-stash-at-point ()
   1605   (magit-section-value-if 'stash))
   1606 
   1607 (defun magit-remote-at-point ()
   1608   (magit-section-case
   1609     (remote (oref it value))
   1610     ([branch remote] (magit-section-parent-value it))))
   1611 
   1612 (defun magit-module-at-point (&optional predicate)
   1613   (when (magit-section-match 'module)
   1614     (let ((module (oref (magit-current-section) value)))
   1615       (and (or (not predicate)
   1616                (funcall predicate module))
   1617            module))))
   1618 
   1619 (defun magit-get-current-branch ()
   1620   "Return the refname of the currently checked out branch.
   1621 Return nil if no branch is currently checked out."
   1622   (magit-git-string "symbolic-ref" "--short" "HEAD"))
   1623 
   1624 (defvar magit-get-previous-branch-timeout 0.5
   1625   "Maximum time to spend in `magit-get-previous-branch'.
   1626 Given as a number of seconds.")
   1627 
   1628 (defun magit-get-previous-branch ()
   1629   "Return the refname of the previously checked out branch.
   1630 Return nil if no branch can be found in the `HEAD' reflog
   1631 which is different from the current branch and still exists.
   1632 The amount of time spent searching is limited by
   1633 `magit-get-previous-branch-timeout'."
   1634   (let ((t0 (float-time))
   1635         (current (magit-get-current-branch))
   1636         (i 1) prev)
   1637     (while (if (> (- (float-time) t0) magit-get-previous-branch-timeout)
   1638                (setq prev nil) ;; Timed out.
   1639              (and (setq prev (magit-rev-verify (format "@{-%d}" i)))
   1640                   (or (not (setq prev (magit-rev-branch prev)))
   1641                       (equal prev current))))
   1642       (cl-incf i))
   1643     prev))
   1644 
   1645 (defun magit--set-default-branch (newname oldname)
   1646   (let ((remote (or (magit-primary-remote)
   1647                     (user-error "Cannot determine primary remote")))
   1648         (branches (mapcar (lambda (line) (split-string line "\t"))
   1649                           (magit-git-lines
   1650                            "for-each-ref" "refs/heads"
   1651                            "--format=%(refname:short)\t%(upstream:short)"))))
   1652     (when-let ((old (assoc oldname branches)))
   1653       (unless (assoc newname branches)
   1654         (magit-call-git "branch" "-m" oldname newname)
   1655         (setcar old newname)))
   1656     (let ((new (if (magit-branch-p newname)
   1657                    newname
   1658                  (concat remote "/" newname))))
   1659       (pcase-dolist (`(,branch ,upstream) branches)
   1660         (cond
   1661          ((equal upstream oldname)
   1662           (magit-set-upstream-branch branch new))
   1663          ((equal upstream (concat remote "/" oldname))
   1664           (magit-set-upstream-branch branch (concat remote "/" newname))))))))
   1665 
   1666 (defun magit--get-default-branch (&optional update)
   1667   (let ((remote (magit-primary-remote)))
   1668     (when update
   1669       (if (not remote)
   1670           (user-error "Cannot determine primary remote")
   1671         (message "Determining default branch...")
   1672         (magit-git "fetch" "--prune")
   1673         (magit-git "remote" "set-head" "--auto" remote)
   1674         (message "Determining default branch...done")))
   1675     (let ((branch (magit-git-string "symbolic-ref" "--short"
   1676                                     (format "refs/remotes/%s/HEAD" remote))))
   1677       (when (and update (not branch))
   1678         (error "Cannot determine new default branch"))
   1679       (list remote (and branch (cdr (magit-split-branch-name branch)))))))
   1680 
   1681 (defun magit-set-upstream-branch (branch upstream)
   1682   "Set UPSTREAM as the upstream of BRANCH.
   1683 If UPSTREAM is nil, then unset BRANCH's upstream.
   1684 Otherwise UPSTREAM has to be an existing branch."
   1685   (if upstream
   1686       (magit-call-git "branch" "--set-upstream-to" upstream branch)
   1687     (magit-call-git "branch" "--unset-upstream" branch)))
   1688 
   1689 (defun magit-get-upstream-ref (&optional branch)
   1690   "Return the upstream branch of BRANCH as a fully qualified ref.
   1691 It BRANCH is nil, then return the upstream of the current branch,
   1692 if any, nil otherwise.  If the upstream is not configured, the
   1693 configured remote is an url, or the named branch does not exist,
   1694 then return nil.  I.e.,  return an existing local or
   1695 remote-tracking branch ref."
   1696   (and-let* ((branch (or branch (magit-get-current-branch))))
   1697     (magit-ref-fullname (concat branch "@{upstream}"))))
   1698 
   1699 (defun magit-get-upstream-branch (&optional branch)
   1700   "Return the name of the upstream branch of BRANCH.
   1701 It BRANCH is nil, then return the upstream of the current branch
   1702 if any, nil otherwise.  If the upstream is not configured, the
   1703 configured remote is an url, or the named branch does not exist,
   1704 then return nil.  I.e., return the name of an existing local or
   1705 remote-tracking branch.  The returned string is colorized
   1706 according to the branch type."
   1707   (magit--with-refresh-cache
   1708       (list default-directory 'magit-get-upstream-branch branch)
   1709     (and-let* ((branch (or branch (magit-get-current-branch)))
   1710                (upstream (magit-ref-abbrev (concat branch "@{upstream}"))))
   1711       (magit--propertize-face
   1712        upstream (if (equal (magit-get "branch" branch "remote") ".")
   1713                     'magit-branch-local
   1714                   'magit-branch-remote)))))
   1715 
   1716 (defun magit-get-indirect-upstream-branch (branch &optional force)
   1717   (let ((remote (magit-get "branch" branch "remote")))
   1718     (and remote (not (equal remote "."))
   1719          ;; The user has opted in...
   1720          (or force
   1721              (--some (if (magit-git-success "check-ref-format" "--branch" it)
   1722                          (equal it branch)
   1723                        (string-match-p it branch))
   1724                      magit-branch-prefer-remote-upstream))
   1725          ;; and local BRANCH tracks a remote branch...
   1726          (let ((upstream (magit-get-upstream-branch branch)))
   1727            ;; whose upstream...
   1728            (and upstream
   1729                 ;; has the same name as BRANCH...
   1730                 (equal (substring upstream (1+ (length remote))) branch)
   1731                 ;; and can be fast-forwarded to BRANCH.
   1732                 (magit-rev-ancestor-p upstream branch)
   1733                 upstream)))))
   1734 
   1735 (defun magit-get-upstream-remote (&optional branch allow-unnamed)
   1736   (and-let* ((branch (or branch (magit-get-current-branch)))
   1737              (remote (magit-get "branch" branch "remote")))
   1738     (and (not (equal remote "."))
   1739          (cond ((member remote (magit-list-remotes))
   1740                 (magit--propertize-face remote 'magit-branch-remote))
   1741                ((and allow-unnamed
   1742                      (string-match-p "\\(\\`.\\{0,2\\}/\\|[:@]\\)" remote))
   1743                 (magit--propertize-face remote 'bold))))))
   1744 
   1745 (defun magit-get-unnamed-upstream (&optional branch)
   1746   (and-let* ((branch (or branch (magit-get-current-branch)))
   1747              (remote (magit-get "branch" branch "remote"))
   1748              (merge  (magit-get "branch" branch "merge")))
   1749     (and (magit--unnamed-upstream-p remote merge)
   1750          (list (magit--propertize-face remote 'bold)
   1751                (magit--propertize-face merge 'magit-branch-remote)))))
   1752 
   1753 (defun magit--unnamed-upstream-p (remote merge)
   1754   (and remote (string-match-p "\\(\\`\\.\\{0,2\\}/\\|[:@]\\)" remote)
   1755        merge  (string-prefix-p "refs/" merge)))
   1756 
   1757 (defun magit--valid-upstream-p (remote merge)
   1758   (and (or (equal remote ".")
   1759            (member remote (magit-list-remotes)))
   1760        (string-prefix-p "refs/" merge)))
   1761 
   1762 (defun magit-get-current-remote (&optional allow-unnamed)
   1763   (or (magit-get-upstream-remote nil allow-unnamed)
   1764       (and-let* ((remotes (magit-list-remotes))
   1765                  (remote (if (length= remotes 1)
   1766                              (car remotes)
   1767                            (magit-primary-remote))))
   1768         (magit--propertize-face remote 'magit-branch-remote))))
   1769 
   1770 (defun magit-get-push-remote (&optional branch)
   1771   (and-let* ((remote
   1772               (or (and (or branch (setq branch (magit-get-current-branch)))
   1773                        (magit-get "branch" branch "pushRemote"))
   1774                   (magit-get "remote.pushDefault"))))
   1775     (magit--propertize-face remote 'magit-branch-remote)))
   1776 
   1777 (defun magit-get-push-branch (&optional branch verify)
   1778   (magit--with-refresh-cache
   1779       (list default-directory 'magit-get-push-branch branch verify)
   1780     (and-let* ((branch (or branch (setq branch (magit-get-current-branch))))
   1781                (remote (magit-get-push-remote branch))
   1782                (target (concat remote "/" branch)))
   1783       (and (or (not verify)
   1784                (magit-rev-verify target))
   1785            (magit--propertize-face target 'magit-branch-remote)))))
   1786 
   1787 (defun magit-get-@{push}-branch (&optional branch)
   1788   (let ((ref (magit-rev-parse "--symbolic-full-name"
   1789                               (concat branch "@{push}"))))
   1790     (and ref
   1791          (string-prefix-p "refs/remotes/" ref)
   1792          (substring ref 13))))
   1793 
   1794 (defun magit-get-remote (&optional branch)
   1795   (and (or branch (setq branch (magit-get-current-branch)))
   1796        (let ((remote (magit-get "branch" branch "remote")))
   1797          (and (not (equal remote "."))
   1798               remote))))
   1799 
   1800 (defun magit-get-some-remote (&optional branch)
   1801   (or (magit-get-remote branch)
   1802       (and-let* ((main (magit-main-branch)))
   1803         (magit-get-remote main))
   1804       (magit-primary-remote)
   1805       (car (magit-list-remotes))))
   1806 
   1807 (defvar magit-primary-remote-names
   1808   '("upstream" "origin"))
   1809 
   1810 (defun magit-primary-remote ()
   1811   "Return the primary remote.
   1812 
   1813 The primary remote is the remote that tracks the repository that
   1814 other repositories are forked from.  It often is called \"origin\"
   1815 but because many people name their own fork \"origin\", using that
   1816 term would be ambiguous.  Likewise we avoid the term \"upstream\"
   1817 because a branch's @{upstream} branch may be a local branch or a
   1818 branch from a remote other than the primary remote.
   1819 
   1820 If a remote exists whose name matches `magit.primaryRemote', then
   1821 that is considered the primary remote.  If no remote by that name
   1822 exists, then remotes in `magit-primary-remote-names' are tried in
   1823 order and the first remote from that list that actually exists in
   1824 the current repository is considered its primary remote."
   1825   (let ((remotes (magit-list-remotes)))
   1826     (seq-find (lambda (name)
   1827                 (member name remotes))
   1828               (delete-dups
   1829                (delq nil
   1830                      (cons (magit-get "magit.primaryRemote")
   1831                            magit-primary-remote-names))))))
   1832 
   1833 (defun magit-branch-merged-p (branch &optional target)
   1834   "Return non-nil if BRANCH is merged into its upstream and TARGET.
   1835 
   1836 TARGET defaults to the current branch.  If `HEAD' is detached and
   1837 TARGET is nil, then always return nil.  As a special case, if
   1838 TARGET is t, then return non-nil if BRANCH is merged into any one
   1839 of the other local branches.
   1840 
   1841 If, and only if, BRANCH has an upstream, then only return non-nil
   1842 if BRANCH is merged into both TARGET (as described above) as well
   1843 as into its upstream."
   1844   (and (if-let ((upstream (and (magit-branch-p branch)
   1845                                (magit-get-upstream-branch branch))))
   1846            (magit-rev-ancestor-p branch upstream)
   1847          t)
   1848        (if (eq target t)
   1849            (delete (magit-name-local-branch branch)
   1850                    (magit-list-containing-branches branch))
   1851          (and-let* ((target (or target (magit-get-current-branch))))
   1852            (magit-rev-ancestor-p branch target)))))
   1853 
   1854 (defun magit-get-tracked (refname)
   1855   "Return the remote branch tracked by the remote-tracking branch REFNAME.
   1856 The returned value has the form (REMOTE . REF), where REMOTE is
   1857 the name of a remote and REF is the ref local to the remote."
   1858   (and-let* ((ref (magit-ref-fullname refname)))
   1859     (save-match-data
   1860       (seq-some (lambda (line)
   1861                   (and (string-match "\
   1862 \\`remote\\.\\([^.]+\\)\\.fetch=\\+?\\([^:]+\\):\\(.+\\)" line)
   1863                        (let ((rmt (match-string 1 line))
   1864                              (src (match-string 2 line))
   1865                              (dst (match-string 3 line)))
   1866                          (and (string-match (format "\\`%s\\'"
   1867                                                     (string-replace
   1868                                                      "*" "\\(.+\\)" dst))
   1869                                             ref)
   1870                               (cons rmt (string-replace
   1871                                          "*" (match-string 1 ref) src))))))
   1872                 (magit-git-lines "config" "--local" "--list")))))
   1873 
   1874 (defun magit-split-branch-name (branch)
   1875   (cond ((member branch (magit-list-local-branch-names))
   1876          (cons "." branch))
   1877         ((string-match "/" branch)
   1878          (or (seq-some (lambda (remote)
   1879                          (and (string-match
   1880                                (format "\\`\\(%s\\)/\\(.+\\)\\'" remote)
   1881                                branch)
   1882                               (cons (match-string 1 branch)
   1883                                     (match-string 2 branch))))
   1884                        (magit-list-remotes))
   1885              (error "Invalid branch name %s" branch)))))
   1886 
   1887 (defun magit-get-current-tag (&optional rev with-distance)
   1888   "Return the closest tag reachable from REV.
   1889 
   1890 If optional REV is nil, then default to `HEAD'.
   1891 If optional WITH-DISTANCE is non-nil then return (TAG COMMITS),
   1892 if it is `dirty' return (TAG COMMIT DIRTY). COMMITS is the number
   1893 of commits in `HEAD' but not in TAG and DIRTY is t if there are
   1894 uncommitted changes, nil otherwise."
   1895   (and-let* ((str (magit-git-str "describe" "--long" "--tags"
   1896                                  (and (eq with-distance 'dirty) "--dirty")
   1897                                  rev)))
   1898     (save-match-data
   1899       (string-match
   1900        "\\(.+\\)-\\(?:0[0-9]*\\|\\([0-9]+\\)\\)-g[0-9a-z]+\\(-dirty\\)?$" str)
   1901       (if with-distance
   1902           `(,(match-string 1 str)
   1903             ,(string-to-number (or (match-string 2 str) "0"))
   1904             ,@(and (match-string 3 str) (list t)))
   1905         (match-string 1 str)))))
   1906 
   1907 (defun magit-get-next-tag (&optional rev with-distance)
   1908   "Return the closest tag from which REV is reachable.
   1909 
   1910 If optional REV is nil, then default to `HEAD'.
   1911 If no such tag can be found or if the distance is 0 (in which
   1912 case it is the current tag, not the next), return nil instead.
   1913 If optional WITH-DISTANCE is non-nil, then return (TAG COMMITS)
   1914 where COMMITS is the number of commits in TAG but not in REV."
   1915   (and-let* ((str (magit-git-str "describe" "--contains" (or rev "HEAD"))))
   1916     (save-match-data
   1917       (when (string-match "^[^^~]+" str)
   1918         (setq str (match-string 0 str))
   1919         (unless (equal str (magit-get-current-tag rev))
   1920           (if with-distance
   1921               (list str (car (magit-rev-diff-count str rev)))
   1922             str))))))
   1923 
   1924 (defun magit-list-refs (&optional namespaces format sortby)
   1925   "Return list of references, excluding symbolic references.
   1926 
   1927 When NAMESPACES is non-nil, list refs from these namespaces
   1928 rather than those from `magit-list-refs-namespaces'.
   1929 
   1930 FORMAT is passed to the `--format' flag of `git for-each-ref'
   1931 and defaults to \"%(refname)\".
   1932 
   1933 SORTBY is a key or list of keys to pass to the `--sort' flag of
   1934 `git for-each-ref'.  When nil, use `magit-list-refs-sortby'"
   1935   (unless format
   1936     (setq format "%(refname)"))
   1937   (seq-keep (lambda (line)
   1938               (pcase-let* ((`(,symrefp ,value)
   1939                             (split-string line ""))
   1940                            (symrefp (not (equal symrefp ""))))
   1941                 (and (not symrefp) value)))
   1942             (magit-git-lines "for-each-ref"
   1943                              (concat "--format=%(symref)" format)
   1944                              (--map (concat "--sort=" it)
   1945                                     (pcase (or sortby magit-list-refs-sortby)
   1946                                       ((and val (pred stringp)) (list val))
   1947                                       ((and val (pred listp)) val)))
   1948                              (or namespaces magit-list-refs-namespaces))))
   1949 
   1950 (defun magit-list-branches ()
   1951   (magit-list-refs (list "refs/heads" "refs/remotes")))
   1952 
   1953 (defun magit-list-local-branches ()
   1954   (magit-list-refs "refs/heads"))
   1955 
   1956 (defun magit-list-remote-branches (&optional remote)
   1957   (magit-list-refs (concat "refs/remotes/" remote)))
   1958 
   1959 (defun magit-list-related-branches (relation &optional commit &rest args)
   1960   (--remove (string-match-p "\\(\\`(HEAD\\|HEAD -> \\)" it)
   1961             (--map (substring it 2)
   1962                    (magit-git-lines "branch" args relation commit))))
   1963 
   1964 (defun magit-list-containing-branches (&optional commit &rest args)
   1965   (magit-list-related-branches "--contains" commit args))
   1966 
   1967 (defun magit-list-publishing-branches (&optional commit)
   1968   (--filter (magit-rev-ancestor-p (or commit "HEAD") it)
   1969             magit-published-branches))
   1970 
   1971 (defun magit-list-merged-branches (&optional commit &rest args)
   1972   (magit-list-related-branches "--merged" commit args))
   1973 
   1974 (defun magit-list-unmerged-branches (&optional commit &rest args)
   1975   (magit-list-related-branches "--no-merged" commit args))
   1976 
   1977 (defun magit-list-unmerged-to-upstream-branches ()
   1978   (--filter (and-let* ((upstream (magit-get-upstream-branch it)))
   1979               (member it (magit-list-unmerged-branches upstream)))
   1980             (magit-list-local-branch-names)))
   1981 
   1982 (defun magit-list-branches-pointing-at (commit)
   1983   (let ((re (format "\\`%s refs/\\(heads\\|remotes\\)/\\(.*\\)\\'"
   1984                     (magit-rev-verify commit))))
   1985     (--keep (and (string-match re it)
   1986                  (let ((name (match-string 2 it)))
   1987                    (and (not (string-suffix-p "HEAD" name))
   1988                         name)))
   1989             (magit-git-lines "show-ref"))))
   1990 
   1991 (defun magit-list-refnames (&optional namespaces include-special)
   1992   (nconc (magit-list-refs namespaces "%(refname:short)")
   1993          (and include-special
   1994               (magit-list-special-refnames))))
   1995 
   1996 (defvar magit-special-refnames
   1997   '("HEAD" "ORIG_HEAD" "FETCH_HEAD" "MERGE_HEAD" "CHERRY_PICK_HEAD"))
   1998 
   1999 (defun magit-list-special-refnames ()
   2000   (let ((gitdir (magit-gitdir)))
   2001     (cl-mapcan (lambda (name)
   2002                  (and (file-exists-p (expand-file-name name gitdir))
   2003                       (list name)))
   2004                magit-special-refnames)))
   2005 
   2006 (defun magit-list-branch-names ()
   2007   (magit-list-refnames (list "refs/heads" "refs/remotes")))
   2008 
   2009 (defun magit-list-local-branch-names ()
   2010   (magit-list-refnames "refs/heads"))
   2011 
   2012 (defun magit-list-remote-branch-names (&optional remote relative)
   2013   (if (and remote relative)
   2014       (let ((regexp (format "^refs/remotes/%s/\\(.+\\)" remote)))
   2015         (--mapcat (when (string-match regexp it)
   2016                     (list (match-string 1 it)))
   2017                   (magit-list-remote-branches remote)))
   2018     (magit-list-refnames (concat "refs/remotes/" remote))))
   2019 
   2020 (defun magit-format-refs (format &rest args)
   2021   (let ((lines (magit-git-lines
   2022                 "for-each-ref" (concat "--format=" format)
   2023                 (or args (list "refs/heads" "refs/remotes" "refs/tags")))))
   2024     (if (string-search "\f" format)
   2025         (--map (split-string it "\f") lines)
   2026       lines)))
   2027 
   2028 (defun magit-list-remotes ()
   2029   (magit-git-lines "remote"))
   2030 
   2031 (defun magit-list-tags ()
   2032   (magit-git-lines "tag"))
   2033 
   2034 (defun magit-list-stashes (&optional format)
   2035   (magit-git-lines "stash" "list" (concat "--format=" (or format "%gd"))))
   2036 
   2037 (defun magit-list-active-notes-refs ()
   2038   "Return notes refs according to `core.notesRef' and `notes.displayRef'."
   2039   (magit-git-lines "for-each-ref" "--format=%(refname)"
   2040                    (or (magit-get "core.notesRef") "refs/notes/commits")
   2041                    (magit-get-all "notes.displayRef")))
   2042 
   2043 (defun magit-list-notes-refnames ()
   2044   (--map (substring it 6) (magit-list-refnames "refs/notes")))
   2045 
   2046 (defun magit-remote-list-tags (remote)
   2047   (--keep (and (not (string-suffix-p "^{}" it))
   2048                (substring it 51))
   2049           (magit-git-lines "ls-remote" "--tags" remote)))
   2050 
   2051 (defun magit-remote-list-branches (remote)
   2052   (--keep (and (not (string-suffix-p "^{}" it))
   2053                (substring it 52))
   2054           (magit-git-lines "ls-remote" "--heads" remote)))
   2055 
   2056 (defun magit-remote-list-refs (remote)
   2057   (--keep (and (not (string-suffix-p "^{}" it))
   2058                (substring it 41))
   2059           (magit-git-lines "ls-remote" remote)))
   2060 
   2061 (defun magit-remote-head (remote)
   2062   (and-let* ((line (cl-find-if
   2063                     (lambda (line)
   2064                       (string-match
   2065                        "\\`ref: refs/heads/\\([^\s\t]+\\)[\s\t]HEAD\\'" line))
   2066                     (magit-git-lines "ls-remote" "--symref" remote "HEAD"))))
   2067     (match-string 1 line)))
   2068 
   2069 (defun magit-list-modified-modules ()
   2070   (--keep (and (string-match "\\`\\+\\([^ ]+\\) \\(.+\\) (.+)\\'" it)
   2071                (match-string 2 it))
   2072           (magit-git-lines "submodule" "status")))
   2073 
   2074 (defun magit-list-module-paths ()
   2075   (magit-with-toplevel
   2076     (--mapcat (and (string-match "^160000 [0-9a-z]\\{40,\\} 0\t\\(.+\\)$" it)
   2077                    (list (match-string 1 it)))
   2078               (magit-git-items "ls-files" "-z" "--stage"))))
   2079 
   2080 (defun magit-list-module-names ()
   2081   (mapcar #'magit-get-submodule-name (magit-list-module-paths)))
   2082 
   2083 (defun magit-get-submodule-name (path)
   2084   "Return the name of the submodule at PATH.
   2085 PATH has to be relative to the super-repository."
   2086   (if (magit-git-version>= "2.38.0")
   2087       ;; "git submodule--helper name" was removed,
   2088       ;; but might still come back in another form.
   2089       (substring
   2090        (car (split-string
   2091              (car (or (magit-git-items
   2092                        "config" "-z"
   2093                        "-f" (expand-file-name ".gitmodules" (magit-toplevel))
   2094                        "--get-regexp" "^submodule\\..*\\.path$"
   2095                        (concat "^" (regexp-quote (directory-file-name path)) "$"))
   2096                       (error "No such submodule `%s'" path)))
   2097              "\n"))
   2098        10 -5)
   2099     (magit-git-string "submodule--helper" "name" path)))
   2100 
   2101 (defun magit-list-worktrees ()
   2102   "Return list of the worktrees of this repository.
   2103 
   2104 The returned list has the form (PATH COMMIT BRANCH BARE DETACHED
   2105 LOCKED PRUNABLE).  The last four elements are booleans, with the
   2106 exception of LOCKED and PRUNABLE, which may also be strings.
   2107 See git-worktree(1) manpage for the meaning of the various parts.
   2108 
   2109 This function corrects a situation where \"git worktree list\"
   2110 would claim a worktree is bare, even though the working tree is
   2111 specified using `core.worktree'."
   2112   (let ((remote (file-remote-p default-directory))
   2113         worktrees worktree)
   2114     (dolist (line (let ((magit-git-global-arguments
   2115                          ;; KLUDGE At least in Git v2.8.3 this argument
   2116                          ;; would trigger a segfault.
   2117                          (remove "--no-pager" magit-git-global-arguments)))
   2118                     (if (magit-git-version>= "2.36")
   2119                         (magit-git-items "worktree" "list" "--porcelain" "-z")
   2120                       (magit-git-lines "worktree" "list" "--porcelain"))))
   2121       (cond ((string-prefix-p "worktree" line)
   2122              (let ((path (substring line 9)))
   2123                (when remote
   2124                  (setq path (concat remote path)))
   2125                ;; If the git directory is separate from the main
   2126                ;; worktree, then "git worktree" returns the git
   2127                ;; directory instead of the worktree, which isn't
   2128                ;; what it is supposed to do and not what we want.
   2129                ;; However, if the worktree has been removed, then
   2130                ;; we want to return it anyway; instead of nil.
   2131                (setq path (or (magit-toplevel path) path))
   2132                (setq worktree (list path nil nil nil nil nil nil))
   2133                (push worktree worktrees)))
   2134             ((string-prefix-p "HEAD" line)
   2135              (setf (nth 1 worktree) (substring line 5)))
   2136             ((string-prefix-p "branch" line)
   2137              (setf (nth 2 worktree) (substring line 18)))
   2138             ((string-equal line "bare")
   2139              (let* ((default-directory (car worktree))
   2140                     (wt (and (not (magit-get-boolean "core.bare"))
   2141                              (magit-get "core.worktree"))))
   2142                (if (and wt (file-exists-p (expand-file-name wt)))
   2143                    (progn (setf (nth 0 worktree) (expand-file-name wt))
   2144                           (setf (nth 2 worktree) (magit-rev-parse "HEAD"))
   2145                           (setf (nth 3 worktree) (magit-get-current-branch)))
   2146                  (setf (nth 3 worktree) t))))
   2147             ((string-equal line "detached")
   2148              (setf (nth 4 worktree) t))
   2149             ((string-prefix-p line "locked")
   2150              (setf (nth 5 worktree)
   2151                    (if (> (length line) 6) (substring line 7) t)))
   2152             ((string-prefix-p line "prunable")
   2153              (setf (nth 6 worktree)
   2154                    (if (> (length line) 8) (substring line 9) t)))))
   2155     (nreverse worktrees)))
   2156 
   2157 (defun magit-symbolic-ref-p (name)
   2158   (magit-git-success "symbolic-ref" "--quiet" name))
   2159 
   2160 (defun magit-ref-p (rev)
   2161   (or (car (member rev (magit-list-refs "refs/")))
   2162       (car (member rev (magit-list-refnames "refs/")))))
   2163 
   2164 (defun magit-branch-p (rev)
   2165   (or (car (member rev (magit-list-branches)))
   2166       (car (member rev (magit-list-branch-names)))))
   2167 
   2168 (defun magit-local-branch-p (rev)
   2169   (or (car (member rev (magit-list-local-branches)))
   2170       (car (member rev (magit-list-local-branch-names)))))
   2171 
   2172 (defun magit-remote-branch-p (rev)
   2173   (or (car (member rev (magit-list-remote-branches)))
   2174       (car (member rev (magit-list-remote-branch-names)))))
   2175 
   2176 (defun magit-branch-set-face (branch)
   2177   (magit--propertize-face branch (if (magit-local-branch-p branch)
   2178                                      'magit-branch-local
   2179                                    'magit-branch-remote)))
   2180 
   2181 (defun magit-tag-p (rev)
   2182   (car (member rev (magit-list-tags))))
   2183 
   2184 (defun magit-remote-p (string)
   2185   (car (member string (magit-list-remotes))))
   2186 
   2187 (defvar magit-main-branch-names
   2188   '("main" "master" "trunk" "development")
   2189   "Branch names reserved for use by the primary branch.
   2190 Use function `magit-main-branch' to get the name actually used in
   2191 the current repository.")
   2192 
   2193 (defvar magit-long-lived-branches
   2194   (append magit-main-branch-names (list "maint" "next"))
   2195   "Branch names reserved for use by long lived branches.")
   2196 
   2197 (defun magit-main-branch ()
   2198   "Return the main branch.
   2199 
   2200 If a branch exists whose name matches `init.defaultBranch', then
   2201 that is considered the main branch.  If no branch by that name
   2202 exists, then the branch names in `magit-main-branch-names' are
   2203 tried in order.  The first branch from that list that actually
   2204 exists in the current repository is considered its main branch."
   2205   (let ((branches (magit-list-local-branch-names)))
   2206     (seq-find (lambda (name)
   2207                 (member name branches))
   2208               (delete-dups
   2209                (delq nil
   2210                      (cons (magit-get "init.defaultBranch")
   2211                            magit-main-branch-names))))))
   2212 
   2213 (defun magit-rev-diff-count (a b &optional first-parent)
   2214   "Return the commits in A but not B and vice versa.
   2215 Return a list of two integers: (A>B B>A).
   2216 
   2217 If `first-parent' is set, traverse only first parents."
   2218   (mapcar #'string-to-number
   2219           (split-string (magit-git-string "rev-list"
   2220                                           "--count" "--left-right"
   2221                                           (and first-parent "--first-parent")
   2222                                           (concat a "..." b))
   2223                         "\t")))
   2224 
   2225 (defun magit-abbrev-length ()
   2226   (let ((abbrev (magit-get "core.abbrev")))
   2227     (if (and abbrev (not (equal abbrev "auto")))
   2228         (string-to-number abbrev)
   2229       ;; Guess the length git will be using based on an example
   2230       ;; abbreviation.  Actually HEAD's abbreviation might be an
   2231       ;; outlier, so use the shorter of the abbreviations for two
   2232       ;; commits.  See #3034.
   2233       (if-let ((head (magit-rev-parse "--short" "HEAD"))
   2234                (head-len (length head)))
   2235           (min head-len
   2236                (if-let ((rev (magit-rev-parse "--short" "HEAD~")))
   2237                    (length rev)
   2238                  head-len))
   2239         ;; We're on an unborn branch, but perhaps the repository has
   2240         ;; other commits.  See #4123.
   2241         (if-let ((commits (magit-git-lines "rev-list" "-n2" "--all"
   2242                                            "--abbrev-commit")))
   2243             (apply #'min (mapcar #'length commits))
   2244           ;; A commit does not exist.  Fall back to the default of 7.
   2245           7)))))
   2246 
   2247 (defun magit-abbrev-arg (&optional arg)
   2248   (format "--%s=%d" (or arg "abbrev") (magit-abbrev-length)))
   2249 
   2250 (defun magit-rev-abbrev (rev)
   2251   (magit-rev-parse (magit-abbrev-arg "short") rev))
   2252 
   2253 (defun magit-commit-children (commit &optional args)
   2254   (mapcar #'car
   2255           (--filter (member commit (cdr it))
   2256                     (--map (split-string it " ")
   2257                            (magit-git-lines
   2258                             "log" "--format=%H %P"
   2259                             (or args (list "--branches" "--tags" "--remotes"))
   2260                             "--not" commit)))))
   2261 
   2262 (defun magit-commit-parents (commit)
   2263   (and-let* ((str (magit-git-string "rev-list" "-1" "--parents" commit)))
   2264     (cdr (split-string str))))
   2265 
   2266 (defun magit-patch-id (rev)
   2267   (magit--with-connection-local-variables
   2268     (magit--with-temp-process-buffer
   2269       (magit-process-file
   2270        shell-file-name nil '(t nil) nil shell-command-switch
   2271        (let ((exec (shell-quote-argument (magit-git-executable))))
   2272          (format "%s diff-tree -u %s | %s patch-id" exec rev exec)))
   2273       (car (split-string (buffer-string))))))
   2274 
   2275 (defun magit-rev-format (format &optional rev args)
   2276   ;; Prefer `git log --no-walk' to `git show --no-patch' because it
   2277   ;; performs better in some scenarios.
   2278   (let ((str (magit-git-string "log" "--no-walk"
   2279                                (concat "--format=" format) args
   2280                                (if rev (magit--rev-dereference rev) "HEAD")
   2281                                "--")))
   2282     (and (not (string-equal str ""))
   2283          str)))
   2284 
   2285 (defun magit-rev-insert-format (format &optional rev args)
   2286   ;; Prefer `git log --no-walk' to `git show --no-patch' because it
   2287   ;; performs better in some scenarios.
   2288   (magit-git-insert "log" "--no-walk"
   2289                     (concat "--format=" format) args
   2290                     (if rev (magit--rev-dereference rev) "HEAD")
   2291                     "--"))
   2292 
   2293 (defun magit-format-rev-summary (rev)
   2294   (and-let* ((str (magit-rev-format "%h %s" rev)))
   2295     (progn
   2296       (magit--put-face 0 (string-match " " str) 'magit-hash str)
   2297       str)))
   2298 
   2299 (defvar magit-ref-namespaces
   2300   '(("\\`HEAD\\'"                  . magit-head)
   2301     ("\\`refs/tags/\\(.+\\)"       . magit-tag)
   2302     ("\\`refs/heads/\\(.+\\)"      . magit-branch-local)
   2303     ("\\`refs/remotes/\\(.+\\)"    . magit-branch-remote)
   2304     ("\\`refs/bisect/\\(bad\\)"    . magit-bisect-bad)
   2305     ("\\`refs/bisect/\\(skip.*\\)" . magit-bisect-skip)
   2306     ("\\`refs/bisect/\\(good.*\\)" . magit-bisect-good)
   2307     ("\\`refs/stash$"              . magit-refname-stash)
   2308     ("\\`refs/wip/\\(.+\\)"        . magit-refname-wip)
   2309     ("\\`refs/pullreqs/\\(.+\\)"   . magit-refname-pullreq)
   2310     ("\\`\\(bad\\):"               . magit-bisect-bad)
   2311     ("\\`\\(skip\\):"              . magit-bisect-skip)
   2312     ("\\`\\(good\\):"              . magit-bisect-good)
   2313     ("\\`\\(.+\\)"                 . magit-refname))
   2314   "How refs are formatted for display.
   2315 
   2316 Each entry controls how a certain type of ref is displayed, and
   2317 has the form (REGEXP . FACE).  REGEXP is a regular expression
   2318 used to match full refs.  The first entry whose REGEXP matches
   2319 the reference is used.
   2320 
   2321 In log and revision buffers the first regexp submatch becomes the
   2322 \"label\" that represents the ref and is propertized with FONT.
   2323 In refs buffers the displayed text is controlled by other means
   2324 and this option only controls what face is used.")
   2325 
   2326 (defun magit-format-ref-labels (string)
   2327   (save-match-data
   2328     (let ((regexp "\\(, \\|tag: \\|HEAD -> \\)")
   2329           names)
   2330       (if (and (derived-mode-p 'magit-log-mode)
   2331                (member "--simplify-by-decoration" magit-buffer-log-args))
   2332           (let ((branches (magit-list-local-branch-names))
   2333                 (re (format "^%s/.+" (regexp-opt (magit-list-remotes)))))
   2334             (setq names
   2335                   (--map (cond ((string-equal it "HEAD")     it)
   2336                                ((string-prefix-p "refs/" it) it)
   2337                                ((member it branches) (concat "refs/heads/" it))
   2338                                ((string-match re it) (concat "refs/remotes/" it))
   2339                                (t                    (concat "refs/" it)))
   2340                          (split-string
   2341                           (string-replace "tag: " "refs/tags/" string)
   2342                           regexp t))))
   2343         (setq names (split-string string regexp t)))
   2344       (let (state head upstream tags branches remotes other combined)
   2345         (dolist (ref names)
   2346           (let* ((face (cdr (--first (string-match (car it) ref)
   2347                                      magit-ref-namespaces)))
   2348                  (name (magit--propertize-face
   2349                         (or (match-string 1 ref) ref) face)))
   2350             (cl-case face
   2351               ((magit-bisect-bad magit-bisect-skip magit-bisect-good)
   2352                (setq state name))
   2353               (magit-head
   2354                (setq head (magit--propertize-face "@" 'magit-head)))
   2355               (magit-tag            (push name tags))
   2356               (magit-branch-local   (push name branches))
   2357               (magit-branch-remote  (push name remotes))
   2358               (t                    (push name other)))))
   2359         (setq remotes
   2360               (seq-keep
   2361                (lambda (name)
   2362                  (if (string-match "\\`\\([^/]*\\)/\\(.*\\)\\'" name)
   2363                      (let ((r (match-string 1 name))
   2364                            (b (match-string 2 name)))
   2365                        (and (not (equal b "HEAD"))
   2366                             (if (equal (concat "refs/remotes/" name)
   2367                                        (magit-git-string
   2368                                         "symbolic-ref"
   2369                                         (format "refs/remotes/%s/HEAD" r)))
   2370                                 (magit--propertize-face
   2371                                  name 'magit-branch-remote-head)
   2372                               name)))
   2373                    name))
   2374                remotes))
   2375         (let* ((current (magit-get-current-branch))
   2376                (target  (magit-get-upstream-branch current)))
   2377           (dolist (name branches)
   2378             (let ((push (car (member (magit-get-push-branch name) remotes))))
   2379               (when push
   2380                 (setq remotes (delete push remotes))
   2381                 (string-match "^[^/]*/" push)
   2382                 (setq push (substring push 0 (match-end 0))))
   2383               (cond
   2384                ((equal name current)
   2385                 (setq head
   2386                       (concat push
   2387                               (magit--propertize-face
   2388                                name 'magit-branch-current))))
   2389                ((equal name target)
   2390                 (setq upstream
   2391                       (concat push
   2392                               (magit--propertize-face
   2393                                name '(magit-branch-upstream
   2394                                       magit-branch-local)))))
   2395                (t
   2396                 (push (concat push name) combined)))))
   2397           (when (and target (not upstream))
   2398             (if (member target remotes)
   2399                 (progn
   2400                   (magit--add-face-text-property
   2401                    0 (length target) 'magit-branch-upstream nil target)
   2402                   (setq upstream target)
   2403                   (setq remotes  (delete target remotes)))
   2404               (when-let ((target (car (member target combined))))
   2405                 (magit--add-face-text-property
   2406                  0 (length target) 'magit-branch-upstream nil target)
   2407                 (setq upstream target)
   2408                 (setq combined (delete target combined))))))
   2409         (string-join (flatten-tree `(,state
   2410                                      ,head
   2411                                      ,upstream
   2412                                      ,@(nreverse tags)
   2413                                      ,@(nreverse combined)
   2414                                      ,@(nreverse remotes)
   2415                                      ,@other))
   2416                      " ")))))
   2417 
   2418 (defun magit-object-type (object)
   2419   (magit-git-string "cat-file" "-t" object))
   2420 
   2421 (defmacro magit-with-blob (commit file &rest body)
   2422   (declare (indent 2)
   2423            (debug (form form body)))
   2424   `(magit--with-temp-process-buffer
   2425      (let ((buffer-file-name ,file))
   2426        (save-excursion
   2427          (magit-git-insert "cat-file" "-p"
   2428                            (concat ,commit ":" buffer-file-name)))
   2429        (decode-coding-inserted-region
   2430         (point-min) (point-max) buffer-file-name t nil nil t)
   2431        ,@body)))
   2432 
   2433 (defmacro magit-with-temp-index (tree arg &rest body)
   2434   (declare (indent 2) (debug (form form body)))
   2435   (let ((file (cl-gensym "file")))
   2436     `(let ((magit--refresh-cache nil)
   2437            (,file (magit-convert-filename-for-git
   2438                    (make-temp-name
   2439                     (expand-file-name "index.magit." (magit-gitdir))))))
   2440        (unwind-protect
   2441            (magit-with-toplevel
   2442              (when-let ((tree ,tree))
   2443                (unless (magit-git-success "read-tree" ,arg tree
   2444                                           (concat "--index-output=" ,file))
   2445                  (error "Cannot read tree %s" tree)))
   2446              (with-environment-variables (("GIT_INDEX_FILE" ,file))
   2447                ,@body))
   2448          (ignore-errors
   2449            (delete-file (concat (file-remote-p default-directory) ,file)))))))
   2450 
   2451 (defun magit-commit-tree (message &optional tree &rest parents)
   2452   (magit-git-string "commit-tree" "--no-gpg-sign" "-m" message
   2453                     (--mapcat (list "-p" it) (delq nil parents))
   2454                     (or tree
   2455                         (magit-git-string "write-tree")
   2456                         (error "Cannot write tree"))))
   2457 
   2458 (defun magit-commit-worktree (message &optional arg &rest other-parents)
   2459   (magit-with-temp-index "HEAD" arg
   2460     (and (magit-update-files (magit-unstaged-files))
   2461          (apply #'magit-commit-tree message nil "HEAD" other-parents))))
   2462 
   2463 (defun magit-update-files (files)
   2464   (magit-git-success "update-index" "--add" "--remove" "--" files))
   2465 
   2466 (defun magit-update-ref (ref message rev &optional stashish)
   2467   (let ((magit--refresh-cache nil))
   2468     (or (if (magit-git-version>= "2.6.0")
   2469             (zerop (magit-call-git "update-ref" "--create-reflog"
   2470                                    "-m" message ref rev
   2471                                    (or (magit-rev-verify ref) "")))
   2472           ;; `--create-reflog' didn't exist before v2.6.0
   2473           (let ((oldrev  (magit-rev-verify ref))
   2474                 (logfile (expand-file-name (concat "logs/" ref)
   2475                                            (magit-gitdir))))
   2476             (unless (file-exists-p logfile)
   2477               (when oldrev
   2478                 (magit-git-success "update-ref" "-d" ref oldrev))
   2479               (make-directory (file-name-directory logfile) t)
   2480               (with-temp-file logfile)
   2481               (when (and oldrev (not stashish))
   2482                 (magit-git-success "update-ref" "-m" "enable reflog"
   2483                                    ref oldrev ""))))
   2484           (magit-git-success "update-ref" "-m" message ref rev
   2485                              (or (magit-rev-verify ref) "")))
   2486         (error "Cannot update %s with %s" ref rev))))
   2487 
   2488 (defconst magit-range-re
   2489   (concat "\\`\\([^ \t]*[^.]\\)?"       ; revA
   2490           "\\(\\.\\.\\.?\\)"            ; range marker
   2491           "\\([^.][^ \t]*\\)?\\'"))     ; revB
   2492 
   2493 (defun magit-split-range (range)
   2494   (pcase-let ((`(,beg ,end ,sep) (magit--split-range-raw range)))
   2495     (and sep
   2496          (let ((beg (or beg "HEAD"))
   2497                (end (or end "HEAD")))
   2498            (if (string-equal (match-string 2 range) "...")
   2499                (and-let* ((base (magit-git-string "merge-base" beg end)))
   2500                  (cons base end))
   2501              (cons beg end))))))
   2502 
   2503 (defun magit--split-range-raw (range)
   2504   (and (string-match magit-range-re range)
   2505        (let ((beg (match-string 1 range))
   2506              (end (match-string 3 range)))
   2507          (and (or beg end)
   2508               (list beg end (match-string 2 range))))))
   2509 
   2510 (defun magit-hash-range (range)
   2511   (if (string-match magit-range-re range)
   2512       (let ((beg (match-string 1 range))
   2513             (end (match-string 3 range)))
   2514         (and (or beg end)
   2515              (let ((beg-hash (and beg (magit-rev-hash (match-string 1 range))))
   2516                    (end-hash (and end (magit-rev-hash (match-string 3 range)))))
   2517                (and (or (not beg) beg-hash)
   2518                     (or (not end) end-hash)
   2519                     (concat beg-hash (match-string 2 range) end-hash)))))
   2520     (magit-rev-hash range)))
   2521 
   2522 (defvar magit-revision-faces
   2523   '(magit-hash
   2524     magit-tag
   2525     magit-branch-remote
   2526     magit-branch-remote-head
   2527     magit-branch-local
   2528     magit-branch-current
   2529     magit-branch-upstream
   2530     magit-branch-warning
   2531     magit-head
   2532     magit-refname
   2533     magit-refname-stash
   2534     magit-refname-wip
   2535     magit-refname-pullreq))
   2536 
   2537 (put 'git-revision 'thing-at-point #'magit-thingatpt--git-revision)
   2538 (defun magit-thingatpt--git-revision (&optional disallow)
   2539   ;; Support hashes and references.
   2540   (and-let* ((bounds
   2541               (let ((c (concat "\s\n\t~^:?*[\\" disallow)))
   2542                 (cl-letf
   2543                     (((get 'git-revision 'beginning-op)
   2544                       (lambda ()
   2545                         (if (re-search-backward (format "[%s]" c) nil t)
   2546                             (forward-char)
   2547                           (goto-char (point-min)))))
   2548                      ((get 'git-revision 'end-op)
   2549                       (lambda ()
   2550                         (re-search-forward (format "\\=[^%s]*" c) nil t))))
   2551                   (bounds-of-thing-at-point 'git-revision))))
   2552              (string (buffer-substring-no-properties (car bounds) (cdr bounds)))
   2553              ;; References are allowed to contain most parentheses and
   2554              ;; most punctuation, but if those characters appear at the
   2555              ;; edges of a possible reference in arbitrary text, then
   2556              ;; they are much more likely to be intended as just that:
   2557              ;; punctuation and delimiters.
   2558              (string (thread-first string
   2559                        (string-trim-left  "[(</]")
   2560                        (string-trim-right "[])>/.,;!]"))))
   2561     (let (disallow)
   2562       (when (or (string-match-p "\\.\\." string)
   2563                 (string-match-p "/\\." string))
   2564         (setq disallow (concat disallow ".")))
   2565       (when (string-match-p "@{" string)
   2566         (setq disallow (concat disallow "@{")))
   2567       (if disallow
   2568           ;; These additional restrictions overcompensate,
   2569           ;; but that only matters in rare cases.
   2570           (magit-thingatpt--git-revision disallow)
   2571         (and (not (equal string "@"))
   2572              (or (and (>= (length string) 7)
   2573                       (string-match-p "[a-z]" string)
   2574                       (magit-commit-p string))
   2575                  (and (magit-ref-p string)
   2576                       (let ((face (get-text-property (point) 'face)))
   2577                         (or (not face)
   2578                             (member face magit-revision-faces)))))
   2579              string)))))
   2580 
   2581 (put 'git-revision-range 'thing-at-point #'magit-thingatpt--git-revision-range)
   2582 (defun magit-thingatpt--git-revision-range ()
   2583   ;; Support hashes but no references.
   2584   (and-let* ((bounds
   2585               (cl-letf (((get 'git-revision 'beginning-op)
   2586                          (lambda ()
   2587                            (if (re-search-backward "[^a-z0-9.]" nil t)
   2588                                (forward-char)
   2589                              (goto-char (point-min)))))
   2590                         ((get 'git-revision 'end-op)
   2591                          (lambda ()
   2592                            (and (re-search-forward "[^a-z0-9.]" nil t)
   2593                                 (backward-char)))))
   2594                 (bounds-of-thing-at-point 'git-revision)))
   2595              (range (buffer-substring-no-properties (car bounds) (cdr bounds))))
   2596     ;; Validate but return as-is.
   2597     (and (magit-hash-range range) range)))
   2598 
   2599 ;;; Completion
   2600 
   2601 (defvar magit-revision-history nil)
   2602 
   2603 (defun magit--minibuf-default-add-commit ()
   2604   (let ((fn minibuffer-default-add-function))
   2605     (lambda ()
   2606       (if-let ((commit (with-selected-window (minibuffer-selected-window)
   2607                          (or (magit-thing-at-point 'git-revision-range t)
   2608                              (magit-commit-at-point)))))
   2609           (let ((rest (cons commit (delete commit (funcall fn))))
   2610                 (def minibuffer-default))
   2611             (if (listp def)
   2612                 (append def rest)
   2613               (cons def (delete def rest))))
   2614         (funcall fn)))))
   2615 
   2616 (defun magit-read-branch (prompt &optional secondary-default)
   2617   (magit-completing-read prompt (magit-list-branch-names)
   2618                          nil t nil 'magit-revision-history
   2619                          (or (magit-branch-at-point)
   2620                              secondary-default
   2621                              (magit-get-current-branch))))
   2622 
   2623 (defun magit-read-branch-or-commit (prompt &optional secondary-default exclude)
   2624   (let ((current (magit-get-current-branch))
   2625         (atpoint (magit-branch-or-commit-at-point))
   2626         (minibuffer-default-add-function (magit--minibuf-default-add-commit)))
   2627     (or (magit-completing-read prompt
   2628                                (delete exclude (magit-list-refnames nil t))
   2629                                nil nil nil 'magit-revision-history
   2630                                (or (and (not (equal atpoint exclude)) atpoint)
   2631                                    secondary-default
   2632                                    (and (not (equal current exclude)) current)))
   2633         (user-error "Nothing selected"))))
   2634 
   2635 (defun magit-read-range-or-commit (prompt &optional secondary-default)
   2636   (magit-read-range
   2637    prompt
   2638    (or (and-let* ((revs (magit-region-values '(commit branch) t)))
   2639          (progn
   2640            (deactivate-mark)
   2641            (concat (car (last revs)) ".." (car revs))))
   2642        (magit-branch-or-commit-at-point)
   2643        secondary-default
   2644        (magit-get-current-branch))))
   2645 
   2646 (defun magit-read-range (prompt &optional default)
   2647   (let ((minibuffer-default-add-function (magit--minibuf-default-add-commit))
   2648         (crm-separator "\\.\\.\\.?"))
   2649     (magit-completing-read-multiple
   2650      (concat prompt ": ")
   2651      (magit-list-refnames)
   2652      nil nil nil 'magit-revision-history default nil t)))
   2653 
   2654 (defun magit-read-remote-branch
   2655     (prompt &optional remote default local-branch require-match)
   2656   (let ((choice (magit-completing-read
   2657                  prompt
   2658                  (cl-union (and local-branch
   2659                                 (if remote
   2660                                     (list local-branch)
   2661                                   (--map (concat it "/" local-branch)
   2662                                          (magit-list-remotes))))
   2663                            (magit-list-remote-branch-names remote t)
   2664                            :test #'equal)
   2665                  nil require-match nil 'magit-revision-history default)))
   2666     (if (or remote (string-match "\\`\\([^/]+\\)/\\(.+\\)" choice))
   2667         choice
   2668       (user-error "`%s' doesn't have the form REMOTE/BRANCH" choice))))
   2669 
   2670 (defun magit-read-refspec (prompt remote)
   2671   (magit-completing-read prompt
   2672                          (prog2 (message "Determining available refs...")
   2673                              (magit-remote-list-refs remote)
   2674                            (message "Determining available refs...done"))))
   2675 
   2676 (defun magit-read-local-branch (prompt &optional secondary-default)
   2677   (magit-completing-read prompt (magit-list-local-branch-names)
   2678                          nil t nil 'magit-revision-history
   2679                          (or (magit-local-branch-at-point)
   2680                              secondary-default
   2681                              (magit-get-current-branch))))
   2682 
   2683 (defun magit-read-local-branch-or-commit (prompt)
   2684   (let ((minibuffer-default-add-function (magit--minibuf-default-add-commit))
   2685         (choices (nconc (magit-list-local-branch-names)
   2686                         (magit-list-special-refnames)))
   2687         (commit (magit-commit-at-point)))
   2688     (when commit
   2689       (push commit choices))
   2690     (or (magit-completing-read prompt choices
   2691                                nil nil nil 'magit-revision-history
   2692                                (or (magit-local-branch-at-point) commit))
   2693         (user-error "Nothing selected"))))
   2694 
   2695 (defun magit-read-local-branch-or-ref (prompt &optional secondary-default)
   2696   (magit-completing-read prompt (nconc (magit-list-local-branch-names)
   2697                                        (magit-list-refs "refs/"))
   2698                          nil t nil 'magit-revision-history
   2699                          (or (magit-local-branch-at-point)
   2700                              secondary-default
   2701                              (magit-get-current-branch))))
   2702 
   2703 (defun magit-read-other-branch
   2704     (prompt &optional exclude secondary-default no-require-match)
   2705   (let* ((current (magit-get-current-branch))
   2706          (atpoint (magit-branch-at-point))
   2707          (exclude (or exclude current))
   2708          (default (or (and (not (equal atpoint exclude)) atpoint)
   2709                       (and (not (equal current exclude)) current)
   2710                       secondary-default
   2711                       (magit-get-previous-branch))))
   2712     (magit-completing-read prompt (delete exclude (magit-list-branch-names))
   2713                            nil (not no-require-match)
   2714                            nil 'magit-revision-history default)))
   2715 
   2716 (defun magit-read-other-branch-or-commit
   2717     (prompt &optional exclude secondary-default)
   2718   (let* ((minibuffer-default-add-function (magit--minibuf-default-add-commit))
   2719          (current (magit-get-current-branch))
   2720          (atpoint (magit-branch-or-commit-at-point))
   2721          (exclude (or exclude current))
   2722          (default (or (and (not (equal atpoint exclude))
   2723                            (not (and (not current)
   2724                                      (magit-rev-equal atpoint "HEAD")))
   2725                            atpoint)
   2726                       (and (not (equal current exclude)) current)
   2727                       secondary-default
   2728                       (magit-get-previous-branch))))
   2729     (or (magit-completing-read prompt (delete exclude (magit-list-refnames))
   2730                                nil nil nil 'magit-revision-history default)
   2731         (user-error "Nothing selected"))))
   2732 
   2733 (defun magit-read-other-local-branch
   2734     (prompt &optional exclude secondary-default no-require-match)
   2735   (let* ((current (magit-get-current-branch))
   2736          (atpoint (magit-local-branch-at-point))
   2737          (exclude (or exclude current))
   2738          (default (or (and (not (equal atpoint exclude)) atpoint)
   2739                       (and (not (equal current exclude)) current)
   2740                       secondary-default
   2741                       (magit-get-previous-branch))))
   2742     (magit-completing-read prompt
   2743                            (delete exclude (magit-list-local-branch-names))
   2744                            nil (not no-require-match)
   2745                            nil 'magit-revision-history default)))
   2746 
   2747 (defun magit-read-branch-prefer-other (prompt)
   2748   (let* ((current (magit-get-current-branch))
   2749          (commit  (magit-commit-at-point))
   2750          (atrev   (and commit (magit-list-branches-pointing-at commit)))
   2751          (atpoint (magit--painted-branch-at-point)))
   2752     (magit-completing-read prompt (magit-list-branch-names)
   2753                            nil t nil 'magit-revision-history
   2754                            (or (magit-section-value-if 'branch)
   2755                                atpoint
   2756                                (and (not (cdr atrev)) (car atrev))
   2757                                (--first (not (equal it current)) atrev)
   2758                                (magit-get-previous-branch)
   2759                                (car atrev)))))
   2760 
   2761 (defun magit-read-upstream-branch (&optional branch prompt)
   2762   "Read the upstream for BRANCH using PROMPT.
   2763 If optional BRANCH is nil, then read the upstream for the
   2764 current branch, or raise an error if no branch is checked
   2765 out.  Only existing branches can be selected."
   2766   (unless branch
   2767     (setq branch (or (magit-get-current-branch)
   2768                      (error "Need a branch to set its upstream"))))
   2769   (let ((branches (delete branch (magit-list-branch-names))))
   2770     (magit-completing-read
   2771      (or prompt (format "Change upstream of %s to" branch))
   2772      branches nil t nil 'magit-revision-history
   2773      (or (let ((r (car (member (magit-remote-branch-at-point) branches)))
   2774                (l (car (member (magit-local-branch-at-point) branches))))
   2775            (if magit-prefer-remote-upstream (or r l) (or l r)))
   2776          (and-let* ((main (magit-main-branch)))
   2777            (let ((r (car (member (concat "origin/" main) branches)))
   2778                  (l (car (member main branches))))
   2779              (if magit-prefer-remote-upstream (or r l) (or l r))))
   2780          (car (member (magit-get-previous-branch) branches))))))
   2781 
   2782 (defun magit-read-starting-point (prompt &optional branch default)
   2783   (or (magit-completing-read
   2784        (concat prompt
   2785                (and branch
   2786                     (if (bound-and-true-p ivy-mode)
   2787                         ;; Ivy-mode strips faces from prompt.
   2788                         (format  " `%s'" branch)
   2789                       (concat " " (magit--propertize-face
   2790                                    branch 'magit-branch-local))))
   2791                " starting at")
   2792        (nconc (list "HEAD")
   2793               (magit-list-refnames)
   2794               (directory-files (magit-gitdir) nil "_HEAD\\'"))
   2795        nil nil nil 'magit-revision-history
   2796        (or default (magit--default-starting-point)))
   2797       (user-error "Nothing selected")))
   2798 
   2799 (defun magit--default-starting-point ()
   2800   (or (let ((r (magit-remote-branch-at-point))
   2801             (l (magit-local-branch-at-point)))
   2802         (if magit-prefer-remote-upstream (or r l) (or l r)))
   2803       (magit-commit-at-point)
   2804       (magit-stash-at-point)
   2805       (magit-get-current-branch)))
   2806 
   2807 (defun magit-read-tag (prompt &optional require-match)
   2808   (magit-completing-read prompt (magit-list-tags) nil
   2809                          require-match nil 'magit-revision-history
   2810                          (magit-tag-at-point)))
   2811 
   2812 (defun magit-read-stash (prompt)
   2813   (let* ((atpoint (magit-stash-at-point))
   2814          (default (and atpoint
   2815                        (concat atpoint (magit-rev-format " %s" atpoint))))
   2816          (choices (mapcar (lambda (c)
   2817                             (pcase-let ((`(,rev ,msg) (split-string c "\0")))
   2818                               (concat (propertize rev 'face 'magit-hash)
   2819                                       " " msg)))
   2820                           (magit-list-stashes "%gd%x00%s")))
   2821          (choice  (magit-completing-read prompt choices
   2822                                          nil t nil nil
   2823                                          default
   2824                                          (car choices))))
   2825     (and choice
   2826          (string-match "^\\([^ ]+\\) \\(.+\\)" choice)
   2827          (substring-no-properties (match-string 1 choice)))))
   2828 
   2829 (defun magit-read-remote (prompt &optional default use-only)
   2830   (let ((remotes (magit-list-remotes)))
   2831     (if (and use-only (length= remotes 1))
   2832         (car remotes)
   2833       (magit-completing-read prompt remotes
   2834                              nil t nil nil
   2835                              (or default
   2836                                  (magit-remote-at-point)
   2837                                  (magit-get-remote))))))
   2838 
   2839 (defun magit-read-remote-or-url (prompt &optional default)
   2840   (magit-completing-read prompt
   2841                          (nconc (magit-list-remotes)
   2842                                 (list "https://" "git://" "git@"))
   2843                          nil nil nil nil
   2844                          (or default
   2845                              (magit-remote-at-point)
   2846                              (magit-get-remote))))
   2847 
   2848 (defun magit-read-module-path (prompt &optional predicate)
   2849   (magit-completing-read prompt (magit-list-module-paths)
   2850                          predicate t nil nil
   2851                          (magit-module-at-point predicate)))
   2852 
   2853 (defun magit-module-confirm (verb &optional predicate)
   2854   ;; Some predicates use the inefficient `magit-toplevel'
   2855   ;; and some repositories have thousands of submodules.
   2856   (let ((magit--refresh-cache (list (cons 0 0)))
   2857         (modules nil))
   2858     (if current-prefix-arg
   2859         (progn
   2860           (setq modules (magit-list-module-paths))
   2861           (when predicate
   2862             (setq modules (seq-filter predicate modules)))
   2863           (unless modules
   2864             (if predicate
   2865                 (user-error "No modules satisfying %s available" predicate)
   2866               (user-error "No modules available"))))
   2867       (setq modules (magit-region-values 'module))
   2868       (when modules
   2869         (when predicate
   2870           (setq modules (seq-filter predicate modules)))
   2871         (unless modules
   2872           (user-error "No modules satisfying %s selected" predicate))))
   2873     (if (or (length> modules 1) current-prefix-arg)
   2874         (magit-confirm t nil (format "%s %%d modules" verb) nil modules)
   2875       (list (magit-read-module-path (format "%s module" verb) predicate)))))
   2876 
   2877 ;;; _
   2878 (provide 'magit-git)
   2879 ;;; magit-git.el ends here