dotemacs

My Emacs configuration
git clone git://git.entf.net/dotemacs
Log | Files | Refs | LICENSE

magit.el (27951B)


      1 ;;; magit.el --- A Git porcelain inside Emacs  -*- lexical-binding: t; coding: utf-8 -*-
      2 
      3 ;; Copyright (C) 2008-2021  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: Marius Vollmer <marius.vollmer@gmail.com>
      9 ;;      Jonas Bernoulli <jonas@bernoul.li>
     10 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
     11 ;;      Kyle Meyer <kyle@kyleam.com>
     12 ;;      Noam Postavsky <npostavs@users.sourceforge.net>
     13 ;; Former-Maintainers:
     14 ;;      Nicolas Dudebout <nicolas.dudebout@gatech.edu>
     15 ;;      Peter J. Weisberg <pj@irregularexpressions.net>
     16 ;;      Phil Jackson <phil@shellarchive.co.uk>
     17 ;;      Rémi Vanicat <vanicat@debian.org>
     18 ;;      Yann Hodique <yann.hodique@gmail.com>
     19 
     20 ;; Keywords: git tools vc
     21 ;; Homepage: https://github.com/magit/magit
     22 ;; Package-Requires: ((emacs "25.1") (dash "2.19.1") (git-commit "3.3.0") (magit-section "3.3.0") (transient "0.3.6") (with-editor "3.0.5"))
     23 ;; Package-Version: 3.3.0
     24 ;; SPDX-License-Identifier: GPL-3.0-or-later
     25 
     26 ;; Magit is free software; you can redistribute it and/or modify it
     27 ;; under the terms of the GNU General Public License as published by
     28 ;; the Free Software Foundation; either version 3, or (at your option)
     29 ;; any later version.
     30 ;;
     31 ;; Magit is distributed in the hope that it will be useful, but WITHOUT
     32 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     33 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
     34 ;; License for more details.
     35 ;;
     36 ;; You should have received a copy of the GNU General Public License
     37 ;; along with Magit.  If not, see http://www.gnu.org/licenses.
     38 
     39 ;; Magit requires at least GNU Emacs 25.1 and Git 2.2.0.
     40 
     41 ;;; Commentary:
     42 
     43 ;; Magit is a text-based Git user interface that puts an unmatched focus
     44 ;; on streamlining workflows.  Commands are invoked using short mnemonic
     45 ;; key sequences that take the cursor’s position in the highly actionable
     46 ;; interface into account to provide context-sensitive behavior.
     47 
     48 ;; With Magit you can do nearly everything that you can do when using Git
     49 ;; on the command-line, but at greater speed and while taking advantage
     50 ;; of advanced features that previously seemed too daunting to use on a
     51 ;; daily basis.  Many users will find that by using Magit they can become
     52 ;; more effective Git user.
     53 
     54 ;;; Code:
     55 
     56 (require 'magit-core)
     57 (require 'magit-diff)
     58 (require 'magit-log)
     59 (require 'magit-wip)
     60 (require 'magit-apply)
     61 (require 'magit-repos)
     62 (require 'git-commit)
     63 
     64 (require 'format-spec)
     65 (require 'package nil t) ; used in `magit-version'
     66 (require 'with-editor)
     67 
     68 (defconst magit--minimal-git "2.2.0")
     69 (defconst magit--minimal-emacs "25.1")
     70 
     71 ;;; Faces
     72 
     73 (defface magit-header-line
     74   '((t :inherit magit-section-heading))
     75   "Face for the `header-line' in some Magit modes.
     76 Note that some modes, such as `magit-log-select-mode', have their
     77 own faces for the `header-line', or for parts of the
     78 `header-line'."
     79   :group 'magit-faces)
     80 
     81 (defface magit-header-line-key
     82   '((t :inherit font-lock-builtin-face))
     83   "Face for keys in the `header-line'."
     84   :group 'magit-faces)
     85 
     86 (defface magit-dimmed
     87   '((((class color) (background light)) :foreground "grey50")
     88     (((class color) (background  dark)) :foreground "grey50"))
     89   "Face for text that shouldn't stand out."
     90   :group 'magit-faces)
     91 
     92 (defface magit-hash
     93   '((((class color) (background light)) :foreground "grey60")
     94     (((class color) (background  dark)) :foreground "grey40"))
     95   "Face for the sha1 part of the log output."
     96   :group 'magit-faces)
     97 
     98 (defface magit-tag
     99   '((((class color) (background light)) :foreground "Goldenrod4")
    100     (((class color) (background  dark)) :foreground "LightGoldenrod2"))
    101   "Face for tag labels shown in log buffer."
    102   :group 'magit-faces)
    103 
    104 (defface magit-branch-remote
    105   '((((class color) (background light)) :foreground "DarkOliveGreen4")
    106     (((class color) (background  dark)) :foreground "DarkSeaGreen2"))
    107   "Face for remote branch head labels shown in log buffer."
    108   :group 'magit-faces)
    109 
    110 (defface magit-branch-remote-head
    111   '((((supports (:box t))) :inherit magit-branch-remote :box t)
    112     (t                     :inherit magit-branch-remote :inverse-video t))
    113   "Face for current branch."
    114   :group 'magit-faces)
    115 
    116 (defface magit-branch-local
    117   '((((class color) (background light)) :foreground "SkyBlue4")
    118     (((class color) (background  dark)) :foreground "LightSkyBlue1"))
    119   "Face for local branches."
    120   :group 'magit-faces)
    121 
    122 (defface magit-branch-current
    123   '((((supports (:box t))) :inherit magit-branch-local :box t)
    124     (t                     :inherit magit-branch-local :inverse-video t))
    125   "Face for current branch."
    126   :group 'magit-faces)
    127 
    128 (defface magit-branch-upstream
    129   '((t :slant italic))
    130   "Face for upstream branch.
    131 This face is only used in logs and it gets combined
    132  with `magit-branch-local', `magit-branch-remote'
    133 and/or `magit-branch-remote-head'."
    134   :group 'magit-faces)
    135 
    136 (defface magit-head
    137   '((((class color) (background light)) :inherit magit-branch-local)
    138     (((class color) (background  dark)) :inherit magit-branch-local))
    139   "Face for the symbolic ref `HEAD'."
    140   :group 'magit-faces)
    141 
    142 (defface magit-refname
    143   '((((class color) (background light)) :foreground "grey30")
    144     (((class color) (background  dark)) :foreground "grey80"))
    145   "Face for refnames without a dedicated face."
    146   :group 'magit-faces)
    147 
    148 (defface magit-refname-stash
    149   '((t :inherit magit-refname))
    150   "Face for stash refnames."
    151   :group 'magit-faces)
    152 
    153 (defface magit-refname-wip
    154   '((t :inherit magit-refname))
    155   "Face for wip refnames."
    156   :group 'magit-faces)
    157 
    158 (defface magit-refname-pullreq
    159   '((t :inherit magit-refname))
    160   "Face for pullreq refnames."
    161   :group 'magit-faces)
    162 
    163 (defface magit-keyword
    164   '((t :inherit font-lock-string-face))
    165   "Face for parts of commit messages inside brackets."
    166   :group 'magit-faces)
    167 
    168 (defface magit-keyword-squash
    169   '((t :inherit font-lock-warning-face))
    170   "Face for squash! and fixup! keywords in commit messages."
    171   :group 'magit-faces)
    172 
    173 (defface magit-signature-good
    174   '((t :foreground "green"))
    175   "Face for good signatures."
    176   :group 'magit-faces)
    177 
    178 (defface magit-signature-bad
    179   '((t :foreground "red" :weight bold))
    180   "Face for bad signatures."
    181   :group 'magit-faces)
    182 
    183 (defface magit-signature-untrusted
    184   '((t :foreground "medium aquamarine"))
    185   "Face for good untrusted signatures."
    186   :group 'magit-faces)
    187 
    188 (defface magit-signature-expired
    189   '((t :foreground "orange"))
    190   "Face for signatures that have expired."
    191   :group 'magit-faces)
    192 
    193 (defface magit-signature-expired-key
    194   '((t :inherit magit-signature-expired))
    195   "Face for signatures made by an expired key."
    196   :group 'magit-faces)
    197 
    198 (defface magit-signature-revoked
    199   '((t :foreground "violet red"))
    200   "Face for signatures made by a revoked key."
    201   :group 'magit-faces)
    202 
    203 (defface magit-signature-error
    204   '((t :foreground "light blue"))
    205   "Face for signatures that cannot be checked (e.g. missing key)."
    206   :group 'magit-faces)
    207 
    208 (defface magit-cherry-unmatched
    209   '((t :foreground "cyan"))
    210   "Face for unmatched cherry commits."
    211   :group 'magit-faces)
    212 
    213 (defface magit-cherry-equivalent
    214   '((t :foreground "magenta"))
    215   "Face for equivalent cherry commits."
    216   :group 'magit-faces)
    217 
    218 (defface magit-filename
    219   '((t :weight normal))
    220   "Face for filenames."
    221   :group 'magit-faces)
    222 
    223 ;;; Global Bindings
    224 
    225 ;;;###autoload
    226 (define-obsolete-variable-alias 'global-magit-file-mode
    227   'magit-define-global-key-bindings "Magit 3.0.0")
    228 
    229 ;;;###autoload
    230 (defcustom magit-define-global-key-bindings t
    231   "Whether to bind some Magit commands in the global keymap.
    232 
    233 If this variable is non-nil, then the following bindings may
    234 be added to the global keymap.  The default is t.
    235 
    236 key             binding
    237 ---             -------
    238 C-x g           magit-status
    239 C-x M-g         magit-dispatch
    240 C-c M-g         magit-file-dispatch
    241 
    242 These bindings may be added when `after-init-hook' is run.
    243 Each binding is added if and only if at that time no other key
    244 is bound to the same command and no other command is bound to
    245 the same key.  In other words we try to avoid adding bindings
    246 that are unnecessary, as well as bindings that conflict with
    247 other bindings.
    248 
    249 Adding the above bindings is delayed until `after-init-hook'
    250 is called to allow users to set the variable anywhere in their
    251 init file (without having to make sure to do so before `magit'
    252 is loaded or autoloaded) and to increase the likelihood that
    253 all the potentially conflicting user bindings have already
    254 been added.
    255 
    256 To set this variable use either `setq' or the Custom interface.
    257 Do not use the function `customize-set-variable' because doing
    258 that would cause Magit to be loaded immediately when that form
    259 is evaluated (this differs from `custom-set-variables', which
    260 doesn't load the libraries that define the customized variables).
    261 
    262 Setting this variable to nil has no effect if that is done after
    263 the key bindings have already been added.
    264 
    265 We recommend that you bind \"C-c g\" instead of \"C-c M-g\" to
    266 `magit-file-dispatch'.  The former is a much better binding
    267 but the \"C-c <letter>\" namespace is strictly reserved for
    268 users; preventing Magit from using it by default.
    269 
    270 Also see info node `(magit)Commands for Buffers Visiting Files'."
    271   :package-version '(magit . "3.0.0")
    272   :group 'magit-essentials
    273   :type 'boolean)
    274 
    275 ;;;###autoload
    276 (progn
    277   (defun magit-maybe-define-global-key-bindings ()
    278     (when magit-define-global-key-bindings
    279       (let ((map (current-global-map)))
    280         (dolist (elt '(("C-x g"   . magit-status)
    281                        ("C-x M-g" . magit-dispatch)
    282                        ("C-c M-g" . magit-file-dispatch)))
    283           (let ((key (kbd (car elt)))
    284                 (def (cdr elt)))
    285             (unless (or (lookup-key map key)
    286                         (where-is-internal def (make-sparse-keymap) t))
    287               (define-key map key def)))))))
    288   (if after-init-time
    289       (magit-maybe-define-global-key-bindings)
    290     (add-hook 'after-init-hook 'magit-maybe-define-global-key-bindings t)))
    291 
    292 ;;; Dispatch Popup
    293 
    294 ;;;###autoload (autoload 'magit-dispatch "magit" nil t)
    295 (transient-define-prefix magit-dispatch ()
    296   "Invoke a Magit command from a list of available commands."
    297   :info-manual "(magit)Top"
    298   ["Transient and dwim commands"
    299    ;; → bound in magit-mode-map or magit-section-mode-map
    300    ;; ↓ bound below
    301    [("A" "Apply"          magit-cherry-pick)
    302     ;; a                  ↓
    303     ("b" "Branch"         magit-branch)
    304     ("B" "Bisect"         magit-bisect)
    305     ("c" "Commit"         magit-commit)
    306     ("C" "Clone"          magit-clone)
    307     ("d" "Diff"           magit-diff)
    308     ("D" "Diff (change)"  magit-diff-refresh)
    309     ("e" "Ediff (dwim)"   magit-ediff-dwim)
    310     ("E" "Ediff"          magit-ediff)
    311     ("f" "Fetch"          magit-fetch)
    312     ("F" "Pull"           magit-pull)
    313     ;; g                  ↓
    314     ;; G                → magit-refresh-all
    315     ("h" "Help"           magit-help)
    316     ("H" "Section info"   magit-describe-section :if-derived magit-mode)]
    317    [("i" "Ignore"         magit-gitignore)
    318     ("I" "Init"           magit-init)
    319     ("j" "Jump to section"magit-status-jump  :if-mode     magit-status-mode)
    320     ("j" "Display status" magit-status-quick :if-not-mode magit-status-mode)
    321     ("J" "Display buffer" magit-display-repository-buffer)
    322     ;; k                  ↓
    323     ;; K                → magit-file-untrack
    324     ("l" "Log"            magit-log)
    325     ("L" "Log (change)"   magit-log-refresh)
    326     ("m" "Merge"          magit-merge)
    327     ("M" "Remote"         magit-remote)
    328     ;; n                → magit-section-forward
    329     ;; N       reserved → forge-dispatch
    330     ("o" "Submodule"      magit-submodule)
    331     ("O" "Subtree"        magit-subtree)
    332     ;; p                → magit-section-backward
    333     ("P" "Push"           magit-push)
    334     ;; q                → magit-mode-bury-buffer
    335     ("Q" "Command"        magit-git-command)]
    336    [("r" "Rebase"         magit-rebase)
    337     ;; R                → magit-file-rename
    338     ;; s                  ↓
    339     ;; S                  ↓
    340     ("t" "Tag"            magit-tag)
    341     ("T" "Note"           magit-notes)
    342     ;; u                  ↓
    343     ;; U                  ↓
    344     ;; v                  ↓
    345     ("V" "Revert"         magit-revert)
    346     ("w" "Apply patches"  magit-am)
    347     ("W" "Format patches" magit-patch)
    348     ;; x                → magit-reset-quickly
    349     ("X" "Reset"          magit-reset)
    350     ("y" "Show Refs"      magit-show-refs)
    351     ("Y" "Cherries"       magit-cherry)
    352     ("z" "Stash"          magit-stash)
    353     ("Z" "Worktree"       magit-worktree)
    354     ("!" "Run"            magit-run)]]
    355   ["Applying changes"
    356    :if-derived magit-mode
    357    [("a" "Apply"          magit-apply)
    358     ("v" "Reverse"        magit-reverse)
    359     ("k" "Discard"        magit-discard)]
    360    [("s" "Stage"          magit-stage)
    361     ("u" "Unstage"        magit-unstage)]
    362    [("S" "Stage all"      magit-stage-modified)
    363     ("U" "Unstage all"    magit-unstage-all)]]
    364   ["Essential commands"
    365    :if-derived magit-mode
    366    ("g" "       refresh current buffer"   magit-refresh)
    367    ("<tab>" "   toggle section at point"  magit-section-toggle)
    368    ("<return>" "visit thing at point"     magit-visit-thing)
    369    ("C-h m" "   show all key bindings"    describe-mode)])
    370 
    371 ;;; Git Popup
    372 
    373 (defcustom magit-shell-command-verbose-prompt t
    374   "Whether to show the working directory when reading a command.
    375 This affects `magit-git-command', `magit-git-command-topdir',
    376 `magit-shell-command', and `magit-shell-command-topdir'."
    377   :package-version '(magit . "2.11.0")
    378   :group 'magit-commands
    379   :type 'boolean)
    380 
    381 (defvar magit-git-command-history nil)
    382 
    383 ;;;###autoload (autoload 'magit-run "magit" nil t)
    384 (transient-define-prefix magit-run ()
    385   "Run git or another command, or launch a graphical utility."
    386   [["Run git subcommand"
    387     ("!" "in repository root"   magit-git-command-topdir)
    388     ("p" "in working directory" magit-git-command)]
    389    ["Run shell command"
    390     ("s" "in repository root"   magit-shell-command-topdir)
    391     ("S" "in working directory" magit-shell-command)]
    392    ["Launch"
    393     ("k" "gitk"                 magit-run-gitk)
    394     ("a" "gitk --all"           magit-run-gitk-all)
    395     ("b" "gitk --branches"      magit-run-gitk-branches)
    396     ("g" "git gui"              magit-run-git-gui)]])
    397 
    398 ;;;###autoload
    399 (defun magit-git-command (command)
    400   "Execute COMMAND asynchronously; display output.
    401 
    402 Interactively, prompt for COMMAND in the minibuffer. \"git \" is
    403 used as initial input, but can be deleted to run another command.
    404 
    405 With a prefix argument COMMAND is run in the top-level directory
    406 of the current working tree, otherwise in `default-directory'."
    407   (interactive (list (magit-read-shell-command nil "git ")))
    408   (magit--shell-command command))
    409 
    410 ;;;###autoload
    411 (defun magit-git-command-topdir (command)
    412   "Execute COMMAND asynchronously; display output.
    413 
    414 Interactively, prompt for COMMAND in the minibuffer. \"git \" is
    415 used as initial input, but can be deleted to run another command.
    416 
    417 COMMAND is run in the top-level directory of the current
    418 working tree."
    419   (interactive (list (magit-read-shell-command t "git ")))
    420   (magit--shell-command command (magit-toplevel)))
    421 
    422 ;;;###autoload
    423 (defun magit-shell-command (command)
    424   "Execute COMMAND asynchronously; display output.
    425 
    426 Interactively, prompt for COMMAND in the minibuffer.  With a
    427 prefix argument COMMAND is run in the top-level directory of
    428 the current working tree, otherwise in `default-directory'."
    429   (interactive (list (magit-read-shell-command)))
    430   (magit--shell-command command))
    431 
    432 ;;;###autoload
    433 (defun magit-shell-command-topdir (command)
    434   "Execute COMMAND asynchronously; display output.
    435 
    436 Interactively, prompt for COMMAND in the minibuffer.  COMMAND
    437 is run in the top-level directory of the current working tree."
    438   (interactive (list (magit-read-shell-command t)))
    439   (magit--shell-command command (magit-toplevel)))
    440 
    441 (defun magit--shell-command (command &optional directory)
    442   (let ((default-directory (or directory default-directory))
    443         (process-environment process-environment))
    444     (push "GIT_PAGER=cat" process-environment)
    445     (magit-start-process shell-file-name nil
    446                          shell-command-switch command))
    447   (magit-process-buffer))
    448 
    449 (defun magit-read-shell-command (&optional toplevel initial-input)
    450   (let ((default-directory
    451           (if (or toplevel current-prefix-arg)
    452               (or (magit-toplevel)
    453                   (magit--not-inside-repository-error))
    454             default-directory)))
    455     (read-shell-command (if magit-shell-command-verbose-prompt
    456                             (format "Async shell command in %s: "
    457                                     (abbreviate-file-name default-directory))
    458                           "Async shell command: ")
    459                         initial-input 'magit-git-command-history)))
    460 
    461 ;;; Font-Lock Keywords
    462 
    463 (defconst magit-font-lock-keywords
    464   (eval-when-compile
    465     `((,(concat "(\\(magit-define-section-jumper\\)\\_>"
    466                 "[ \t'\(]*"
    467                 "\\(\\(?:\\sw\\|\\s_\\)+\\)?")
    468        (1 'font-lock-keyword-face)
    469        (2 'font-lock-function-name-face nil t))
    470       (,(concat "(" (regexp-opt '("magit-insert-section"
    471                                   "magit-section-case"
    472                                   "magit-bind-match-strings"
    473                                   "magit-with-temp-index"
    474                                   "magit-with-blob"
    475                                   "magit-with-toplevel") t)
    476                 "\\_>")
    477        . 1))))
    478 
    479 (font-lock-add-keywords 'emacs-lisp-mode magit-font-lock-keywords)
    480 
    481 ;;; Version
    482 
    483 (defvar magit-version 'undefined
    484   "The version of Magit that you're using.
    485 Use the function by the same name instead of this variable.")
    486 
    487 ;;;###autoload
    488 (defun magit-version (&optional print-dest)
    489   "Return the version of Magit currently in use.
    490 If optional argument PRINT-DEST is non-nil, output
    491 stream (interactively, the echo area, or the current buffer with
    492 a prefix argument), also print the used versions of Magit, Git,
    493 and Emacs to it."
    494   (interactive (list (if current-prefix-arg (current-buffer) t)))
    495   (let ((magit-git-global-arguments nil)
    496         (toplib (or load-file-name buffer-file-name))
    497         debug)
    498     (unless (and toplib
    499                  (member (file-name-nondirectory toplib)
    500                          '("magit.el" "magit.el.gz")))
    501       (let ((load-suffixes '(".el")))
    502         (setq toplib (locate-library "magit"))))
    503     (setq toplib (and toplib (magit--straight-chase-links toplib)))
    504     (push toplib debug)
    505     (when toplib
    506       (let* ((topdir (file-name-directory toplib))
    507              (gitdir (expand-file-name
    508                       ".git" (file-name-directory
    509                               (directory-file-name topdir))))
    510              (static (locate-library "magit-version.el" nil (list topdir)))
    511              (static (and static (magit--straight-chase-links static))))
    512         (or (progn
    513               (push 'repo debug)
    514               (when (and (file-exists-p gitdir)
    515                          ;; It is a repo, but is it the Magit repo?
    516                          (file-exists-p
    517                           (expand-file-name "../lisp/magit.el" gitdir)))
    518                 (push t debug)
    519                 ;; Inside the repo the version file should only exist
    520                 ;; while running make.
    521                 (when (and static (not noninteractive))
    522                   (ignore-errors (delete-file static)))
    523                 (setq magit-version
    524                       (let ((default-directory topdir))
    525                         (magit-git-string "describe"
    526                                           "--tags" "--dirty" "--always")))))
    527             (progn
    528               (push 'static debug)
    529               (when (and static (file-exists-p static))
    530                 (push t debug)
    531                 (load-file static)
    532                 magit-version))
    533             (when (featurep 'package)
    534               (push 'elpa debug)
    535               (ignore-errors
    536                 (--when-let (assq 'magit package-alist)
    537                   (push t debug)
    538                   (setq magit-version
    539                         (and (fboundp 'package-desc-version)
    540                              (package-version-join
    541                               (package-desc-version (cadr it))))))))
    542             (progn
    543               (push 'dirname debug)
    544               (let ((dirname (file-name-nondirectory
    545                               (directory-file-name topdir))))
    546                 (when (string-match "\\`magit-\\([0-9].*\\)" dirname)
    547                   (setq magit-version (match-string 1 dirname)))))
    548             ;; If all else fails, just report the commit hash. It's
    549             ;; better than nothing and we cannot do better in the case
    550             ;; of e.g. a shallow clone.
    551             (progn
    552               (push 'hash debug)
    553               ;; Same check as above to see if it's really the Magit repo.
    554               (when (and (file-exists-p gitdir)
    555                          (file-exists-p
    556                           (expand-file-name "../lisp/magit.el" gitdir)))
    557                 (setq magit-version
    558                       (let ((default-directory topdir))
    559                         (magit-git-string "rev-parse" "HEAD"))))))))
    560     (if (stringp magit-version)
    561         (when print-dest
    562           (princ (format "Magit %s%s, Git %s, Emacs %s, %s"
    563                          (or magit-version "(unknown)")
    564                          (or (and (ignore-errors (version< "2008" magit-version))
    565                                   (ignore-errors
    566                                     (require 'lisp-mnt)
    567                                     (and (fboundp 'lm-header)
    568                                          (format
    569                                           " [>= %s]"
    570                                           (with-temp-buffer
    571                                             (insert-file-contents
    572                                              (locate-library "magit.el" t))
    573                                             (lm-header "Package-Version"))))))
    574                              "")
    575                          (or (let ((magit-git-debug
    576                                     (lambda (err)
    577                                       (display-warning '(magit git)
    578                                                        err :error))))
    579                                (magit-git-version t))
    580                              "(unknown)")
    581                          emacs-version
    582                          system-type)
    583                  print-dest))
    584       (setq debug (reverse debug))
    585       (setq magit-version 'error)
    586       (when magit-version
    587         (push magit-version debug))
    588       (unless (equal (getenv "CI") "true")
    589         ;; The repository is a sparse clone.
    590         (message "Cannot determine Magit's version %S" debug)))
    591     magit-version))
    592 
    593 ;;; Debugging Tools
    594 
    595 (defun magit-debug-git-executable ()
    596   "Display a buffer with information about `magit-git-executable'.
    597 Also include information about `magit-remote-git-executable'.
    598 See info node `(magit)Debugging Tools' for more information."
    599   (interactive)
    600   (with-current-buffer (get-buffer-create "*magit-git-debug*")
    601     (pop-to-buffer (current-buffer))
    602     (erase-buffer)
    603     (insert (format "magit-remote-git-executable: %S\n"
    604                     magit-remote-git-executable))
    605     (insert (concat
    606              (format "magit-git-executable: %S" magit-git-executable)
    607              (and (not (file-name-absolute-p magit-git-executable))
    608                   (format " [%S]" (executable-find magit-git-executable)))
    609              (format " (%s)\n"
    610                      (let* ((errmsg nil)
    611                             (magit-git-debug (lambda (err) (setq errmsg err))))
    612                        (or (magit-git-version t) errmsg)))))
    613     (insert (format "exec-path: %S\n" exec-path))
    614     (--when-let (cl-set-difference
    615                  (-filter #'file-exists-p (remq nil (parse-colon-path
    616                                                      (getenv "PATH"))))
    617                  (-filter #'file-exists-p (remq nil exec-path))
    618                  :test #'file-equal-p)
    619       (insert (format "  entries in PATH, but not in exec-path: %S\n" it)))
    620     (dolist (execdir exec-path)
    621       (insert (format "  %s (%s)\n" execdir (car (file-attributes execdir))))
    622       (when (file-directory-p execdir)
    623         (dolist (exec (directory-files
    624                        execdir t (concat
    625                                   "\\`git" (regexp-opt exec-suffixes) "\\'")))
    626           (insert (format "    %s (%s)\n" exec
    627                           (let* ((magit-git-executable exec)
    628                                  (errmsg nil)
    629                                  (magit-git-debug (lambda (err) (setq errmsg err))))
    630                             (or (magit-git-version t) errmsg)))))))))
    631 
    632 ;;; Startup Asserts
    633 
    634 (defun magit-startup-asserts ()
    635   (when-let ((val (getenv "GIT_DIR")))
    636     (setenv "GIT_DIR")
    637     (message "Magit unset $GIT_DIR (was %S).  See \
    638 https://github.com/magit/magit/wiki/Don't-set-$GIT_DIR-and-alike" val))
    639   (when-let ((val (getenv "GIT_WORK_TREE")))
    640     (setenv "GIT_WORK_TREE")
    641     (message "Magit unset $GIT_WORK_TREE (was %S).  See \
    642 https://github.com/magit/magit/wiki/Don't-set-$GIT_DIR-and-alike" val))
    643   (let ((version (magit-git-version)))
    644     (when (and version
    645                (version< version magit--minimal-git)
    646                (not (equal (getenv "CI") "true")))
    647       (display-warning 'magit (format "\
    648 Magit requires Git >= %s, you are using %s.
    649 
    650 If this comes as a surprise to you, because you do actually have
    651 a newer version installed, then that probably means that the
    652 older version happens to appear earlier on the `$PATH'.  If you
    653 always start Emacs from a shell, then that can be fixed in the
    654 shell's init file.  If you start Emacs by clicking on an icon,
    655 or using some sort of application launcher, then you probably
    656 have to adjust the environment as seen by graphical interface.
    657 For X11 something like ~/.xinitrc should work.
    658 
    659 If you use Tramp to work inside remote Git repositories, then you
    660 have to make sure a suitable Git is used on the remote machines
    661 too.\n" magit--minimal-git version) :error)))
    662   (when (version< emacs-version magit--minimal-emacs)
    663     (display-warning 'magit (format "\
    664 Magit requires Emacs >= %s, you are using %s.
    665 
    666 If this comes as a surprise to you, because you do actually have
    667 a newer version installed, then that probably means that the
    668 older version happens to appear earlier on the `$PATH'.  If you
    669 always start Emacs from a shell, then that can be fixed in the
    670 shell's init file.  If you start Emacs by clicking on an icon,
    671 or using some sort of application launcher, then you probably
    672 have to adjust the environment as seen by graphical interface.
    673 For X11 something like ~/.xinitrc should work.\n"
    674                                     magit--minimal-emacs emacs-version)
    675                      :error)))
    676 
    677 ;;; Loading Libraries
    678 
    679 (provide 'magit)
    680 
    681 (cl-eval-when (load eval)
    682   (require 'magit-status)
    683   (require 'magit-refs)
    684   (require 'magit-files)
    685   (require 'magit-reset)
    686   (require 'magit-branch)
    687   (require 'magit-merge)
    688   (require 'magit-tag)
    689   (require 'magit-worktree)
    690   (require 'magit-notes)
    691   (require 'magit-sequence)
    692   (require 'magit-commit)
    693   (require 'magit-remote)
    694   (require 'magit-clone)
    695   (require 'magit-fetch)
    696   (require 'magit-pull)
    697   (require 'magit-push)
    698   (require 'magit-bisect)
    699   (require 'magit-stash)
    700   (require 'magit-blame)
    701   (require 'magit-obsolete)
    702   (require 'magit-submodule)
    703   (unless (load "magit-autoloads" t t)
    704     (require 'magit-patch)
    705     (require 'magit-subtree)
    706     (require 'magit-ediff)
    707     (require 'magit-gitignore)
    708     (require 'magit-extras)
    709     (require 'git-rebase)
    710     (require 'magit-imenu)
    711     (require 'magit-bookmark)))
    712 
    713 (with-eval-after-load 'bookmark
    714   (require 'magit-bookmark))
    715 
    716 (if after-init-time
    717     (progn (magit-startup-asserts)
    718            (magit-version))
    719   (add-hook 'after-init-hook #'magit-startup-asserts t)
    720   (add-hook 'after-init-hook #'magit-version t))
    721 
    722 ;;; magit.el ends here