mirror of https://github.com/Chizi123/.emacs.d.git

Chizi123
2018-11-21 e75a20334813452c6912c090d70a0de2c805f94d
commit | author | age
5cb5f7 1 ;;; magit-git.el --- Git functionality  -*- lexical-binding: t -*-
C 2
3 ;; Copyright (C) 2010-2018  The Magit Project Contributors
4 ;;
5 ;; You should have received a copy of the AUTHORS.md file which
6 ;; lists all contributors.  If not, see http://magit.vc/authors.
7
8 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
9 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
10
11 ;; Magit is free software; you can redistribute it and/or modify it
12 ;; under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 3, or (at your option)
14 ;; any later version.
15 ;;
16 ;; Magit is distributed in the hope that it will be useful, but WITHOUT
17 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
19 ;; License for more details.
20 ;;
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with Magit.  If not, see http://www.gnu.org/licenses.
23
24 ;;; Commentary:
25
26 ;; This library implements wrappers for various Git plumbing commands.
27
28 ;;; Code:
29
30 (require 'cl-lib)
31 (require 'dash)
32
33 (eval-when-compile
34   (require 'subr-x))
35
36 (require 'magit-utils)
37 (require 'magit-section)
38
39 (declare-function magit-call-git "magit-process" (&rest args))
40 (declare-function magit-maybe-make-margin-overlay "magit-margin" ())
41 (declare-function magit-process-buffer "magit-process" (&optional nodisplay))
42 (declare-function magit-process-file "magit-process" (&rest args))
43 (declare-function magit-process-insert-section "magit-process"
44                   (pwe program args &optional errcode errlog))
45 (declare-function magit-refresh "magit-mode" ())
46 (defvar magit-process-error-message-regexps)
47 (defvar magit-refresh-args) ; from `magit-mode' for `magit-current-file'
48 (defvar magit-branch-prefer-remote-upstream)
49 (defvar magit-published-branches)
50 (defvar magit-diff-section-arguments)
51
52 (defvar magit-tramp-process-environment nil)
53
54 ;;; Options
55
56 ;; For now this is shared between `magit-process' and `magit-git'.
57 (defgroup magit-process nil
58   "Git and other external processes used by Magit."
59   :group 'magit)
60
61 (defvar magit-git-environment
62   (list (format "INSIDE_EMACS=%s,magit" emacs-version))
63   "Prepended to `process-environment' while running git.")
64
65 (defcustom magit-git-output-coding-system
66   (and (eq system-type 'windows-nt) 'utf-8)
67   "Coding system for receiving output from Git.
68
69 If non-nil, the Git config value `i18n.logOutputEncoding' should
70 be set via `magit-git-global-arguments' to value consistent with
71 this."
72   :package-version '(magit . "2.9.0")
73   :group 'magit-process
74   :type '(choice (coding-system :tag "Coding system to decode Git output")
75                  (const :tag "Use system default" nil)))
76
77 (defvar magit-git-w32-path-hack nil
78   "Alist of (EXE . (PATHENTRY)).
79 This specifies what additional PATH setting needs to be added to
80 the environment in order to run the non-wrapper git executables
81 successfully.")
82
83 (defcustom magit-git-executable
84   ;; Git might be installed in a different location on a remote, so
85   ;; it is better not to use the full path to the executable, except
86   ;; on Window were we would otherwise end up using one one of the
87   ;; wrappers "cmd/git.exe" or "cmd/git.cmd", which are much slower
88   ;; than using "bin/git.exe" directly.
89   (or (and (eq system-type 'windows-nt)
90            (--when-let (executable-find "git")
91              (ignore-errors
92                ;; Git for Windows 2.x provides cygpath so we can
93                ;; ask it for native paths.
94                (let* ((core-exe
95                        (car
96                         (process-lines
97                          it "-c"
98                          "alias.X=!x() { which \"$1\" | cygpath -mf -; }; x"
99                          "X" "git")))
100                       (hack-entry (assoc core-exe magit-git-w32-path-hack))
101                       ;; Running the libexec/git-core executable
102                       ;; requires some extra PATH entries.
103                       (path-hack
104                        (list (concat "PATH="
105                                      (car (process-lines
106                                            it "-c"
107                                            "alias.P=!cygpath -wp \"$PATH\""
108                                            "P"))))))
109                  ;; The defcustom STANDARD expression can be
110                  ;; evaluated many times, so make sure it is
111                  ;; idempotent.
112                  (if hack-entry
113                      (setcdr hack-entry path-hack)
114                    (push (cons core-exe path-hack) magit-git-w32-path-hack))
115                  core-exe))))
116       "git")
117   "The Git executable used by Magit."
118   :group 'magit-process
119   :type 'string)
120
121 (defcustom magit-git-global-arguments
122   `("--no-pager" "--literal-pathspecs" "-c" "core.preloadindex=true"
123     "-c" "log.showSignature=false"
124     ,@(and (eq system-type 'windows-nt)
125            (list "-c" "i18n.logOutputEncoding=UTF-8")))
126   "Global Git arguments.
127
128 The arguments set here are used every time the git executable is
129 run as a subprocess.  They are placed right after the executable
130 itself and before the git command - as in `git HERE... COMMAND
131 REST'.  See the manpage `git(1)' for valid arguments.
132
133 Be careful what you add here, especially if you are using Tramp
134 to connect to servers with ancient Git versions.  Never remove
135 anything that is part of the default value, unless you really
136 know what you are doing.  And think very hard before adding
137 something; it will be used every time Magit runs Git for any
138 purpose."
139   :package-version '(magit . "2.9.0")
140   :group 'magit-git-arguments
141   :group 'magit-process
142   :type '(repeat string))
143
144 (defvar magit-git-debug nil
145   "Whether to enable additional reporting of git errors.
146
147 Magit basically calls git for one of these two reasons: for
148 side-effects or to do something with its standard output.
149
150 When git is run for side-effects then its output, including error
151 messages, go into the process buffer which is shown when using \
152 \\<magit-status-mode-map>\\[magit-process].
153
154 When git's output is consumed in some way, then it would be too
155 expensive to also insert it into this buffer, but when this
156 option is non-nil and git returns with a non-zero exit status,
157 then at least its standard error is inserted into this buffer.
158
159 This is only intended for debugging purposes.  Do not enable this
160 permanently, that would negatively affect performance.")
161
162
163 (defcustom magit-prefer-remote-upstream nil
164   "Whether to favor remote branches when reading the upstream branch.
165
166 This controls whether commands that read a branch from the user
167 and then set it as the upstream branch, offer a local or a remote
168 branch as default completion candidate, when they have the choice.
169
170 This affects all commands that use `magit-read-upstream-branch'
171 or `magit-read-starting-point', which includes all commands that
172 change the upstream and many which create new branches."
173   :package-version '(magit . "2.4.2")
174   :group 'magit-commands
175   :type 'boolean)
176
177 (defcustom magit-list-refs-sortby nil
178   "How to sort the ref collection in the prompt.
179
180 This affects commands that read a ref.  More specifically, it
181 controls the order of refs returned by `magit-list-refs', which
182 is called by functions like `magit-list-branch-names' to generate
183 the collection of refs.  By default, refs are sorted according to
184 their full refname (i.e., 'refs/...').
185
186 Any value accepted by the `--sort' flag of `git for-each-ref' can
187 be used.  For example, \"-creatordate\" places refs with more
188 recent committer or tagger dates earlier in the list.  A list of
189 strings can also be given in order to pass multiple sort keys to
190 `git for-each-ref'.
191
192 Note that, depending on the completion framework you use, this
193 may not be sufficient to change the order in which the refs are
194 displayed.  It only controls the order of the collection passed
195 to `magit-completing-read' or, for commands that support reading
196 multiple strings, `read-from-minibuffer'.  The completion
197 framework ultimately determines how the collection is displayed."
198   :package-version '(magit . "2.11.0")
199   :group 'magit-miscellanous
200   :type '(choice string (repeat string)))
201
202 ;;; Git
203
204 (defvar magit--refresh-cache nil)
205
206 (defmacro magit--with-refresh-cache (key &rest body)
207   (declare (indent 1) (debug (form body)))
208   (let ((k (cl-gensym)))
209     `(if magit--refresh-cache
210          (let ((,k ,key))
211            (--if-let (assoc ,k (cdr magit--refresh-cache))
212                (progn (cl-incf (caar magit--refresh-cache))
213                       (cdr it))
214              (cl-incf (cdar magit--refresh-cache))
215              (let ((value ,(macroexp-progn body)))
216                (push (cons ,k value)
217                      (cdr magit--refresh-cache))
218                value)))
219        ,@body)))
220
221 (defvar magit-with-editor-envvar "GIT_EDITOR"
222   "The environment variable exported by `magit-with-editor'.
223 Set this to \"GIT_SEQUENCE_EDITOR\" if you do not want to use
224 Emacs to edit commit messages but would like to do so to edit
225 rebase sequences.")
226
227 (defmacro magit-with-editor (&rest body)
228   "Like `with-editor' but let-bind some more variables.
229 Also respect the value of `magit-with-editor-envvar'."
230   (declare (indent 0) (debug (body)))
231   `(let ((magit-process-popup-time -1)
232          ;; The user may have customized `shell-file-name' to
233          ;; something which results in `w32-shell-dos-semantics' nil
234          ;; (which changes the quoting style used by
235          ;; `shell-quote-argument'), but Git for Windows expects shell
236          ;; quoting in the dos style.
237          (shell-file-name (if (and (eq system-type 'windows-nt)
238                                    ;; If we have Cygwin mount points,
239                                    ;; the git flavor is cygwin, so dos
240                                    ;; shell quoting is probably wrong.
241                                    (not magit-cygwin-mount-points))
242                               "cmdproxy"
243                             shell-file-name)))
244      (with-editor* magit-with-editor-envvar
245        ,@body)))
246
247 (defun magit-process-git-arguments (args)
248   "Prepare ARGS for a function that invokes Git.
249
250 Magit has many specialized functions for running Git; they all
251 pass arguments through this function before handing them to Git,
252 to do the following.
253
254 * Flatten ARGS, removing nil arguments.
255 * Prepend `magit-git-global-arguments' to ARGS.
256 * On w32 systems, encode to `w32-ansi-code-page'."
257   (setq args (append magit-git-global-arguments (-flatten args)))
258   (if (and (eq system-type 'windows-nt) (boundp 'w32-ansi-code-page))
259       ;; On w32, the process arguments *must* be encoded in the
260       ;; current code-page (see #3250).
261       (mapcar (lambda (arg)
262                 (encode-coding-string
263                  arg (intern (format "cp%d" w32-ansi-code-page))))
264               args)
265     args))
266
267 (defun magit-git-exit-code (&rest args)
268   "Execute Git with ARGS, returning its exit code."
269   (apply #'magit-process-file magit-git-executable nil nil nil
270          (magit-process-git-arguments args)))
271
272 (defun magit-git-success (&rest args)
273   "Execute Git with ARGS, returning t if its exit code is 0."
274   (= (magit-git-exit-code args) 0))
275
276 (defun magit-git-failure (&rest args)
277   "Execute Git with ARGS, returning t if its exit code is 1."
278   (= (magit-git-exit-code args) 1))
279
280 (defun magit-git-str (&rest args)
281   "Execute Git with ARGS, returning the first line of its output.
282 If there is no output, return nil.  If the output begins with a
283 newline, return an empty string.  Like `magit-git-string' but
284 ignore `magit-git-debug'."
285   (setq args (-flatten args))
286   (magit--with-refresh-cache (cons default-directory args)
287     (with-temp-buffer
288       (apply #'magit-process-file magit-git-executable nil (list t nil) nil
289              (magit-process-git-arguments args))
290       (unless (bobp)
291         (goto-char (point-min))
292         (buffer-substring-no-properties (point) (line-end-position))))))
293
294 (defun magit-git-output (&rest args)
295   "Execute Git with ARGS, returning its output."
296   (setq args (-flatten args))
297   (magit--with-refresh-cache (cons default-directory args)
298     (with-temp-buffer
299       (apply #'magit-process-file magit-git-executable nil (list t nil) nil
300              (magit-process-git-arguments args))
301       (buffer-substring-no-properties (point-min) (point-max)))))
302
303 (define-error 'magit-invalid-git-boolean "Not a Git boolean")
304
305 (defun magit-git-true (&rest args)
306   "Execute Git with ARGS, returning t if it prints \"true\".
307 If it prints \"false\", then return nil.  For any other output
308 signal `magit-invalid-git-boolean'."
309   (pcase (magit-git-output args)
310     ((or "true"  "true\n")  t)
311     ((or "false" "false\n") nil)
312     (output (signal 'magit-invalid-git-boolean output))))
313
314 (defun magit-git-false (&rest args)
315   "Execute Git with ARGS, returning t if it prints \"false\".
316 If it prints \"true\", then return nil.  For any other output
317 signal `magit-invalid-git-boolean'."
318   (pcase (magit-git-output args)
319     ((or "true"  "true\n")  nil)
320     ((or "false" "false\n") t)
321     (output (signal 'magit-invalid-git-boolean output))))
322
323 (defun magit-git-insert (&rest args)
324   "Execute Git with ARGS, inserting its output at point.
325 If Git exits with a non-zero exit status, then show a message and
326 add a section in the respective process buffer."
327   (setq args (magit-process-git-arguments args))
328   (if magit-git-debug
329       (let (log)
330         (unwind-protect
331             (progn
332               (setq log (make-temp-file "magit-stderr"))
333               (delete-file log)
334               (let ((exit (apply #'magit-process-file magit-git-executable
335                                  nil (list t log) nil args)))
336                 (when (> exit 0)
337                   (let ((msg "Git failed"))
338                     (when (file-exists-p log)
339                       (setq msg (with-temp-buffer
340                                   (insert-file-contents log)
341                                   (goto-char (point-max))
342                                   (cond
343                                    ((functionp magit-git-debug)
344                                     (funcall magit-git-debug (buffer-string)))
345                                    ((run-hook-wrapped
346                                      'magit-process-error-message-regexps
347                                      (lambda (re) (re-search-backward re nil t)))
348                                     (match-string-no-properties 1)))))
349                       (let ((magit-git-debug nil))
350                         (with-current-buffer (magit-process-buffer t)
351                           (magit-process-insert-section default-directory
352                                                         magit-git-executable
353                                                         args exit log))))
354                     (message "%s" msg)))
355                 exit))
356           (ignore-errors (delete-file log))))
357     (apply #'magit-process-file magit-git-executable
358            nil (list t nil) nil args)))
359
360 (defun magit-git-string (&rest args)
361   "Execute Git with ARGS, returning the first line of its output.
362 If there is no output, return nil.  If the output begins with a
363 newline, return an empty string."
364   (setq args (-flatten args))
365   (magit--with-refresh-cache (cons default-directory args)
366     (with-temp-buffer
367       (apply #'magit-git-insert args)
368       (unless (bobp)
369         (goto-char (point-min))
370         (buffer-substring-no-properties (point) (line-end-position))))))
371
372 (defun magit-git-lines (&rest args)
373   "Execute Git with ARGS, returning its output as a list of lines.
374 Empty lines anywhere in the output are omitted.
375
376 If Git exits with a non-zero exit status, then report show a
377 message and add a section in the respective process buffer."
378   (with-temp-buffer
379     (apply #'magit-git-insert args)
380     (split-string (buffer-string) "\n" t)))
381
382 (defun magit-git-items (&rest args)
383   "Execute Git with ARGS, returning its null-separated output as a list.
384 Empty items anywhere in the output are omitted.
385
386 If Git exits with a non-zero exit status, then report show a
387 message and add a section in the respective process buffer."
388   (with-temp-buffer
389     (apply #'magit-git-insert args)
390     (split-string (buffer-string) "\0" t)))
391
392 (defun magit-git-wash (washer &rest args)
393   "Execute Git with ARGS, inserting washed output at point.
394 Actually first insert the raw output at point.  If there is no
395 output, call `magit-cancel-section'.  Otherwise temporarily narrow
396 the buffer to the inserted text, move to its beginning, and then
397 call function WASHER with ARGS as its sole argument."
398   (declare (indent 1))
399   (let ((beg (point)))
400     (setq args (-flatten args))
401     (magit-git-insert args)
402     (if (= (point) beg)
403         (magit-cancel-section)
404       (unless (bolp)
405         (insert "\n"))
406       (save-restriction
407         (narrow-to-region beg (point))
408         (goto-char beg)
409         (funcall washer args))
410       (when (or (= (point) beg)
411                 (= (point) (1+ beg)))
412         (magit-cancel-section))
413       (magit-maybe-make-margin-overlay))))
414
415 (defun magit-git-version (&optional raw)
416   (--when-let (let (magit-git-global-arguments)
417                 (ignore-errors (substring (magit-git-string "version") 12)))
418     (if raw it (and (string-match "^\\([0-9]+\\.[0-9]+\\.[0-9]+\\)" it)
419                     (match-string 1 it)))))
420
421 ;;; Variables
422
423 (defun magit-config-get-from-cached-list (key)
424   (gethash
425    ;; `git config --list' downcases first and last components of the key.
426    (--> key
427         (replace-regexp-in-string "\\`[^.]+" #'downcase it t t)
428         (replace-regexp-in-string "[^.]+\\'" #'downcase it t t))
429    (magit--with-refresh-cache (cons (magit-toplevel) 'config)
430      (let ((configs (make-hash-table :test 'equal)))
431        (dolist (conf (magit-git-items "config" "--list" "-z"))
432          (let* ((nl-pos (cl-position ?\n conf))
433                 (key (substring conf 0 nl-pos))
434                 (val (if nl-pos (substring conf (1+ nl-pos)) "")))
435            (puthash key (nconc (gethash key configs) (list val)) configs)))
436        configs))))
437
438 (defun magit-get (&rest keys)
439   "Return the value of the Git variable specified by KEYS."
440   (car (last (apply 'magit-get-all keys))))
441
442 (defun magit-get-all (&rest keys)
443   "Return all values of the Git variable specified by KEYS."
444   (let ((magit-git-debug nil)
445         (arg (and (or (null (car keys))
446                       (string-prefix-p "--" (car keys)))
447                   (pop keys)))
448         (key (mapconcat 'identity keys ".")))
449     (if (and magit--refresh-cache (not arg))
450         (magit-config-get-from-cached-list key)
451       (magit-git-items "config" arg "-z" "--get-all" key))))
452
453 (defun magit-get-boolean (&rest keys)
454   "Return the boolean value of the Git variable specified by KEYS."
455   (let ((key (mapconcat 'identity keys ".")))
456     (if magit--refresh-cache
457         (equal "true" (car (last (magit-config-get-from-cached-list key))))
458       (equal (magit-git-str "config" "--bool" key) "true"))))
459
460 (defun magit-set (value &rest keys)
461   "Set the value of the Git variable specified by KEYS to VALUE."
462   (let ((arg (and (or (null (car keys))
463                       (string-prefix-p "--" (car keys)))
464                   (pop keys)))
465         (key (mapconcat 'identity keys ".")))
466     (if value
467         (magit-git-success "config" arg key value)
468       (magit-git-success "config" arg "--unset" key))
469     value))
470
471 (gv-define-setter magit-get (val &rest keys)
472   `(magit-set ,val ,@keys))
473
474 (defun magit-set-all (values &rest keys)
475   "Set all values of the Git variable specified by KEYS to VALUES."
476   (let ((arg (and (or (null (car keys))
477                       (string-prefix-p "--" (car keys)))
478                   (pop keys)))
479         (var (mapconcat 'identity keys ".")))
480     (when (magit-get var)
481       (magit-call-git "config" arg "--unset-all" var))
482     (dolist (v values)
483       (magit-call-git "config" arg "--add" var v))))
484
485 ;;; Files
486
487 (defun magit--safe-default-directory (&optional file)
488   (catch 'unsafe-default-dir
489     (let ((dir (file-name-as-directory
490                 (expand-file-name (or file default-directory))))
491           (previous nil))
492       (while (not (magit-file-accessible-directory-p dir))
493         (setq dir (file-name-directory (directory-file-name dir)))
494         (when (equal dir previous)
495           (throw 'unsafe-default-dir nil))
496         (setq previous dir))
497       dir)))
498
499 (defmacro magit--with-safe-default-directory (file &rest body)
500   (declare (indent 1) (debug (form body)))
501   `(when-let ((default-directory (magit--safe-default-directory ,file)))
502      ,@body))
503
504 (defun magit-gitdir (&optional directory)
505   "Return the absolute and resolved path of the .git directory.
506
507 If the `GIT_DIR' environment variable is define then return that.
508 Otherwise return the .git directory for DIRECTORY, or if that is
509 nil, then for `default-directory' instead.  If the directory is
510 not located inside a Git repository, then return nil."
511   (let ((default-directory (or directory default-directory)))
512     (magit-git-dir)))
513
514 (defun magit-git-dir (&optional path)
515   "Return the absolute and resolved path of the .git directory.
516
517 If the `GIT_DIR' environment variable is define then return that.
518 Otherwise return the .git directory for `default-directory'.  If
519 the directory is not located inside a Git repository, then return
520 nil."
521   (magit--with-refresh-cache (list default-directory 'magit-git-dir path)
522     (magit--with-safe-default-directory nil
523       (when-let ((dir (magit-rev-parse-safe "--git-dir")))
524         (setq dir (file-name-as-directory (magit-expand-git-file-name dir)))
525         (unless (file-remote-p dir)
526           (setq dir (concat (file-remote-p default-directory) dir)))
527         (if path (expand-file-name (convert-standard-filename path) dir) dir)))))
528
529 (defvar magit--separated-gitdirs nil)
530
531 (defun magit--record-separated-gitdir ()
532   (let ((topdir (magit-toplevel))
533         (gitdir (magit-git-dir)))
534     ;; Kludge: git-annex converts submodule gitdirs to symlinks. See #3599.
535     (when (file-symlink-p (directory-file-name gitdir))
536       (setq gitdir (file-truename gitdir)))
537     ;; We want to delete the entry for `topdir' here, rather than within
538     ;; (unless ...), in case a `--separate-git-dir' repository was switched to
539     ;; the standard structure (i.e., "topdir/.git/").
540     (setq magit--separated-gitdirs (cl-delete topdir
541                                               magit--separated-gitdirs
542                                               :key #'car :test #'equal))
543     (unless (equal (file-name-as-directory (expand-file-name ".git" topdir))
544                    gitdir)
545       (push (cons topdir gitdir) magit--separated-gitdirs))))
546
547 (defun magit-toplevel (&optional directory)
548   "Return the absolute path to the toplevel of the current repository.
549
550 From within the working tree or control directory of a repository
551 return the absolute path to the toplevel directory of the working
552 tree.  As a special case, from within a bare repository return
553 the control directory instead.  When called outside a repository
554 then return nil.
555
556 When optional DIRECTORY is non-nil then return the toplevel for
557 that directory instead of the one for `default-directory'.
558
559 Try to respect the option `find-file-visit-truename', i.e.  when
560 the value of that option is nil, then avoid needlessly returning
561 the truename.  When a symlink to a sub-directory of the working
562 tree is involved, or when called from within a sub-directory of
563 the gitdir or from the toplevel of a gitdir, which itself is not
564 located within the working tree, then it is not possible to avoid
565 returning the truename."
566   (magit--with-refresh-cache
567       (cons (or directory default-directory) 'magit-toplevel)
568     (magit--with-safe-default-directory directory
569       (if-let ((topdir (magit-rev-parse-safe "--show-toplevel")))
570           (let (updir)
571             (setq topdir (magit-expand-git-file-name topdir))
572             (if (and
573                  ;; Always honor these settings.
574                  (not find-file-visit-truename)
575                  (not (getenv "GIT_WORK_TREE"))
576                  ;; `--show-cdup' is the relative path to the toplevel
577                  ;; from `(file-truename default-directory)'.  Here we
578                  ;; pretend it is relative to `default-directory', and
579                  ;; go to that directory.  Then we check whether
580                  ;; `--show-toplevel' still returns the same value and
581                  ;; whether `--show-cdup' now is the empty string.  If
582                  ;; both is the case, then we are at the toplevel of
583                  ;; the same working tree, but also avoided needlessly
584                  ;; following any symlinks.
585                  (progn
586                    (setq updir (file-name-as-directory
587                                 (magit-rev-parse-safe "--show-cdup")))
588                    (setq updir (if (file-name-absolute-p updir)
589                                    (concat (file-remote-p default-directory) updir)
590                                  (expand-file-name updir)))
591                    (let ((default-directory updir))
592                      (and (string-equal (magit-rev-parse-safe "--show-cdup") "")
593                           (--when-let (magit-rev-parse-safe "--show-toplevel")
594                             (string-equal (magit-expand-git-file-name it)
595                                           topdir))))))
596                 updir
597               (concat (file-remote-p default-directory)
598                       (file-name-as-directory topdir))))
599         (when-let ((gitdir (magit-rev-parse-safe "--git-dir")))
600           (setq gitdir (file-name-as-directory
601                         (if (file-name-absolute-p gitdir)
602                             ;; We might have followed a symlink.
603                             (concat (file-remote-p default-directory)
604                                     (magit-expand-git-file-name gitdir))
605                           (expand-file-name gitdir))))
606           (if (magit-bare-repo-p)
607               gitdir
608             (let* ((link (expand-file-name "gitdir" gitdir))
609                    (wtree (and (file-exists-p link)
610                                (magit-file-line link))))
611               (cond
612                ((and wtree
613                      ;; Ignore .git/gitdir files that result from a
614                      ;; Git bug.  See #2364.
615                      (not (equal wtree ".git")))
616                 ;; Return the linked working tree.
617                 (file-name-directory wtree))
618                ;; The working directory may not be the parent directory of
619                ;; .git if it was set up with `git init --separate-git-dir'.
620                ;; See #2955.
621                ((car (rassoc gitdir magit--separated-gitdirs)))
622                (t
623                 ;; Step outside the control directory to enter the working tree.
624                 (file-name-directory (directory-file-name gitdir)))))))))))
625
626 (defmacro magit-with-toplevel (&rest body)
627   (declare (indent defun) (debug (body)))
628   (let ((toplevel (cl-gensym "toplevel")))
629     `(let ((,toplevel (magit-toplevel)))
630        (if ,toplevel
631            (let ((default-directory ,toplevel))
632              ,@body)
633          (magit--not-inside-repository-error)))))
634
635 (define-error 'magit-outside-git-repo "Not inside Git repository")
636 (define-error 'magit-git-executable-not-found
637   "Git executable cannot be found (see https://magit.vc/goto/e6a78ed2)")
638
639 (defun magit--not-inside-repository-error ()
640   (if (executable-find magit-git-executable)
641       (signal 'magit-outside-git-repo default-directory)
642     (signal 'magit-git-executable-not-found magit-git-executable)))
643
644 (defun magit-inside-gitdir-p (&optioal noerror)
645   "Return t if `default-directory' is below the repository directory.
646 If it is below the working directory, then return nil.
647 If it isn't below either, then signal an error unless NOERROR
648 is non-nil, in which case return nil."
649   (and (magit--assert-default-directory noerror)
650        ;; Below a repository directory that is not located below the
651        ;; working directory "git rev-parse --is-inside-git-dir" prints
652        ;; "false", which is wrong.
653        (let ((gitdir (magit-git-dir)))
654          (cond (gitdir (file-in-directory-p default-directory gitdir))
655                (noerror nil)
656                (t (signal 'magit-outside-git-repo default-directory))))))
657
658 (defun magit-inside-worktree-p (&optional noerror)
659   "Return t if `default-directory' is below the working directory.
660 If it is below the repository directory, then return nil.
661 If it isn't below either, then signal an error unless NOERROR
662 is non-nil, in which case return nil."
663   (and (magit--assert-default-directory noerror)
664        (condition-case nil
665            (magit-rev-parse-true "--is-inside-work-tree")
666          (magit-invalid-git-boolean
667           (and (not noerror)
668                (signal 'magit-outside-git-repo default-directory))))))
669
670 (defun magit-bare-repo-p (&optional noerror)
671   "Return t if the current repository is bare.
672 If it is non-bare, then return nil.  If `default-directory'
673 isn't below a Git repository, then signal an error unless
674 NOERROR is non-nil, in which case return nil."
675   (and (magit--assert-default-directory noerror)
676        (condition-case nil
677            (magit-rev-parse-true "--is-bare-repository")
678          (magit-invalid-git-boolean
679           (and (not noerror)
680                (signal 'magit-outside-git-repo default-directory))))))
681
682 (defun magit--assert-default-directory (&optional noerror)
683   (or (file-directory-p default-directory)
684       (and (not noerror)
685            (let ((exists (file-exists-p default-directory)))
686              (signal (if exists 'file-error 'file-missing)
687                      (list "Running git in directory"
688                            (if exists
689                                "Not a directory"
690                              "No such file or directory")
691                            default-directory))))))
692
693 (defun magit-git-repo-p (directory &optional non-bare)
694   "Return t if DIRECTORY is a Git repository.
695 When optional NON-BARE is non-nil also return nil if DIRECTORY is
696 a bare repository."
697   (and (file-directory-p directory) ; Avoid archives, see #3397.
698        (or (file-regular-p (expand-file-name ".git" directory))
699            (file-directory-p (expand-file-name ".git" directory))
700            (and (not non-bare)
701                 (file-regular-p (expand-file-name "HEAD" directory))
702                 (file-directory-p (expand-file-name "refs" directory))
703                 (file-directory-p (expand-file-name "objects" directory))))))
704
705 (defvar-local magit-buffer-revision  nil)
706 (defvar-local magit-buffer-refname   nil)
707 (defvar-local magit-buffer-file-name nil)
708 (put 'magit-buffer-revision  'permanent-local t)
709 (put 'magit-buffer-refname   'permanent-local t)
710 (put 'magit-buffer-file-name 'permanent-local t)
711
712 (defun magit-file-relative-name (&optional file tracked)
713   "Return the path of FILE relative to the repository root.
714
715 If optional FILE is nil or omitted, return the relative path of
716 the file being visited in the current buffer, if any, else nil.
717 If the file is not inside a Git repository, then return nil.
718
719 If TRACKED is non-nil, return the path only if it matches a
720 tracked file."
721   (unless file
722     (with-current-buffer (or (buffer-base-buffer)
723                              (current-buffer))
724       (setq file (or magit-buffer-file-name buffer-file-name
725                      (and (derived-mode-p 'dired-mode) default-directory)))))
726   (when (and file (or (not tracked)
727                       (magit-file-tracked-p (file-relative-name file))))
728     (--when-let (magit-toplevel
729                  (magit--safe-default-directory
730                   (directory-file-name (file-name-directory file))))
731       (file-relative-name file it))))
732
733 (defun magit-file-tracked-p (file)
734   (magit-git-success "ls-files" "--error-unmatch" file))
735
736 (defun magit-list-files (&rest args)
737   (apply #'magit-git-items "ls-files" "-z" "--full-name" args))
738
739 (defun magit-tracked-files ()
740   (magit-list-files "--cached"))
741
742 (defun magit-untracked-files (&optional all files)
743   (magit-list-files "--other" (unless all "--exclude-standard") "--" files))
744
745 (defun magit-unstaged-files (&optional nomodules files)
746   (magit-git-items "diff-files" "-z" "--name-only"
747                    (and nomodules "--ignore-submodules")
748                    "--" files))
749
750 (defun magit-staged-files (&optional nomodules files)
751   (magit-git-items "diff-index" "-z" "--name-only" "--cached"
752                    (and nomodules "--ignore-submodules")
753                    (magit-headish) "--" files))
754
755 (defun magit-binary-files (&rest args)
756   (--mapcat (and (string-match "^-\t-\t\\(.+\\)" it)
757                  (list (match-string 1 it)))
758             (apply #'magit-git-items
759                    "diff" "-z" "--numstat" "--ignore-submodules"
760                    args)))
761
762 (defun magit-unmerged-files ()
763   (magit-git-items "diff-files" "-z" "--name-only" "--diff-filter=U"))
764
765 (defun magit-ignored-files ()
766   (magit-git-items "ls-files" "-z" "--others" "--ignored"
767                    "--exclude-standard" "--directory"))
768
769 (defun magit-revision-files (rev)
770   (magit-with-toplevel
771     (magit-git-items "ls-tree" "-z" "-r" "--name-only" rev)))
772
773 (defun magit-changed-files (rev-or-range &optional other-rev)
774   "Return list of files the have changed between two revisions.
775 If OTHER-REV is non-nil, REV-OR-RANGE should be a revision, not a
776 range.  Otherwise, it can be any revision or range accepted by
777 \"git diff\" (i.e., <rev>, <revA>..<revB>, or <revA>...<revB>)."
778   (magit-with-toplevel
779     (magit-git-items "diff" "-z" "--name-only" rev-or-range other-rev)))
780
781 (defun magit-renamed-files (revA revB)
782   (--map (cons (nth 1 it) (nth 2 it))
783          (-partition 3 (magit-git-items
784                         "diff-tree" "-r" "--diff-filter=R" "-z" "-M"
785                         revA revB))))
786
787 (defun magit-file-status (&rest args)
788   (with-temp-buffer
789     (save-excursion (magit-git-insert "status" "-z" args))
790     (let ((pos (point)) status)
791       (while (> (skip-chars-forward "[:print:]") 0)
792         (let ((x (char-after     pos))
793               (y (char-after (1+ pos)))
794               (file (buffer-substring (+ pos 3) (point))))
795           (forward-char)
796           (if (memq x '(?R ?C))
797               (progn
798                 (setq pos (point))
799                 (skip-chars-forward "[:print:]")
800                 (push (list file (buffer-substring pos (point)) x y) status)
801                 (forward-char))
802             (push (list file nil x y) status)))
803         (setq pos (point)))
804       status)))
805
806 (defcustom magit-cygwin-mount-points
807   (when (eq system-type 'windows-nt)
808     (cl-sort (--map (if (string-match "^\\(.*\\) on \\(.*\\) type" it)
809                         (cons (file-name-as-directory (match-string 2 it))
810                               (file-name-as-directory (match-string 1 it)))
811                       (lwarn '(magit) :error
812                              "Failed to parse Cygwin mount: %S" it))
813                     ;; If --exec-path is not a native Windows path,
814                     ;; then we probably have a cygwin git.
815                     (let ((process-environment
816                            (append magit-git-environment process-environment)))
817                       (and (not (string-match-p
818                                  "\\`[a-zA-Z]:"
819                                  (car (process-lines
820                                        magit-git-executable "--exec-path"))))
821                            (ignore-errors (process-lines "mount")))))
822              #'> :key (pcase-lambda (`(,cyg . ,_win)) (length cyg))))
823   "Alist of (CYGWIN . WIN32) directory names.
824 Sorted from longest to shortest CYGWIN name."
825   :package-version '(magit . "2.3.0")
826   :group 'magit-process
827   :type '(alist :key-type string :value-type directory))
828
829 (defun magit-expand-git-file-name (filename)
830   (unless (file-name-absolute-p filename)
831     (setq filename (expand-file-name filename)))
832   (-if-let ((cyg . win)
833             (cl-assoc filename magit-cygwin-mount-points
834                       :test (lambda (f cyg) (string-prefix-p cyg f))))
835       (concat win (substring filename (length cyg)))
836     filename))
837
838 (defun magit-convert-filename-for-git (filename)
839   "Convert FILENAME so that it can be passed to git.
840 1. If it's a remote filename, then remove the remote part.
841 2. Deal with an `windows-nt' Emacs vs. Cygwin Git incompatibility."
842   (if (file-name-absolute-p filename)
843       (-if-let ((cyg . win)
844                 (cl-rassoc filename magit-cygwin-mount-points
845                            :test (lambda (f win) (string-prefix-p win f))))
846           (concat cyg (substring filename (length win)))
847         (or (file-remote-p filename 'localname)
848             filename))
849     filename))
850
851 (defun magit-decode-git-path (path)
852   (if (eq (aref path 0) ?\")
853       (decode-coding-string (read path)
854                             (or magit-git-output-coding-system
855                                 (car default-process-coding-system))
856                             t)
857     path))
858
859 (defun magit-file-at-point ()
860   (magit-section-case
861     (file (oref it value))
862     (hunk (magit-section-parent-value it))))
863
864 (defun magit-current-file ()
865   (or (magit-file-relative-name)
866       (magit-file-at-point)
867       (and (derived-mode-p 'magit-log-mode)
868            (car (nth 2 magit-refresh-args)))))
869
870 ;;; Predicates
871
872 (defun magit-no-commit-p ()
873   "Return t if there is no commit in the current Git repository."
874   (not (magit-rev-verify "HEAD")))
875
876 (defun magit-merge-commit-p (commit)
877   "Return t if COMMIT is a merge commit."
878   (> (length (magit-commit-parents commit)) 1))
879
880 (defun magit-anything-staged-p (&optional ignore-submodules &rest files)
881   "Return t if there are any staged changes.
882 If optional FILES is non-nil, then only changes to those files
883 are considered."
884   (magit-git-failure "diff" "--quiet" "--cached"
885                      (and ignore-submodules "--ignore-submodules")
886                      "--" files))
887
888 (defun magit-anything-unstaged-p (&optional ignore-submodules &rest files)
889   "Return t if there are any unstaged changes.
890 If optional FILES is non-nil, then only changes to those files
891 are considered."
892   (magit-git-failure "diff" "--quiet"
893                      (and ignore-submodules "--ignore-submodules")
894                      "--" files))
895
896 (defun magit-anything-modified-p (&optional ignore-submodules &rest files)
897   "Return t if there are any staged or unstaged changes.
898 If optional FILES is non-nil, then only changes to those files
899 are considered."
900   (or (apply 'magit-anything-staged-p   ignore-submodules files)
901       (apply 'magit-anything-unstaged-p ignore-submodules files)))
902
903 (defun magit-anything-unmerged-p (&rest files)
904   "Return t if there are any merge conflicts.
905 If optional FILES is non-nil, then only conflicts in those files
906 are considered."
907   (and (magit-git-string "ls-files" "--unmerged" files) t))
908
909 (defun magit-module-worktree-p (module)
910   (magit-with-toplevel
911     (file-exists-p (expand-file-name (expand-file-name ".git" module)))))
912
913 (defun magit-module-no-worktree-p (module)
914   (not (magit-module-worktree-p module)))
915
916 (defun magit-ignore-submodules-p ()
917   (cl-find-if (lambda (arg)
918                 (string-prefix-p "--ignore-submodules" arg))
919               magit-diff-section-arguments))
920
921 ;;; Revisions and References
922
923 (defun magit-rev-parse (&rest args)
924   "Execute `git rev-parse ARGS', returning first line of output.
925 If there is no output, return nil."
926   (apply #'magit-git-string "rev-parse" args))
927
928 (defun magit-rev-parse-safe (&rest args)
929   "Execute `git rev-parse ARGS', returning first line of output.
930 If there is no output, return nil.  Like `magit-rev-parse' but
931 ignore `magit-git-debug'."
932   (apply #'magit-git-str "rev-parse" args))
933
934 (defun magit-rev-parse-true (&rest args)
935   "Execute `git rev-parse ARGS', returning t if it prints \"true\".
936 If it prints \"false\", then return nil.  For any other output
937 signal an error."
938   (magit-git-true "rev-parse" args))
939
940 (defun magit-rev-parse-false (&rest args)
941   "Execute `git rev-parse ARGS', returning t if it prints \"false\".
942 If it prints \"true\", then return nil.  For any other output
943 signal an error."
944   (magit-git-false "rev-parse" args))
945
946 (defun magit-rev-parse-p (&rest args)
947   "Execute `git rev-parse ARGS', returning t if it prints \"true\".
948 Return t if the first (and usually only) output line is the
949 string \"true\", otherwise return nil."
950   (equal (magit-git-str "rev-parse" args) "true"))
951
952 (defun magit-rev-verify (rev)
953   (magit-rev-parse-safe "--verify" rev))
954
955 (defun magit-rev-verify-commit (rev)
956   "Return full hash for REV if it names an existing commit."
957   (magit-rev-verify (concat rev "^{commit}")))
958
959 (defun magit-rev-equal (a b)
960   (magit-git-success "diff" "--quiet" a b))
961
962 (defun magit-rev-eq (a b)
963   (let ((a (magit-rev-verify a))
964         (b (magit-rev-verify b)))
965     (and a b (equal a b))))
966
967 (defun magit-rev-ancestor-p (a b)
968   "Return non-nil if commit A is an ancestor of commit B."
969   (magit-git-success "merge-base" "--is-ancestor" a b))
970
971 (defun magit-rev-head-p (rev)
972   (or (equal rev "HEAD")
973       (and rev
974            (not (string-match-p "\\.\\." rev))
975            (equal (magit-rev-parse rev)
976                   (magit-rev-parse "HEAD")))))
977
978 (defun magit-rev-author-p (rev)
979   "Return t if the user is the author of REV.
980 More precisely return t if `user.name' is equal to the author
981 name of REV and/or `user.email' is equal to the author email
982 of REV."
983   (or (equal (magit-get "user.name")  (magit-rev-format "%an" rev))
984       (equal (magit-get "user.email") (magit-rev-format "%ae" rev))))
985
986 (defun magit-rev-name (rev &optional pattern)
987   "Return a symbolic name for REV.
988 PATTERN is passed to the `--refs' flag of `git-name-rev' and can
989 be used to limit the result to a matching ref.  When structured
990 as \"refs/<subdir>/*\", PATTERN is taken as a namespace.  In this
991 case, the name returned by `git-name-rev' is discarded if it
992 corresponds to a ref outside of the namespace."
993   (--when-let (magit-git-string "name-rev" "--name-only" "--no-undefined"
994                                 (and pattern (concat "--refs=" pattern))
995                                 rev)
996     ;; We can't use name-rev's --exclude to filter out "*/PATTERN"
997     ;; because --exclude wasn't added until Git v2.13.0.
998     (if (and pattern
999              (string-match-p "\\`refs/[^/]+/\\*\\'" pattern))
1000         (let ((namespace (substring pattern 0 -1)))
1001           (unless (and (string-match-p namespace it)
1002                        (not (magit-rev-verify (concat namespace it))))
1003             it))
1004       it)))
1005
1006 (defun magit-rev-branch (rev)
1007   (--when-let (magit-rev-name rev "refs/heads/*")
1008     (unless (string-match-p "[~^]" it) it)))
1009
1010 (defun magit-get-shortname (rev)
1011   (let* ((fn (apply-partially 'magit-rev-name rev))
1012          (name (or (funcall fn "refs/tags/*")
1013                    (funcall fn "refs/heads/*")
1014                    (funcall fn "refs/remotes/*"))))
1015     (cond ((not name)
1016            (magit-rev-parse "--short" rev))
1017           ((string-match "^\\(?:tags\\|remotes\\)/\\(.+\\)" name)
1018            (if (magit-ref-ambiguous-p (match-string 1 name))
1019                name
1020              (match-string 1 name)))
1021           (t (magit-ref-maybe-qualify name)))))
1022
1023 (defun magit-name-branch (rev &optional lax)
1024   (or (magit-name-local-branch rev)
1025       (magit-name-remote-branch rev)
1026       (and lax (or (magit-name-local-branch rev t)
1027                    (magit-name-remote-branch rev t)))))
1028
1029 (defun magit-name-local-branch (rev &optional lax)
1030   (--when-let (magit-rev-name rev "refs/heads/*")
1031     (and (or lax (not (string-match-p "[~^]" it))) it)))
1032
1033 (defun magit-name-remote-branch (rev &optional lax)
1034   (--when-let (magit-rev-name rev "refs/remotes/*")
1035     (and (or lax (not (string-match-p "[~^]" it)))
1036          (substring it 8))))
1037
1038 (defun magit-name-tag (rev &optional lax)
1039   (--when-let (magit-rev-name rev "refs/tags/*")
1040     (and (or lax (not (string-match-p "[~^]" it)))
1041          (substring it 5))))
1042
1043 (defun magit-ref-fullname (name)
1044   "Return fully qualified refname for NAME.
1045 If NAME is ambiguous, return nil.  NAME may include suffixes such
1046 as \"^1\" and \"~3\".  "
1047   (save-match-data
1048     (if (string-match "\\`\\([^^~]+\\)\\(.*\\)" name)
1049         (--when-let (magit-rev-parse "--symbolic-full-name"
1050                                      (match-string 1 name))
1051           (concat it (match-string 2 name)))
1052       (error "`name' has an unrecognized format"))))
1053
1054 (defun magit-ref-ambiguous-p (name)
1055   (not (magit-ref-fullname name)))
1056
1057 (cl-defun magit-ref-maybe-qualify (name &optional (prefix "heads/"))
1058   "If NAME is ambiguous, prepend PREFIX to it."
1059   (concat (and (magit-ref-ambiguous-p name)
1060                prefix)
1061           name))
1062
1063 (defun magit-ref-exists-p (ref)
1064   (magit-git-success "show-ref" "--verify" ref))
1065
1066 (defun magit-ref-equal (a b)
1067   "Return t if the refs A and B are `equal'.
1068 A symbolic-ref pointing to some ref, is `equal' to that ref,
1069 as are two symbolic-refs pointing to the same ref."
1070   (equal (magit-ref-fullname a)
1071          (magit-ref-fullname b)))
1072
1073 (defun magit-ref-eq (a b)
1074   "Return t if the refs A and B are `eq'.
1075 A symbolic-ref is `eq' to itself, but not to the ref it points
1076 to, or to some other symbolic-ref that points to the same ref."
1077   (let ((symbolic-a (magit-symbolic-ref-p a))
1078         (symbolic-b (magit-symbolic-ref-p b)))
1079     (or (and symbolic-a
1080              symbolic-b
1081              (equal a b))
1082         (and (not symbolic-a)
1083              (not symbolic-b)
1084              (magit-ref-equal a b)))))
1085
1086 (defun magit-headish ()
1087   "Return \"HEAD\" or if that doesn't exist the hash of the empty tree."
1088   (if (magit-no-commit-p)
1089       (magit-git-string "mktree")
1090     "HEAD"))
1091
1092 (defun magit-branch-at-point ()
1093   (magit-section-case
1094     (branch (oref it value))
1095     (commit (or (magit--painted-branch-at-point)
1096                 (magit-name-branch (oref it value))))))
1097
1098 (defun magit--painted-branch-at-point (&optional type)
1099   (or (and (not (eq type 'remote))
1100            (memq (get-text-property (point) 'face)
1101                  (list 'magit-branch-local
1102                        'magit-branch-current))
1103            (cdr (magit-split-branch-name
1104                  (thing-at-point 'git-revision t))))
1105       (and (not (eq type 'local))
1106            (memq (get-text-property (point) 'face)
1107                  (list 'magit-branch-remote
1108                        'magit-branch-remote-head))
1109            (thing-at-point 'git-revision t))))
1110
1111 (defun magit-local-branch-at-point ()
1112   (magit-section-case
1113     (branch (let ((branch (magit-ref-maybe-qualify (oref it value))))
1114               (when (member branch (magit-list-local-branch-names))
1115                 branch)))
1116     (commit (or (magit--painted-branch-at-point 'local)
1117                 (magit-name-local-branch (oref it value))))))
1118
1119 (defun magit-remote-branch-at-point ()
1120   (magit-section-case
1121     (branch (let ((branch (oref it value)))
1122               (when (member branch (magit-list-remote-branch-names))
1123                 branch)))
1124     (commit (or (magit--painted-branch-at-point 'remote)
1125                 (magit-name-remote-branch (oref it value))))))
1126
1127 (defun magit-commit-at-point ()
1128   (or (magit-section-value-if 'commit)
1129       (and (derived-mode-p 'magit-revision-mode)
1130            (car magit-refresh-args))))
1131
1132 (defun magit-branch-or-commit-at-point ()
1133   (or magit-buffer-refname
1134       (magit-section-case
1135         (branch (magit-ref-maybe-qualify (oref it value)))
1136         (commit (or (magit--painted-branch-at-point)
1137                     (let ((rev (oref it value)))
1138                       (or (magit-name-branch rev)
1139                           (magit-get-shortname rev)
1140                           rev))))
1141         (tag (magit-ref-maybe-qualify (oref it value) "tags/")))
1142       (thing-at-point 'git-revision t)
1143       (and (derived-mode-p 'magit-revision-mode
1144                            'magit-merge-preview-mode)
1145            (car magit-refresh-args))))
1146
1147 (defun magit-tag-at-point ()
1148   (magit-section-case
1149     (tag    (oref it value))
1150     (commit (magit-name-tag (oref it value)))))
1151
1152 (defun magit-stash-at-point ()
1153   (magit-section-value-if 'stash))
1154
1155 (defun magit-remote-at-point ()
1156   (magit-section-case
1157     (remote (oref it value))
1158     (branch (magit-section-parent-value it))))
1159
1160 (defun magit-module-at-point (&optional predicate)
1161   (when (magit-section-match 'magit-module-section)
1162     (let ((module (oref (magit-current-section) value)))
1163       (and (or (not predicate)
1164                (funcall predicate module))
1165            module))))
1166
1167 (defun magit-get-current-branch ()
1168   "Return the refname of the currently checked out branch.
1169 Return nil if no branch is currently checked out."
1170   (magit-git-string "symbolic-ref" "--short" "HEAD"))
1171
1172 (defvar magit-get-previous-branch-timeout 0.5
1173   "Maximum time to spend in `magit-get-previous-branch'.
1174 Given as a number of seconds.")
1175
1176 (defun magit-get-previous-branch ()
1177   "Return the refname of the previously checked out branch.
1178 Return nil if no branch can be found in the `HEAD' reflog
1179 which is different from the current branch and still exists.
1180 The amount of time spent searching is limited by
1181 `magit-get-previous-branch-timeout'."
1182   (let ((t0 (float-time))
1183         (current (magit-get-current-branch))
1184         (i 1) prev)
1185     (while (if (> (- (float-time) t0) magit-get-previous-branch-timeout)
1186                (setq prev nil) ;; Timed out.
1187              (and (setq prev (magit-rev-verify (format "@{-%i}" i)))
1188                   (or (not (setq prev (magit-rev-branch prev)))
1189                       (equal prev current))))
1190       (cl-incf i))
1191     prev))
1192
1193 (defun magit-get-upstream-ref (&optional branch)
1194   (and (or branch (setq branch (magit-get-current-branch)))
1195        (let ((remote (magit-get "branch" branch "remote"))
1196              (merge  (magit-get "branch" branch "merge")))
1197          (when (and remote merge)
1198            (cond ((string-equal remote ".") merge)
1199                  ((string-prefix-p "refs/heads/" merge)
1200                   (concat "refs/remotes/" remote "/" (substring merge 11))))))))
1201
1202 (defun magit-set-upstream-branch (branch upstream)
1203   (if upstream
1204       (pcase-let ((`(,remote . ,merge) (magit-split-branch-name upstream)))
1205         (setf (magit-get (format "branch.%s.remote" branch)) remote)
1206         (setf (magit-get (format "branch.%s.merge"  branch))
1207               (concat "refs/heads/" merge)))
1208     (magit-call-git "branch" "--unset-upstream" branch)))
1209
1210 (defun magit-get-upstream-branch (&optional branch verify)
1211   (and (or branch (setq branch (magit-get-current-branch)))
1212        (when-let ((remote (magit-get "branch" branch "remote"))
1213                   (merge  (magit-get "branch" branch "merge")))
1214          (and (string-prefix-p "refs/heads/" merge)
1215               (let* ((upstream (substring merge 11))
1216                      (upstream
1217                       (cond ((string-equal remote ".")
1218                              (propertize upstream 'face 'magit-branch-local))
1219                             ((string-match-p "[@:]" remote)
1220                              (propertize (concat remote " " upstream)
1221                                          'face 'magit-branch-remote))
1222                             (t
1223                              (propertize (concat remote "/" upstream)
1224                                          'face 'magit-branch-remote)))))
1225                 (and (or (not verify)
1226                          (magit-rev-verify upstream))
1227                      upstream))))))
1228
1229 (defun magit-get-indirect-upstream-branch (branch &optional force)
1230   (let ((remote (magit-get "branch" branch "remote")))
1231     (and remote (not (equal remote "."))
1232          ;; The user has opted in...
1233          (or force
1234              (--some (if (magit-git-success "check-ref-format" "--branch" it)
1235                          (equal it branch)
1236                        (string-match-p it branch))
1237                      magit-branch-prefer-remote-upstream))
1238          ;; and local BRANCH tracks a remote branch...
1239          (let ((upstream (magit-get-upstream-branch branch)))
1240            ;; whose upstream...
1241            (and upstream
1242                 ;; has the same name as BRANCH and...
1243                 (equal (substring upstream (1+ (length remote))) branch)
1244                 ;; and can be fast-forwarded to BRANCH.
1245                 (magit-rev-ancestor-p upstream branch)
1246                 upstream)))))
1247
1248 (defun magit-get-upstream-remote (&optional branch non-local)
1249   (unless branch
1250     (setq branch (magit-get-current-branch)))
1251   (and branch
1252        (let ((remote (magit-get "branch" branch "remote")))
1253          (and (not (and non-local (equal remote ".")))
1254               remote))))
1255
1256 (defun magit-get-push-remote (&optional branch)
1257   (or (and (or branch (setq branch (magit-get-current-branch)))
1258            (magit-get "branch" branch "pushRemote"))
1259       (magit-get "remote.pushDefault")))
1260
1261 (defun magit-get-push-branch (&optional branch verify)
1262   (and (or branch (setq branch (magit-get-current-branch)))
1263        (when-let ((remote (magit-get-push-remote branch))
1264                   (push-branch (concat remote "/" branch)))
1265          (and (or (not verify)
1266                   (magit-rev-verify push-branch))
1267               (propertize push-branch 'face 'magit-branch-remote)))))
1268
1269 (defun magit-get-@{push}-branch (&optional branch)
1270   (let ((ref (magit-rev-parse "--symbolic-full-name"
1271                               (concat branch "@{push}"))))
1272     (when (and ref (string-prefix-p "refs/remotes/" ref))
1273       (substring ref 13))))
1274
1275 (defun magit-get-remote (&optional branch)
1276   (when (or branch (setq branch (magit-get-current-branch)))
1277     (let ((remote (magit-get "branch" branch "remote")))
1278       (unless (equal remote ".")
1279         remote))))
1280
1281 (defun magit-get-some-remote (&optional branch)
1282   (or (magit-get-remote branch)
1283       (and (magit-branch-p "master")
1284            (magit-get-remote "master"))
1285       (let ((remotes (magit-list-remotes)))
1286         (or (car (member "origin" remotes))
1287             (car remotes)))))
1288
1289 (defun magit-branch-merged-p (branch &optional target)
1290   "Return non-nil if BRANCH is merged into its upstream and TARGET.
1291
1292 TARGET defaults to the current branch.  If `HEAD' is detached and
1293 TARGET is nil, then always return nil.  As a special case, if
1294 TARGET is t, then return non-nil if BRANCH is merged into any one
1295 of the other local branches.
1296
1297 If, and only if, BRANCH has an upstream, then only return non-nil
1298 if BRANCH is merged into both TARGET (as described above) as well
1299 as into its upstream."
1300   (and (--if-let (and (magit-branch-p branch)
1301                       (magit-get-upstream-branch branch))
1302            (magit-git-success "merge-base" "--is-ancestor" branch it)
1303          t)
1304        (if (eq target t)
1305            (delete (magit-name-local-branch branch)
1306                    (magit-list-containing-branches branch))
1307          (--when-let (or target (magit-get-current-branch))
1308            (magit-git-success "merge-base" "--is-ancestor" branch it)))))
1309
1310 (defun magit-split-branch-name (branch)
1311   (cond ((member branch (magit-list-local-branch-names))
1312          (cons "." branch))
1313         ((string-match " " branch)
1314          (pcase-let ((`(,url ,branch) (split-string branch " ")))
1315            (cons url branch)))
1316         ((string-match "/" branch)
1317          (let ((remote (substring branch 0 (match-beginning 0))))
1318            (if (save-match-data (member remote (magit-list-remotes)))
1319                (cons remote (substring branch (match-end 0)))
1320              (error "Invalid branch name %s" branch))))))
1321
1322 (defun magit-get-current-tag (&optional rev with-distance)
1323   "Return the closest tag reachable from REV.
1324
1325 If optional REV is nil, then default to `HEAD'.
1326 If optional WITH-DISTANCE is non-nil then return (TAG COMMITS),
1327 if it is `dirty' return (TAG COMMIT DIRTY). COMMITS is the number
1328 of commits in `HEAD' but not in TAG and DIRTY is t if there are
1329 uncommitted changes, nil otherwise."
1330   (--when-let (magit-git-str "describe" "--long" "--tags"
1331                              (and (eq with-distance 'dirty) "--dirty") rev)
1332     (save-match-data
1333       (string-match
1334        "\\(.+\\)-\\(?:0[0-9]*\\|\\([0-9]+\\)\\)-g[0-9a-z]+\\(-dirty\\)?$" it)
1335       (if with-distance
1336           `(,(match-string 1 it)
1337             ,(string-to-number (or (match-string 2 it) "0"))
1338             ,@(and (match-string 3 it) (list t)))
1339         (match-string 1 it)))))
1340
1341 (defun magit-get-next-tag (&optional rev with-distance)
1342   "Return the closest tag from which REV is reachable.
1343
1344 If optional REV is nil, then default to `HEAD'.
1345 If no such tag can be found or if the distance is 0 (in which
1346 case it is the current tag, not the next), return nil instead.
1347 If optional WITH-DISTANCE is non-nil, then return (TAG COMMITS)
1348 where COMMITS is the number of commits in TAG but not in REV."
1349   (--when-let (magit-git-str "describe" "--contains" (or rev "HEAD"))
1350     (save-match-data
1351       (when (string-match "^[^^~]+" it)
1352         (setq it (match-string 0 it))
1353         (unless (equal it (magit-get-current-tag rev))
1354           (if with-distance
1355               (list it (car (magit-rev-diff-count it rev)))
1356             it))))))
1357
1358 (defvar magit-list-refs-namespaces
1359   '("refs/heads" "refs/remotes" "refs/tags" "refs/pull"))
1360
1361 (defun magit-list-refs (&optional namespaces format sortby)
1362   "Return list of references.
1363
1364 When NAMESPACES is non-nil, list refs from these namespaces
1365 rather than those from `magit-list-refs-namespaces'.
1366
1367 FORMAT is passed to the `--format' flag of `git for-each-ref'
1368 and defaults to \"%(refname)\".  If the format is \"%(refname)\"
1369 or \"%(refname:short)\", then drop the symbolic-ref \"HEAD\".
1370
1371 SORTBY is a key or list of keys to pass to the `--sort' flag of
1372 `git for-each-ref'.  When nil, use `magit-list-refs-sortby'"
1373   (unless format
1374     (setq format "%(refname)"))
1375   (let ((refs (magit-git-lines "for-each-ref"
1376                                (concat "--format=" format)
1377                                (--map (concat "--sort=" it)
1378                                       (pcase (or sortby magit-list-refs-sortby)
1379                                         ((and val (pred stringp)) (list val))
1380                                         ((and val (pred listp)) val)))
1381                                (or namespaces magit-list-refs-namespaces))))
1382     (if (member format '("%(refname)" "%(refname:short)"))
1383         (--remove (string-match-p "\\(\\`\\|/\\)HEAD\\'" it) refs)
1384       refs)))
1385
1386 (defun magit-list-branches ()
1387   (magit-list-refs (list "refs/heads" "refs/remotes")))
1388
1389 (defun magit-list-local-branches ()
1390   (magit-list-refs "refs/heads"))
1391
1392 (defun magit-list-remote-branches (&optional remote)
1393   (magit-list-refs (concat "refs/remotes/" remote)))
1394
1395 (defun magit-list-related-branches (relation &optional commit arg)
1396   (--remove (string-match-p "\\(\\`(HEAD\\|HEAD -> \\)" it)
1397             (--map (substring it 2)
1398                    (magit-git-lines "branch" arg relation commit))))
1399
1400 (defun magit-list-containing-branches (&optional commit arg)
1401   (magit-list-related-branches "--contains" commit arg))
1402
1403 (defun magit-list-publishing-branches (&optional commit)
1404   (--filter (magit-rev-ancestor-p commit it)
1405             magit-published-branches))
1406
1407 (defun magit-list-merged-branches (&optional commit arg)
1408   (magit-list-related-branches "--merged" commit arg))
1409
1410 (defun magit-list-unmerged-branches (&optional commit arg)
1411   (magit-list-related-branches "--no-merged" commit arg))
1412
1413 (defun magit-list-unmerged-to-upstream-branches ()
1414   (--filter (when-let ((upstream (magit-get-upstream-branch it)))
1415               (member it (magit-list-unmerged-branches upstream)))
1416             (magit-list-local-branch-names)))
1417
1418 (defun magit-list-branches-pointing-at (commit)
1419   (let ((re (format "\\`%s refs/\\(heads\\|remotes\\)/\\(.*\\)\\'"
1420                    (magit-rev-verify commit))))
1421     (--keep (and (string-match re it)
1422                  (let ((name (match-string 2 it)))
1423                    (and (not (string-suffix-p "HEAD" name))
1424                         name)))
1425             (magit-git-lines "show-ref"))))
1426
1427 (defun magit-list-refnames (&optional namespaces)
1428   (magit-list-refs namespaces "%(refname:short)"))
1429
1430 (defun magit-list-branch-names ()
1431   (magit-list-refnames (list "refs/heads" "refs/remotes")))
1432
1433 (defun magit-list-local-branch-names ()
1434   (magit-list-refnames "refs/heads"))
1435
1436 (defun magit-list-remote-branch-names (&optional remote relative)
1437   (if (and remote relative)
1438       (let ((regexp (format "^refs/remotes/%s/\\(.+\\)" remote)))
1439         (--mapcat (when (string-match regexp it)
1440                     (list (match-string 1 it)))
1441                   (magit-list-remote-branches remote)))
1442     (magit-list-refnames (concat "refs/remotes/" remote))))
1443
1444 (defun magit-format-refs (format &rest args)
1445   (let ((lines (magit-git-lines
1446                 "for-each-ref" (concat "--format=" format)
1447                 (or args (list "refs/heads" "refs/remotes" "refs/tags")))))
1448     (if (string-match-p "\f" format)
1449         (--map (split-string it "\f") lines)
1450       lines)))
1451
1452 (defun magit-list-remotes ()
1453   (magit-git-lines "remote"))
1454
1455 (defun magit-list-tags ()
1456   (magit-git-lines "tag"))
1457
1458 (defun magit-list-stashes (&optional format)
1459   (magit-git-lines "stash" "list" (concat "--format=" (or format "%gd"))))
1460
1461 (defun magit-list-active-notes-refs ()
1462   "Return notes refs according to `core.notesRef' and `notes.displayRef'."
1463   (magit-git-lines "for-each-ref" "--format=%(refname)"
1464                    (or (magit-get "core.notesRef") "refs/notes/commits")
1465                    (magit-get-all "notes.displayRef")))
1466
1467 (defun magit-list-notes-refnames ()
1468   (--map (substring it 6) (magit-list-refnames "refs/notes")))
1469
1470 (defun magit-remote-list-tags (remote)
1471   (--keep (and (not (string-match-p "\\^{}$" it))
1472                (substring it 51))
1473           (magit-git-lines "ls-remote" "--tags" remote)))
1474
1475 (defun magit-remote-list-branches (remote)
1476   (--keep (and (not (string-match-p "\\^{}$" it))
1477                (substring it 52))
1478           (magit-git-lines "ls-remote" "--heads" remote)))
1479
1480 (defun magit-remote-list-refs (remote)
1481   (--keep (and (not (string-match-p "\\^{}$" it))
1482                (substring it 41))
1483           (magit-git-lines "ls-remote" remote)))
1484
1485 (defun magit-list-module-paths ()
1486   (--mapcat (and (string-match "^160000 [0-9a-z]\\{40\\} 0\t\\(.+\\)$" it)
1487                  (list (match-string 1 it)))
1488             (magit-git-items "ls-files" "-z" "--stage")))
1489
1490 (defun magit-get-submodule-name (path)
1491   "Return the name of the submodule at PATH.
1492 PATH has to be relative to the super-repository."
1493   (cadr (split-string
1494          (car (or (magit-git-items
1495                    "config" "-z"
1496                    "-f" (expand-file-name ".gitmodules" (magit-toplevel))
1497                    "--get-regexp" "^submodule\\..*\\.path$"
1498                    (concat "^" (regexp-quote (directory-file-name path)) "$"))
1499                   (error "No such submodule `%s'" path)))
1500          "\n")))
1501
1502 (defun magit-list-worktrees ()
1503   (let (worktrees worktree)
1504     (dolist (line (let ((magit-git-global-arguments
1505                          ;; KLUDGE At least in v2.8.3 this triggers a segfault.
1506                          (remove "--no-pager" magit-git-global-arguments)))
1507                     (magit-git-lines "worktree" "list" "--porcelain")))
1508       (cond ((string-prefix-p "worktree" line)
1509              (push (setq worktree (list (substring line 9) nil nil nil))
1510                    worktrees))
1511             ((string-equal line "bare")
1512              (let* ((default-directory (car worktree))
1513                     (wt (and (not (magit-get-boolean "core.bare"))
1514                              (magit-get "core.worktree"))))
1515                (if (and wt (file-exists-p (expand-file-name wt)))
1516                    (progn (setf (nth 0 worktree) (expand-file-name wt))
1517                           (setf (nth 2 worktree) (magit-rev-parse "HEAD"))
1518                           (setf (nth 3 worktree) (magit-get-current-branch)))
1519                  (setf (nth 1 worktree) t))))
1520             ((string-prefix-p "HEAD" line)
1521              (setf (nth 2 worktree) (substring line 5)))
1522             ((string-prefix-p "branch" line)
1523              (setf (nth 3 worktree) (substring line 18)))
1524             ((string-equal line "detached"))))
1525     (nreverse worktrees)))
1526
1527 (defun magit-symbolic-ref-p (name)
1528   (magit-git-success "symbolic-ref" "--quiet" name))
1529
1530 (defun magit-ref-p (rev)
1531   (or (car (member rev (magit-list-refs)))
1532       (car (member rev (magit-list-refnames)))))
1533
1534 (defun magit-branch-p (rev)
1535   (or (car (member rev (magit-list-branches)))
1536       (car (member rev (magit-list-branch-names)))))
1537
1538 (defun magit-local-branch-p (rev)
1539   (or (car (member rev (magit-list-local-branches)))
1540       (car (member rev (magit-list-local-branch-names)))))
1541
1542 (defun magit-remote-branch-p (rev)
1543   (or (car (member rev (magit-list-remote-branches)))
1544       (car (member rev (magit-list-remote-branch-names)))))
1545
1546 (defun magit-branch-set-face (branch)
1547   (propertize branch 'face (if (magit-local-branch-p branch)
1548                                'magit-branch-local
1549                              'magit-branch-remote)))
1550
1551 (defun magit-tag-p (rev)
1552   (car (member rev (magit-list-tags))))
1553
1554 (defun magit-remote-p (string)
1555   (car (member string (magit-list-remotes))))
1556
1557 (defun magit-rev-diff-count (a b)
1558   "Return the commits in A but not B and vice versa.
1559 Return a list of two integers: (A>B B>A)."
1560   (mapcar 'string-to-number
1561           (split-string (magit-git-string "rev-list"
1562                                           "--count" "--left-right"
1563                                           (concat a "..." b))
1564                         "\t")))
1565
1566 (defun magit-abbrev-length ()
1567   (--if-let (magit-get "core.abbrev")
1568       (string-to-number it)
1569     ;; Guess the length git will be using based on an example
1570     ;; abbreviation.  Actually HEAD's abbreviation might be an
1571     ;; outlier, so use the shorter of the abbreviations for two
1572     ;; commits.  When a commit does not exist, then fall back
1573     ;; to the default of 7.  See #3034.
1574     (min (--if-let (magit-rev-parse "--short" "HEAD")  (length it) 7)
1575          (--if-let (magit-rev-parse "--short" "HEAD~") (length it) 7))))
1576
1577 (defun magit-abbrev-arg (&optional arg)
1578   (format "--%s=%d" (or arg "abbrev") (magit-abbrev-length)))
1579
1580 (defun magit-rev-abbrev (rev)
1581   (magit-rev-parse (magit-abbrev-arg "short") rev))
1582
1583 (defun magit-commit-children (commit &optional args)
1584   (mapcar #'car
1585           (--filter (member commit (cdr it))
1586                     (--map (split-string it " ")
1587                            (magit-git-lines
1588                             "log" "--format=%H %P"
1589                             (or args (list "--branches" "--tags" "--remotes"))
1590                             "--not" commit)))))
1591
1592 (defun magit-commit-parents (commit)
1593   (--when-let (magit-git-string "rev-list" "-1" "--parents" commit)
1594     (cdr (split-string it))))
1595
1596 (defun magit-patch-id (rev)
1597   (with-temp-buffer
1598     (magit-process-file
1599      shell-file-name nil '(t nil) nil shell-command-switch
1600      (let ((exec (shell-quote-argument magit-git-executable)))
1601        (format "%s diff-tree -u %s | %s patch-id" exec rev exec)))
1602     (car (split-string (buffer-string)))))
1603
1604 (defun magit-rev-format (format &optional rev args)
1605   (let ((str (magit-git-string "show" "--no-patch"
1606                                (concat "--format=" format) args
1607                                (if rev (concat rev "^{commit}") "HEAD") "--")))
1608     (unless (string-equal str "")
1609       str)))
1610
1611 (defun magit-rev-insert-format (format &optional rev args)
1612   (magit-git-insert "show" "--no-patch"
1613                     (concat "--format=" format) args
1614                     (if rev (concat rev "^{commit}") "HEAD") "--"))
1615
1616 (defun magit-format-rev-summary (rev)
1617   (--when-let (magit-rev-format "%h %s" rev)
1618     (string-match " " it)
1619     (put-text-property 0 (match-beginning 0) 'face 'magit-hash it)
1620     it))
1621
1622 (defvar magit-ref-namespaces
1623   '(("\\`HEAD\\'"                  . magit-head)
1624     ("\\`refs/tags/\\(.+\\)"       . magit-tag)
1625     ("\\`refs/heads/\\(.+\\)"      . magit-branch-local)
1626     ("\\`refs/remotes/\\(.+\\)"    . magit-branch-remote)
1627     ("\\`refs/bisect/\\(bad\\)"    . magit-bisect-bad)
1628     ("\\`refs/bisect/\\(skip.*\\)" . magit-bisect-skip)
1629     ("\\`refs/bisect/\\(good.*\\)" . magit-bisect-good)
1630     ("\\`refs/stash$"              . magit-refname-stash)
1631     ("\\`refs/wip/\\(.+\\)"        . magit-refname-wip)
1632     ("\\`refs/pullreqs/\\(.+\\)"   . magit-refname-pullreq)
1633     ("\\`\\(bad\\):"               . magit-bisect-bad)
1634     ("\\`\\(skip\\):"              . magit-bisect-skip)
1635     ("\\`\\(good\\):"              . magit-bisect-good)
1636     ("\\`\\(.+\\)"                 . magit-refname))
1637   "How refs are formatted for display.
1638
1639 Each entry controls how a certain type of ref is displayed, and
1640 has the form (REGEXP . FACE).  REGEXP is a regular expression
1641 used to match full refs.  The first entry whose REGEXP matches
1642 the reference is used.
1643
1644 In log and revision buffers the first regexp submatch becomes the
1645 \"label\" that represents the ref and is propertized with FONT.
1646 In refs buffers the displayed text is controlled by other means
1647 and this option only controls what face is used.")
1648
1649 (defun magit-format-ref-labels (string)
1650   ;; To support Git <2.2.0, we remove the surrounding parentheses here
1651   ;; rather than specifying that STRING should be generated with Git's
1652   ;; "%D" placeholder.
1653   (setq string (->> string
1654                     (replace-regexp-in-string "\\`\\s-*(" "")
1655                     (replace-regexp-in-string ")\\s-*\\'" "")))
1656   (save-match-data
1657     (let ((regexp "\\(, \\|tag: \\|HEAD -> \\)")
1658           names)
1659       (if (and (derived-mode-p 'magit-log-mode)
1660                (member "--simplify-by-decoration" (cadr magit-refresh-args)))
1661           (let ((branches (magit-list-local-branch-names))
1662                 (re (format "^%s/.+" (regexp-opt (magit-list-remotes)))))
1663             (setq names
1664                   (--map (cond ((string-equal it "HEAD")     it)
1665                                ((string-prefix-p "refs/" it) it)
1666                                ((member it branches) (concat "refs/heads/" it))
1667                                ((string-match re it) (concat "refs/remotes/" it))
1668                                (t                    (concat "refs/" it)))
1669                          (split-string
1670                           (replace-regexp-in-string "tag: " "refs/tags/" string)
1671                           regexp t))))
1672         (setq names (split-string string regexp t)))
1673       (let (state head upstream tags branches remotes other combined)
1674         (dolist (ref names)
1675           (let* ((face (cdr (--first (string-match (car it) ref)
1676                                      magit-ref-namespaces)))
1677                  (name (propertize (or (match-string 1 ref) ref) 'face face)))
1678             (cl-case face
1679               ((magit-bisect-bad magit-bisect-skip magit-bisect-good)
1680                (setq state name))
1681               (magit-head
1682                (setq head (propertize "@" 'face 'magit-head)))
1683               (magit-tag            (push name tags))
1684               (magit-branch-local   (push name branches))
1685               (magit-branch-remote  (push name remotes))
1686               (t                    (push name other)))))
1687         (setq remotes
1688               (-keep
1689                (lambda (name)
1690                  (if (string-match "\\`\\([^/]*\\)/\\(.*\\)\\'" name)
1691                      (let ((r (match-string 1 name))
1692                            (b (match-string 2 name)))
1693                        (and (not (equal b "HEAD"))
1694                             (if (equal (concat "refs/remotes/" name)
1695                                        (magit-git-string
1696                                         "symbolic-ref"
1697                                         (format "refs/remotes/%s/HEAD" r)))
1698                                 (propertize name
1699                                             'face 'magit-branch-remote-head)
1700                               name)))
1701                    name))
1702                remotes))
1703         (let* ((current (magit-get-current-branch))
1704                (target  (magit-get-upstream-branch current t)))
1705           (dolist (name branches)
1706             (let ((push (car (member (magit-get-push-branch name) remotes))))
1707               (when push
1708                 (setq remotes (delete push remotes))
1709                 (string-match "^[^/]*/" push)
1710                 (setq push (substring push 0 (match-end 0))))
1711               (cond
1712                ((equal name current)
1713                 (setq head
1714                       (concat push
1715                               (propertize name 'face 'magit-branch-current))))
1716                ((equal name target)
1717                 (setq upstream
1718                       (concat push
1719                               (propertize name 'face '(magit-branch-upstream
1720                                                        magit-branch-local)))))
1721                (t
1722                 (push (concat push name) combined)))))
1723           (when (and target (not upstream))
1724             (if (member target remotes)
1725                 (progn
1726                   (add-face-text-property 0 (length target)
1727                                           'magit-branch-upstream nil target)
1728                   (setq upstream target)
1729                   (setq remotes  (delete target remotes)))
1730               (when-let ((target (car (member target combined))))
1731                 (add-face-text-property 0 (length target)
1732                                         'magit-branch-upstream nil target)
1733                 (setq upstream target)
1734                 (setq combined (delete target combined))))))
1735         (mapconcat #'identity
1736                    (-flatten `(,state
1737                                ,head
1738                                ,upstream
1739                                ,@(nreverse tags)
1740                                ,@(nreverse combined)
1741                                ,@(nreverse remotes)
1742                                ,@other))
1743                    " ")))))
1744
1745 (defun magit-object-type (object)
1746   (magit-git-string "cat-file" "-t" object))
1747
1748 (defmacro magit-with-blob (commit file &rest body)
1749   (declare (indent 2)
1750            (debug (form form body)))
1751   `(with-temp-buffer
1752      (let ((buffer-file-name ,file))
1753        (save-excursion
1754          (magit-git-insert "cat-file" "-p"
1755                            (concat ,commit ":" buffer-file-name)))
1756        (decode-coding-inserted-region
1757         (point-min) (point-max) buffer-file-name t nil nil t)
1758        ,@body)))
1759
1760 (defmacro magit-with-temp-index (tree arg &rest body)
1761   (declare (indent 2) (debug (form form body)))
1762   (let ((file (cl-gensym "file")))
1763     `(let ((magit--refresh-cache nil)
1764            (,file (magit-convert-filename-for-git
1765                    (make-temp-name (magit-git-dir "index.magit.")))))
1766        (unwind-protect
1767            (magit-with-toplevel
1768              (--when-let ,tree
1769                (or (magit-git-success "read-tree" ,arg it
1770                                       (concat "--index-output=" ,file))
1771                    (error "Cannot read tree %s" it)))
1772              (if (file-remote-p default-directory)
1773                  (let ((magit-tramp-process-environment
1774                         (cons (concat "GIT_INDEX_FILE=" ,file)
1775                               magit-tramp-process-environment)))
1776                    ,@body)
1777                (let ((process-environment
1778                       (cons (concat "GIT_INDEX_FILE=" ,file)
1779                             process-environment)))
1780                  ,@body)))
1781          (ignore-errors
1782            (delete-file (concat (file-remote-p default-directory) ,file)))))))
1783
1784 (defun magit-commit-tree (message &optional tree &rest parents)
1785   (magit-git-string "commit-tree" "--no-gpg-sign" "-m" message
1786                     (--mapcat (list "-p" it) (delq nil parents))
1787                     (or tree
1788                         (magit-git-string "write-tree")
1789                         (error "Cannot write tree"))))
1790
1791 (defun magit-commit-worktree (message &optional arg &rest other-parents)
1792   (magit-with-temp-index "HEAD" arg
1793     (and (magit-update-files (magit-unstaged-files))
1794          (apply #'magit-commit-tree message nil "HEAD" other-parents))))
1795
1796 (defun magit-update-files (files)
1797   (magit-git-success "update-index" "--add" "--remove" "--" files))
1798
1799 (defun magit-update-ref (ref message rev &optional stashish)
1800   (let ((magit--refresh-cache nil))
1801     (or (if (not (version< (magit-git-version) "2.6.0"))
1802             (zerop (magit-call-git "update-ref" "--create-reflog"
1803                                    "-m" message ref rev
1804                                    (or (magit-rev-verify ref) "")))
1805           ;; `--create-reflog' didn't exist before v2.6.0
1806           (let ((oldrev  (magit-rev-verify ref))
1807                 (logfile (magit-git-dir (concat "logs/" ref))))
1808             (unless (file-exists-p logfile)
1809               (when oldrev
1810                 (magit-git-success "update-ref" "-d" ref oldrev))
1811               (make-directory (file-name-directory logfile) t)
1812               (with-temp-file logfile)
1813               (when (and oldrev (not stashish))
1814                 (magit-git-success "update-ref" "-m" "enable reflog"
1815                                    ref oldrev ""))))
1816           (magit-git-success "update-ref" "-m" message ref rev
1817                              (or (magit-rev-verify ref) "")))
1818         (error "Cannot update %s with %s" ref rev))))
1819
1820 (defconst magit-range-re
1821   (concat "\\`\\([^ \t]*[^.]\\)?"       ; revA
1822           "\\(\\.\\.\\.?\\)"            ; range marker
1823           "\\([^.][^ \t]*\\)?\\'"))     ; revB
1824
1825 (defun magit-split-range (range)
1826   (and (string-match magit-range-re range)
1827        (let ((beg (or (match-string 1 range) "HEAD"))
1828              (end (or (match-string 3 range) "HEAD")))
1829          (cons (if (string-equal (match-string 2 range) "...")
1830                    (magit-git-string "merge-base" beg end)
1831                  beg)
1832                end))))
1833
1834 (defvar magit-thingatpt--git-revision-chars "-_./[:alnum:]@{}^~!"
1835   "Characters allowable in filenames, excluding space and colon.")
1836
1837 (put 'git-revision 'end-op
1838      (lambda ()
1839        (re-search-forward
1840         (concat "\\=[" magit-thingatpt--git-revision-chars "]*")
1841         nil t)))
1842
1843 (put 'git-revision 'beginning-op
1844      (lambda ()
1845        (if (re-search-backward
1846             (concat "[^" magit-thingatpt--git-revision-chars "]") nil t)
1847            (forward-char)
1848          (goto-char (point-min)))))
1849
1850 (put 'git-revision 'thing-at-point 'magit-thingatpt--git-revision)
1851
1852 (defun magit-thingatpt--git-revision ()
1853   (--when-let (bounds-of-thing-at-point 'git-revision)
1854     (let ((text (buffer-substring-no-properties (car it) (cdr it))))
1855       (and (magit-rev-verify-commit text) text))))
1856
1857 ;;; Completion
1858
1859 (defvar magit-revision-history nil)
1860
1861 (defun magit-read-branch (prompt &optional secondary-default)
1862   (magit-completing-read prompt (magit-list-branch-names)
1863                          nil t nil 'magit-revision-history
1864                          (or (magit-branch-at-point)
1865                              secondary-default
1866                              (magit-get-current-branch))))
1867
1868 (defun magit-read-branch-or-commit (prompt &optional secondary-default)
1869   (or (magit-completing-read prompt (cons "HEAD" (magit-list-refnames))
1870                              nil nil nil 'magit-revision-history
1871                              (or (magit-branch-or-commit-at-point)
1872                                  secondary-default
1873                                  (magit-get-current-branch)))
1874       (user-error "Nothing selected")))
1875
1876 (defun magit-read-range-or-commit (prompt &optional secondary-default)
1877   (magit-read-range
1878    prompt
1879    (or (--when-let (magit-region-values '(commit branch) t)
1880          (deactivate-mark)
1881          (concat (car (last it)) ".." (car it)))
1882        (magit-branch-or-commit-at-point)
1883        secondary-default
1884        (magit-get-current-branch))))
1885
1886 (defun magit-read-range (prompt &optional default)
1887   (magit-completing-read-multiple prompt
1888                                   (magit-list-refnames)
1889                                   "\\.\\.\\.?"
1890                                   default 'magit-revision-history))
1891
1892 (defun magit-read-remote-branch
1893     (prompt &optional remote default local-branch require-match)
1894   (let ((choice (magit-completing-read
1895                  prompt
1896                  (-union (and local-branch
1897                               (if remote
1898                                   (concat remote "/" local-branch)
1899                                 (--map (concat it "/" local-branch)
1900                                        (magit-list-remotes))))
1901                          (magit-list-remote-branch-names remote t))
1902                  nil require-match nil 'magit-revision-history default)))
1903     (if (or remote (string-match "\\`\\([^/]+\\)/\\(.+\\)" choice))
1904         choice
1905       (user-error "`%s' doesn't have the form REMOTE/BRANCH" choice))))
1906
1907 (defun magit-read-refspec (prompt remote)
1908   (magit-completing-read prompt
1909                          (prog2 (message "Determining available refs...")
1910                              (magit-remote-list-refs remote)
1911                            (message "Determining available refs...done"))))
1912
1913 (defun magit-read-local-branch (prompt &optional secondary-default)
1914   (magit-completing-read prompt (magit-list-local-branch-names)
1915                          nil t nil 'magit-revision-history
1916                          (or (magit-local-branch-at-point)
1917                              secondary-default
1918                              (magit-get-current-branch))))
1919
1920 (defun magit-read-local-branch-or-commit (prompt)
1921   (let ((branches (magit-list-local-branch-names))
1922         (commit (magit-commit-at-point)))
1923     (or (magit-completing-read prompt
1924                                (if commit (cons commit branches) branches)
1925                                nil nil nil 'magit-revision-history
1926                                (or (magit-local-branch-at-point) commit))
1927                      (user-error "Nothing selected"))))
1928
1929 (defun magit-read-local-branch-or-ref (prompt &optional secondary-default)
1930   (magit-completing-read prompt (nconc (magit-list-local-branch-names)
1931                                        (magit-list-refs "refs/"))
1932                          nil t nil 'magit-revision-history
1933                          (or (magit-local-branch-at-point)
1934                              secondary-default
1935                              (magit-get-current-branch))))
1936
1937 (defun magit-read-other-branch
1938     (prompt &optional exclude secondary-default no-require-match)
1939   (let* ((current (magit-get-current-branch))
1940          (atpoint (magit-branch-at-point))
1941          (exclude (or exclude current))
1942          (default (or (and (not (equal atpoint exclude)) atpoint)
1943                       (and (not (equal current exclude)) current)
1944                       secondary-default
1945                       (magit-get-previous-branch))))
1946     (magit-completing-read prompt (delete exclude (magit-list-branch-names))
1947                            nil (not no-require-match)
1948                            nil 'magit-revision-history default)))
1949
1950 (defun magit-read-other-branch-or-commit
1951     (prompt &optional exclude secondary-default)
1952   (let* ((current (magit-get-current-branch))
1953          (atpoint (magit-branch-or-commit-at-point))
1954          (exclude (or exclude current))
1955          (default (or (and (not (equal atpoint exclude)) atpoint)
1956                       (and (not (equal current exclude)) current)
1957                       secondary-default
1958                       (magit-get-previous-branch))))
1959     (or (magit-completing-read prompt (delete exclude (magit-list-refnames))
1960                                nil nil nil 'magit-revision-history default)
1961         (user-error "Nothing selected"))))
1962
1963 (defun magit-read-other-local-branch
1964     (prompt &optional exclude secondary-default no-require-match)
1965   (let* ((current (magit-get-current-branch))
1966          (atpoint (magit-local-branch-at-point))
1967          (exclude (or exclude current))
1968          (default (or (and (not (equal atpoint exclude)) atpoint)
1969                       (and (not (equal current exclude)) current)
1970                       secondary-default
1971                       (magit-get-previous-branch))))
1972     (magit-completing-read prompt
1973                            (delete exclude (magit-list-local-branch-names))
1974                            nil (not no-require-match)
1975                            nil 'magit-revision-history default)))
1976
1977 (defun magit-read-branch-prefer-other (prompt)
1978   (let* ((current (magit-get-current-branch))
1979          (commit  (magit-commit-at-point))
1980          (atrev   (and commit (magit-list-branches-pointing-at commit)))
1981          (atpoint (magit--painted-branch-at-point)))
1982     (magit-completing-read prompt (magit-list-branch-names)
1983                            nil t nil 'magit-revision-history
1984                            (or (magit-section-value-if 'branch)
1985                                atpoint
1986                                (and (not (cdr atrev)) (car atrev))
1987                                (--first (not (equal it current)) atrev)
1988                                (magit-get-previous-branch)
1989                                (car atrev)))))
1990
1991 (cl-defun magit-read-upstream-branch
1992     (&optional (branch (magit-get-current-branch)) prompt)
1993   (magit-completing-read
1994    (or prompt (format "Change upstream of %s to" branch))
1995    (-union (--map (concat it "/" branch)
1996                   (magit-list-remotes))
1997            (delete branch (magit-list-branch-names)))
1998    nil nil nil 'magit-revision-history
1999    (or (let ((r (magit-remote-branch-at-point))
2000              (l (magit-branch-at-point)))
2001          (when (and l (equal l branch))
2002            (setq l nil))
2003          (if magit-prefer-remote-upstream (or r l) (or l r)))
2004        (let ((r (magit-branch-p "origin/master"))
2005              (l (and (not (equal branch "master"))
2006                      (magit-branch-p "master"))))
2007          (if magit-prefer-remote-upstream (or r l) (or l r)))
2008        (let ((previous (magit-get-previous-branch)))
2009          (and (not (equal previous branch)) previous)))))
2010
2011 (defun magit-read-starting-point (prompt &optional branch)
2012   (or (magit-completing-read
2013        (concat prompt
2014                (and branch
2015                     (if (bound-and-true-p ivy-mode)
2016                         ;; Ivy-mode strips faces from prompt.
2017                         (format  " `%s'" branch)
2018                       (concat " "
2019                               (propertize branch 'face 'magit-branch-local))))
2020                " starting at")
2021        (nconc (list "HEAD")
2022               (magit-list-refnames)
2023               (directory-files (magit-git-dir) nil "_HEAD\\'"))
2024        nil nil nil 'magit-revision-history
2025        (magit--default-starting-point))
2026       (user-error "Nothing selected")))
2027
2028 (defun magit--default-starting-point ()
2029   (or (let ((r (magit-remote-branch-at-point))
2030             (l (magit-local-branch-at-point)))
2031         (if magit-prefer-remote-upstream (or r l) (or l r)))
2032       (magit-commit-at-point)
2033       (magit-stash-at-point)
2034       (magit-get-current-branch)))
2035
2036 (defun magit-read-tag (prompt &optional require-match)
2037   (magit-completing-read prompt (magit-list-tags) nil
2038                          require-match nil 'magit-revision-history
2039                          (magit-tag-at-point)))
2040
2041 (defun magit-read-stash (prompt)
2042   (let ((stashes (magit-list-stashes)))
2043     (magit-completing-read prompt stashes nil t nil nil
2044                            (magit-stash-at-point)
2045                            (car stashes))))
2046
2047 (defun magit-read-remote (prompt &optional default use-only)
2048   (let ((remotes (magit-list-remotes)))
2049     (if (and use-only (= (length remotes) 1))
2050         (car remotes)
2051       (magit-completing-read prompt remotes
2052                              nil t nil nil
2053                              (or default
2054                                  (magit-remote-at-point)
2055                                  (magit-get-remote))))))
2056
2057 (defun magit-read-remote-or-url (prompt &optional default)
2058   (magit-completing-read prompt
2059                          (nconc (magit-list-remotes)
2060                                 (list "https://" "git://" "git@"))
2061                          nil nil nil nil
2062                          (or default
2063                              (magit-remote-at-point)
2064                              (magit-get-remote))))
2065
2066 (defun magit-read-module-path (prompt &optional predicate)
2067   (magit-completing-read prompt (magit-list-module-paths)
2068                          predicate t nil nil
2069                          (magit-module-at-point predicate)))
2070
2071 (defun magit-module-confirm (verb &optional predicate)
2072   (let (modules)
2073     (if current-prefix-arg
2074         (progn
2075           (setq modules (magit-list-module-paths))
2076           (when predicate
2077             (setq modules (-filter predicate modules)))
2078           (unless modules
2079             (if predicate
2080                 (user-error "No modules satisfying %s available" predicate)
2081               (user-error "No modules available"))))
2082       (setq modules (magit-region-values 'magit-module-section))
2083       (when modules
2084         (when predicate
2085           (setq modules (-filter predicate modules)))
2086         (unless modules
2087           (user-error "No modules satisfying %s selected" predicate))))
2088     (if (> (length modules) 1)
2089         (magit-confirm t nil (format "%s %%i modules" verb) nil modules)
2090       (list (magit-read-module-path (format "%s module" verb) predicate)))))
2091
2092 ;;; Variables in Popups
2093
2094 (defun magit--format-popup-variable:value (variable width &optional global)
2095   (concat variable
2096           (make-string (max 1 (- width 3 (length variable))) ?\s)
2097           (if-let ((value (magit-get (and global "--global") variable)))
2098               (propertize value 'face 'magit-popup-option-value)
2099             (propertize "unset" 'face 'magit-popup-disabled-argument))))
2100
2101 (defun magit--format-popup-variable:values (variable width &optional global)
2102   (concat variable
2103           (make-string (max 1 (- width 3 (length variable))) ?\s)
2104           (if-let ((values (magit-get-all (and global "--global") variable)))
2105               (concat
2106                (propertize (car values) 'face 'magit-popup-option-value)
2107                (mapconcat
2108                 (lambda (value)
2109                   (concat "\n" (make-string width ?\s)
2110                           (propertize value
2111                                       'face 'magit-popup-option-value)))
2112                 (cdr values) ""))
2113             (propertize "unset" 'face 'magit-popup-disabled-argument))))
2114
2115 (defun magit--set-popup-variable
2116     (variable choices &optional default other)
2117   (magit-set (--if-let (magit-git-string "config" "--local" variable)
2118                  (cadr (member it choices))
2119                (car choices))
2120              variable)
2121   (magit-with-pre-popup-buffer
2122     (magit-refresh))
2123   (message "%s %s" variable
2124            (magit--format-popup-variable:choices*
2125             variable choices default other)))
2126
2127 (defun magit--format-popup-variable:choices
2128     (variable choices &optional default other width)
2129   (concat variable
2130           (if width (make-string (- width (length variable)) ?\s) " ")
2131           (magit--format-popup-variable:choices*
2132            variable choices default other)))
2133
2134 (defun magit--format-popup-variable:choices*
2135     (variable choices &optional default other)
2136   (let ((local  (magit-git-string "config" "--local"  variable))
2137         (global (magit-git-string "config" "--global" variable)))
2138     (when other
2139       (setq other (--when-let (magit-get other)
2140                     (concat other ":" it))))
2141     (concat
2142      (propertize "[" 'face 'magit-popup-disabled-argument)
2143      (mapconcat
2144       (lambda (choice)
2145         (propertize choice 'face (if (equal choice local)
2146                                      'magit-popup-option-value
2147                                    'magit-popup-disabled-argument)))
2148       choices
2149       (propertize "|" 'face 'magit-popup-disabled-argument))
2150      (when (or global other default)
2151        (concat
2152         (propertize "|" 'face 'magit-popup-disabled-argument)
2153         (cond (global
2154                (propertize (concat "global:" global)
2155                            'face (cond (local
2156                                         'magit-popup-disabled-argument)
2157                                        ((member global choices)
2158                                         'magit-popup-option-value)
2159                                        (t
2160                                         'font-lock-warning-face))))
2161               (other
2162                (propertize other
2163                            'face (if local
2164                                      'magit-popup-disabled-argument
2165                                    'magit-popup-option-value)))
2166               (default
2167                (propertize (concat "default:" default)
2168                            'face (if local
2169                                      'magit-popup-disabled-argument
2170                                    'magit-popup-option-value))))))
2171      (propertize "]" 'face 'magit-popup-disabled-argument))))
2172
2173 ;;; _
2174 (provide 'magit-git)
2175 ;;; magit-git.el ends here