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