Klimi's new dotfiles with stow.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

596 lines
22 KiB

5 years ago
  1. ;;; magit.el --- A Git porcelain inside Emacs -*- lexical-binding: t; coding: utf-8 -*-
  2. ;; Copyright (C) 2008-2019 The Magit Project Contributors
  3. ;;
  4. ;; You should have received a copy of the AUTHORS.md file which
  5. ;; lists all contributors. If not, see http://magit.vc/authors.
  6. ;; Author: Marius Vollmer <marius.vollmer@gmail.com>
  7. ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
  8. ;; Kyle Meyer <kyle@kyleam.com>
  9. ;; Noam Postavsky <npostavs@users.sourceforge.net>
  10. ;; Former-Maintainers:
  11. ;; Nicolas Dudebout <nicolas.dudebout@gatech.edu>
  12. ;; Peter J. Weisberg <pj@irregularexpressions.net>
  13. ;; Phil Jackson <phil@shellarchive.co.uk>
  14. ;; Rémi Vanicat <vanicat@debian.org>
  15. ;; Yann Hodique <yann.hodique@gmail.com>
  16. ;; Keywords: git tools vc
  17. ;; Homepage: https://github.com/magit/magit
  18. ;; Magit requires at least GNU Emacs 25.1 and Git 2.2.0.
  19. ;; Magit is free software; you can redistribute it and/or modify it
  20. ;; under the terms of the GNU General Public License as published by
  21. ;; the Free Software Foundation; either version 3, or (at your option)
  22. ;; any later version.
  23. ;;
  24. ;; Magit is distributed in the hope that it will be useful, but WITHOUT
  25. ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  26. ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
  27. ;; License for more details.
  28. ;;
  29. ;; You should have received a copy of the GNU General Public License
  30. ;; along with Magit. If not, see http://www.gnu.org/licenses.
  31. ;;; Commentary:
  32. ;; Magit is an interface to the version control system Git,
  33. ;; implemented as an Emacs package. Magit aspires to be a complete
  34. ;; Git porcelain. While we cannot (yet) claim, that Magit wraps and
  35. ;; improves upon each and every Git command, it is complete enough to
  36. ;; allow even experienced Git users to perform almost all of their
  37. ;; daily version control tasks directly from within Emacs. While many
  38. ;; fine Git clients exist, only Magit and Git itself deserve to be
  39. ;; called porcelains.
  40. ;;; Code:
  41. (require 'cl-lib)
  42. (require 'dash)
  43. (require 'subr-x)
  44. (require 'with-editor)
  45. (require 'git-commit)
  46. (require 'magit-core)
  47. (require 'magit-diff)
  48. (require 'magit-log)
  49. (require 'magit-wip)
  50. (require 'magit-apply)
  51. (require 'magit-repos)
  52. (require 'format-spec)
  53. (require 'package nil t) ; used in `magit-version'
  54. (defconst magit--minimal-git "2.2.0")
  55. (defconst magit--minimal-emacs "25.1")
  56. ;;; Faces
  57. (defface magit-header-line
  58. '((t :inherit magit-section-heading))
  59. "Face for the `header-line' in some Magit modes.
  60. Note that some modes, such as `magit-log-select-mode', have their
  61. own faces for the `header-line', or for parts of the
  62. `header-line'."
  63. :group 'magit-faces)
  64. (defface magit-header-line-key
  65. '((t :inherit magit-popup-key))
  66. "Face for keys in the `header-line'."
  67. :group 'magit-faces)
  68. (defface magit-dimmed
  69. '((((class color) (background light)) :foreground "grey50")
  70. (((class color) (background dark)) :foreground "grey50"))
  71. "Face for text that shouldn't stand out."
  72. :group 'magit-faces)
  73. (defface magit-hash
  74. '((((class color) (background light)) :foreground "grey60")
  75. (((class color) (background dark)) :foreground "grey40"))
  76. "Face for the sha1 part of the log output."
  77. :group 'magit-faces)
  78. (defface magit-tag
  79. '((((class color) (background light)) :foreground "Goldenrod4")
  80. (((class color) (background dark)) :foreground "LightGoldenrod2"))
  81. "Face for tag labels shown in log buffer."
  82. :group 'magit-faces)
  83. (defface magit-branch-remote
  84. '((((class color) (background light)) :foreground "DarkOliveGreen4")
  85. (((class color) (background dark)) :foreground "DarkSeaGreen2"))
  86. "Face for remote branch head labels shown in log buffer."
  87. :group 'magit-faces)
  88. (defface magit-branch-remote-head
  89. '((((class color) (background light)) :inherit magit-branch-remote :box t)
  90. (((class color) (background dark)) :inherit magit-branch-remote :box t))
  91. "Face for current branch."
  92. :group 'magit-faces)
  93. (defface magit-branch-local
  94. '((((class color) (background light)) :foreground "SkyBlue4")
  95. (((class color) (background dark)) :foreground "LightSkyBlue1"))
  96. "Face for local branches."
  97. :group 'magit-faces)
  98. (defface magit-branch-current
  99. '((((class color) (background light)) :inherit magit-branch-local :box t)
  100. (((class color) (background dark)) :inherit magit-branch-local :box t))
  101. "Face for current branch."
  102. :group 'magit-faces)
  103. (defface magit-branch-upstream
  104. '((t :slant italic))
  105. "Face for upstream branch.
  106. This face is only used in logs and it gets combined
  107. with `magit-branch-local', `magit-branch-remote'
  108. and/or `magit-branch-remote-head'."
  109. :group 'magit-faces)
  110. (defface magit-head
  111. '((((class color) (background light)) :inherit magit-branch-local)
  112. (((class color) (background dark)) :inherit magit-branch-local))
  113. "Face for the symbolic ref `HEAD'."
  114. :group 'magit-faces)
  115. (defface magit-refname
  116. '((((class color) (background light)) :foreground "grey30")
  117. (((class color) (background dark)) :foreground "grey80"))
  118. "Face for refnames without a dedicated face."
  119. :group 'magit-faces)
  120. (defface magit-refname-stash
  121. '((t :inherit magit-refname))
  122. "Face for stash refnames."
  123. :group 'magit-faces)
  124. (defface magit-refname-wip
  125. '((t :inherit magit-refname))
  126. "Face for wip refnames."
  127. :group 'magit-faces)
  128. (defface magit-refname-pullreq
  129. '((t :inherit magit-refname))
  130. "Face for pullreq refnames."
  131. :group 'magit-faces)
  132. (defface magit-keyword
  133. '((t :inherit font-lock-string-face))
  134. "Face for parts of commit messages inside brackets."
  135. :group 'magit-faces)
  136. (defface magit-keyword-squash
  137. '((t :inherit font-lock-warning-face))
  138. "Face for squash! and fixup! keywords in commit messages."
  139. :group 'magit-faces)
  140. (defface magit-signature-good
  141. '((t :foreground "green"))
  142. "Face for good signatures."
  143. :group 'magit-faces)
  144. (defface magit-signature-bad
  145. '((t :foreground "red" :weight bold))
  146. "Face for bad signatures."
  147. :group 'magit-faces)
  148. (defface magit-signature-untrusted
  149. '((t :foreground "cyan"))
  150. "Face for good untrusted signatures."
  151. :group 'magit-faces)
  152. (defface magit-signature-expired
  153. '((t :foreground "orange"))
  154. "Face for signatures that have expired."
  155. :group 'magit-faces)
  156. (defface magit-signature-expired-key
  157. '((t :inherit magit-signature-expired))
  158. "Face for signatures made by an expired key."
  159. :group 'magit-faces)
  160. (defface magit-signature-revoked
  161. '((t :foreground "violet red"))
  162. "Face for signatures made by a revoked key."
  163. :group 'magit-faces)
  164. (defface magit-signature-error
  165. '((t :foreground "firebrick3"))
  166. "Face for signatures that cannot be checked (e.g. missing key)."
  167. :group 'magit-faces)
  168. (defface magit-cherry-unmatched
  169. '((t :foreground "cyan"))
  170. "Face for unmatched cherry commits."
  171. :group 'magit-faces)
  172. (defface magit-cherry-equivalent
  173. '((t :foreground "magenta"))
  174. "Face for equivalent cherry commits."
  175. :group 'magit-faces)
  176. (defface magit-filename
  177. '((t :weight normal))
  178. "Face for filenames."
  179. :group 'magit-faces)
  180. ;;; Dispatch Popup
  181. ;;;###autoload (autoload 'magit-dispatch "magit" nil t)
  182. (define-transient-command magit-dispatch ()
  183. "Invoke a Magit command from a list of available commands."
  184. ["Transient and dwim commands"
  185. [("A" "Apply" magit-cherry-pick)
  186. ("b" "Branch" magit-branch)
  187. ("B" "Bisect" magit-bisect)
  188. ("c" "Commit" magit-commit)
  189. ("C" "Clone" magit-clone)
  190. ("d" "Diff" magit-diff)
  191. ("D" "Diff (change)" magit-diff-refresh)
  192. ("e" "Ediff (dwim)" magit-ediff-dwim)
  193. ("E" "Ediff" magit-ediff)]
  194. [("f" "Fetch" magit-fetch)
  195. ("F" "Pull" magit-pull)
  196. ("l" "Log" magit-log)
  197. ("L" "Log (change)" magit-log-refresh)
  198. ("m" "Merge" magit-merge)
  199. ("M" "Remote" magit-remote)
  200. ("o" "Submodule" magit-submodule)
  201. ("O" "Subtree" magit-subtree)]
  202. [("P" "Push" magit-push)
  203. ("r" "Rebase" magit-rebase)
  204. ("t" "Tag" magit-tag)
  205. ("T" "Note" magit-notes)
  206. ("V" "Revert" magit-revert)
  207. ("w" "Apply patches" magit-am)
  208. ("W" "Format patches" magit-patch)
  209. ("X" "Reset" magit-reset)]
  210. [("y" "Show Refs" magit-show-refs)
  211. ("Y" "Cherries" magit-cherry)
  212. ("z" "Stash" magit-stash)
  213. ("!" "Run" magit-run)
  214. ("%" "Worktree" magit-worktree)]]
  215. ["Applying changes"
  216. :if-derived magit-mode
  217. [("a" "Apply" magit-apply)
  218. ("v" "Reverse" magit-reverse)
  219. ("k" "Discard" magit-discard)]
  220. [("s" "Stage" magit-stage)
  221. ("u" "Unstage" magit-unstage)]
  222. [("S" "Stage all" magit-stage-modified)
  223. ("U" "Unstage all" magit-unstage-all)]]
  224. ["Essential commands"
  225. :if-derived magit-mode
  226. ("g" " refresh current buffer" magit-refresh)
  227. ("<tab>" " toggle section at point" magit-section-toggle)
  228. ("<return>" "visit thing at point" magit-visit-thing)
  229. ("C-h m" " show all key bindings" describe-mode)])
  230. ;;; Git Popup
  231. (defcustom magit-shell-command-verbose-prompt t
  232. "Whether to show the working directory when reading a command.
  233. This affects `magit-git-command', `magit-git-command-topdir',
  234. `magit-shell-command', and `magit-shell-command-topdir'."
  235. :package-version '(magit . "2.11.0")
  236. :group 'magit-commands
  237. :type 'boolean)
  238. (defvar magit-git-command-history nil)
  239. ;;;###autoload (autoload 'magit-run "magit" nil t)
  240. (define-transient-command magit-run ()
  241. "Run git or another command, or launch a graphical utility."
  242. [["Run git subcommand"
  243. ("!" "in repository root" magit-git-command-topdir)
  244. ("p" "in working directory" magit-git-command)]
  245. ["Run shell command"
  246. ("s" "in repository root" magit-shell-command-topdir)
  247. ("S" "in working directory" magit-shell-command)]
  248. ["Launch"
  249. ("k" "gitk" magit-run-gitk)
  250. ("a" "gitk --all" magit-run-gitk-all)
  251. ("b" "gitk --branches" magit-run-gitk-branches)
  252. ("g" "git gui" magit-run-git-gui)]])
  253. ;;;###autoload
  254. (defun magit-git-command (command)
  255. "Execute COMMAND asynchronously; display output.
  256. Interactively, prompt for COMMAND in the minibuffer. \"git \" is
  257. used as initial input, but can be deleted to run another command.
  258. With a prefix argument COMMAND is run in the top-level directory
  259. of the current working tree, otherwise in `default-directory'."
  260. (interactive (list (magit-read-shell-command nil "git ")))
  261. (magit--shell-command command))
  262. ;;;###autoload
  263. (defun magit-git-command-topdir (command)
  264. "Execute COMMAND asynchronously; display output.
  265. Interactively, prompt for COMMAND in the minibuffer. \"git \" is
  266. used as initial input, but can be deleted to run another command.
  267. COMMAND is run in the top-level directory of the current
  268. working tree."
  269. (interactive (list (magit-read-shell-command t "git ")))
  270. (magit--shell-command command (magit-toplevel)))
  271. ;;;###autoload
  272. (defun magit-shell-command (command)
  273. "Execute COMMAND asynchronously; display output.
  274. Interactively, prompt for COMMAND in the minibuffer. With a
  275. prefix argument COMMAND is run in the top-level directory of
  276. the current working tree, otherwise in `default-directory'."
  277. (interactive (list (magit-read-shell-command)))
  278. (magit--shell-command command))
  279. ;;;###autoload
  280. (defun magit-shell-command-topdir (command)
  281. "Execute COMMAND asynchronously; display output.
  282. Interactively, prompt for COMMAND in the minibuffer. COMMAND
  283. is run in the top-level directory of the current working tree."
  284. (interactive (list (magit-read-shell-command t)))
  285. (magit--shell-command command (magit-toplevel)))
  286. (defun magit--shell-command (command &optional directory)
  287. (let ((default-directory (or directory default-directory))
  288. (process-environment process-environment))
  289. (push "GIT_PAGER=cat" process-environment)
  290. (magit-start-process shell-file-name nil
  291. shell-command-switch command))
  292. (magit-process-buffer))
  293. (defun magit-read-shell-command (&optional toplevel initial-input)
  294. (let ((dir (abbreviate-file-name
  295. (if (or toplevel current-prefix-arg)
  296. (or (magit-toplevel)
  297. (magit--not-inside-repository-error))
  298. default-directory))))
  299. (read-shell-command (if magit-shell-command-verbose-prompt
  300. (format "Async shell command in %s: " dir)
  301. "Async shell command: ")
  302. initial-input 'magit-git-command-history)))
  303. ;;; Font-Lock Keywords
  304. (defconst magit-font-lock-keywords
  305. (eval-when-compile
  306. `((,(concat "(\\(magit-define-section-jumper\\)\\_>"
  307. "[ \t'\(]*"
  308. "\\(\\(?:\\sw\\|\\s_\\)+\\)?")
  309. (1 'font-lock-keyword-face)
  310. (2 'font-lock-function-name-face nil t))
  311. (,(concat "(" (regexp-opt '("magit-insert-section"
  312. "magit-section-case"
  313. "magit-bind-match-strings"
  314. "magit-with-temp-index"
  315. "magit-with-blob"
  316. "magit-with-toplevel") t)
  317. "\\_>")
  318. . 1))))
  319. (font-lock-add-keywords 'emacs-lisp-mode magit-font-lock-keywords)
  320. ;;; Version
  321. (defvar magit-version 'undefined
  322. "The version of Magit that you're using.
  323. Use the function by the same name instead of this variable.")
  324. ;;;###autoload
  325. (defun magit-version (&optional print-dest)
  326. "Return the version of Magit currently in use.
  327. If optional argument PRINT-DEST is non-nil, output
  328. stream (interactively, the echo area, or the current buffer with
  329. a prefix argument), also print the used versions of Magit, Git,
  330. and Emacs to it."
  331. (interactive (list (if current-prefix-arg (current-buffer) t)))
  332. (let ((magit-git-global-arguments nil)
  333. (toplib (or load-file-name buffer-file-name))
  334. debug)
  335. (unless (and toplib
  336. (equal (file-name-nondirectory toplib) "magit.el"))
  337. (setq toplib (locate-library "magit.el")))
  338. (setq toplib (and toplib (file-chase-links toplib)))
  339. (push toplib debug)
  340. (when toplib
  341. (let* ((topdir (file-name-directory toplib))
  342. (gitdir (expand-file-name
  343. ".git" (file-name-directory
  344. (directory-file-name topdir))))
  345. (static (locate-library "magit-version.el" nil (list topdir)))
  346. (static (and static (file-chase-links static))))
  347. (or (progn
  348. (push 'repo debug)
  349. (when (and (file-exists-p gitdir)
  350. ;; It is a repo, but is it the Magit repo?
  351. (file-exists-p
  352. (expand-file-name "../lisp/magit.el" gitdir)))
  353. (push t debug)
  354. ;; Inside the repo the version file should only exist
  355. ;; while running make.
  356. (when (and static (not noninteractive))
  357. (ignore-errors (delete-file static)))
  358. (setq magit-version
  359. (let ((default-directory topdir))
  360. (magit-git-string "describe" "--tags" "--dirty")))))
  361. (progn
  362. (push 'static debug)
  363. (when (and static (file-exists-p static))
  364. (push t debug)
  365. (load-file static)
  366. magit-version))
  367. (when (featurep 'package)
  368. (push 'elpa debug)
  369. (ignore-errors
  370. (--when-let (assq 'magit package-alist)
  371. (push t debug)
  372. (setq magit-version
  373. (and (fboundp 'package-desc-version)
  374. (package-version-join
  375. (package-desc-version (cadr it))))))))
  376. (progn
  377. (push 'dirname debug)
  378. (let ((dirname (file-name-nondirectory
  379. (directory-file-name topdir))))
  380. (when (string-match "\\`magit-\\([0-9]\\{8\\}\\.[0-9]*\\)"
  381. dirname)
  382. (setq magit-version (match-string 1 dirname))))))))
  383. (if (stringp magit-version)
  384. (when print-dest
  385. (princ (format "Magit %s, Git %s, Emacs %s, %s"
  386. (or magit-version "(unknown)")
  387. (or (let ((magit-git-debug
  388. (lambda (err)
  389. (display-warning '(magit git)
  390. err :error))))
  391. (magit-git-version t))
  392. "(unknown)")
  393. emacs-version
  394. system-type)
  395. print-dest))
  396. (setq debug (reverse debug))
  397. (setq magit-version 'error)
  398. (when magit-version
  399. (push magit-version debug))
  400. (unless (equal (getenv "TRAVIS") "true")
  401. ;; The repository is a sparse clone.
  402. (message "Cannot determine Magit's version %S" debug)))
  403. magit-version))
  404. ;;; Debugging Tools
  405. (defun magit-debug-git-executable ()
  406. "Display a buffer with information about `magit-git-executable'.
  407. See info node `(magit)Debugging Tools' for more information."
  408. (interactive)
  409. (with-current-buffer (get-buffer-create "*magit-git-debug*")
  410. (pop-to-buffer (current-buffer))
  411. (erase-buffer)
  412. (insert (concat
  413. (format "magit-git-executable: %S" magit-git-executable)
  414. (and (not (file-name-absolute-p magit-git-executable))
  415. (format " [%S]" (executable-find magit-git-executable)))
  416. (format " (%s)\n"
  417. (let* ((errmsg nil)
  418. (magit-git-debug (lambda (err) (setq errmsg err))))
  419. (or (magit-git-version t) errmsg)))))
  420. (insert (format "exec-path: %S\n" exec-path))
  421. (--when-let (cl-set-difference
  422. (-filter #'file-exists-p (remq nil (parse-colon-path
  423. (getenv "PATH"))))
  424. (-filter #'file-exists-p (remq nil exec-path))
  425. :test #'file-equal-p)
  426. (insert (format " entries in PATH, but not in exec-path: %S\n" it)))
  427. (dolist (execdir exec-path)
  428. (insert (format " %s (%s)\n" execdir (car (file-attributes execdir))))
  429. (when (file-directory-p execdir)
  430. (dolist (exec (directory-files
  431. execdir t (concat
  432. "\\`git" (regexp-opt exec-suffixes) "\\'")))
  433. (insert (format " %s (%s)\n" exec
  434. (let* ((magit-git-executable exec)
  435. (errmsg nil)
  436. (magit-git-debug (lambda (err) (setq errmsg err))))
  437. (or (magit-git-version t) errmsg)))))))))
  438. ;;; Startup Asserts
  439. (defun magit-startup-asserts ()
  440. (when-let ((val (getenv "GIT_DIR")))
  441. (setenv "GIT_DIR")
  442. (message "Magit unset $GIT_DIR (was %S). See \
  443. https://github.com/magit/magit/wiki/Don't-set-$GIT_DIR-and-alike" val))
  444. (when-let ((val (getenv "GIT_WORK_TREE")))
  445. (setenv "GIT_WORK_TREE")
  446. (message "Magit unset $GIT_WORK_TREE (was %S). See \
  447. https://github.com/magit/magit/wiki/Don't-set-$GIT_DIR-and-alike" val))
  448. (let ((version (magit-git-version)))
  449. (when (and version
  450. (version< version magit--minimal-git)
  451. (not (equal (getenv "TRAVIS") "true")))
  452. (display-warning 'magit (format "\
  453. Magit requires Git >= %s, you are using %s.
  454. If this comes as a surprise to you, because you do actually have
  455. a newer version installed, then that probably means that the
  456. older version happens to appear earlier on the `$PATH'. If you
  457. always start Emacs from a shell, then that can be fixed in the
  458. shell's init file. If you start Emacs by clicking on an icon,
  459. or using some sort of application launcher, then you probably
  460. have to adjust the environment as seen by graphical interface.
  461. For X11 something like ~/.xinitrc should work.
  462. If you use Tramp to work inside remote Git repositories, then you
  463. have to make sure a suitable Git is used on the remote machines
  464. too.\n" magit--minimal-git version) :error)))
  465. (when (version< emacs-version magit--minimal-emacs)
  466. (display-warning 'magit (format "\
  467. Magit requires Emacs >= %s, you are using %s.
  468. If this comes as a surprise to you, because you do actually have
  469. a newer version installed, then that probably means that the
  470. older version happens to appear earlier on the `$PATH'. If you
  471. always start Emacs from a shell, then that can be fixed in the
  472. shell's init file. If you start Emacs by clicking on an icon,
  473. or using some sort of application launcher, then you probably
  474. have to adjust the environment as seen by graphical interface.
  475. For X11 something like ~/.xinitrc should work.\n"
  476. magit--minimal-emacs emacs-version)
  477. :error)))
  478. ;;; Loading Libraries
  479. (provide 'magit)
  480. (cl-eval-when (load eval)
  481. (require 'magit-status)
  482. (require 'magit-refs)
  483. (require 'magit-files)
  484. (require 'magit-reset)
  485. (require 'magit-branch)
  486. (require 'magit-merge)
  487. (require 'magit-tag)
  488. (require 'magit-worktree)
  489. (require 'magit-notes)
  490. (require 'magit-sequence)
  491. (require 'magit-commit)
  492. (require 'magit-remote)
  493. (require 'magit-clone)
  494. (require 'magit-fetch)
  495. (require 'magit-pull)
  496. (require 'magit-push)
  497. (require 'magit-bisect)
  498. (require 'magit-stash)
  499. (require 'magit-blame)
  500. (require 'magit-obsolete)
  501. (require 'magit-submodule)
  502. (unless (load "magit-autoloads" t t)
  503. (require 'magit-patch)
  504. (require 'magit-subtree)
  505. (require 'magit-ediff)
  506. (require 'magit-gitignore)
  507. (require 'magit-extras)
  508. (require 'git-rebase)
  509. (require 'magit-imenu)
  510. (require 'magit-bookmark)))
  511. (eval-after-load 'bookmark
  512. '(require 'magit-bookmark))
  513. (if after-init-time
  514. (progn (magit-startup-asserts)
  515. (magit-version))
  516. (add-hook 'after-init-hook #'magit-startup-asserts t)
  517. (add-hook 'after-init-hook #'magit-version t))
  518. ;;; magit.el ends here