From 6ca9eb9da567a1a6291fc0a45a7496e0a285ff25 Mon Sep 17 00:00:00 2001 From: Marcus Kammer <2262664-marcuskammer@users.noreply.gitlab.com> Date: Fri, 22 Nov 2019 22:45:34 +0100 Subject: [PATCH] Refresh elpa dir --- elpa/archives/melpa/archive-contents | 22 +- .../berrys-theme-autoloads.el | 24 + .../berrys-theme-pkg.el | 2 + .../berrys-theme.el | 399 + elpa/magit-20191122.2040/AUTHORS.md | 341 + elpa/magit-20191122.2040/LICENSE | 676 ++ elpa/magit-20191122.2040/dir | 18 + elpa/magit-20191122.2040/git-rebase.el | 818 ++ elpa/magit-20191122.2040/git-rebase.elc | Bin 0 -> 27987 bytes elpa/magit-20191122.2040/magit-apply.el | 739 ++ elpa/magit-20191122.2040/magit-apply.elc | Bin 0 -> 31993 bytes elpa/magit-20191122.2040/magit-autoloads.el | 2510 ++++++ elpa/magit-20191122.2040/magit-autorevert.el | 258 + elpa/magit-20191122.2040/magit-autorevert.elc | Bin 0 -> 12107 bytes elpa/magit-20191122.2040/magit-bisect.el | 239 + elpa/magit-20191122.2040/magit-bisect.elc | Bin 0 -> 15636 bytes elpa/magit-20191122.2040/magit-blame.el | 954 ++ elpa/magit-20191122.2040/magit-blame.elc | Bin 0 -> 37852 bytes elpa/magit-20191122.2040/magit-bookmark.el | 203 + elpa/magit-20191122.2040/magit-bookmark.elc | Bin 0 -> 5676 bytes elpa/magit-20191122.2040/magit-branch.el | 887 ++ elpa/magit-20191122.2040/magit-branch.elc | Bin 0 -> 37160 bytes elpa/magit-20191122.2040/magit-clone.el | 267 + elpa/magit-20191122.2040/magit-clone.elc | Bin 0 -> 11156 bytes elpa/magit-20191122.2040/magit-commit.el | 570 ++ elpa/magit-20191122.2040/magit-commit.elc | Bin 0 -> 22559 bytes elpa/magit-20191122.2040/magit-core.el | 126 + elpa/magit-20191122.2040/magit-core.elc | Bin 0 -> 2968 bytes elpa/magit-20191122.2040/magit-diff.el | 3162 +++++++ elpa/magit-20191122.2040/magit-diff.elc | Bin 0 -> 156338 bytes elpa/magit-20191122.2040/magit-ediff.el | 509 ++ elpa/magit-20191122.2040/magit-ediff.elc | Bin 0 -> 18902 bytes elpa/magit-20191122.2040/magit-extras.el | 649 ++ elpa/magit-20191122.2040/magit-extras.elc | Bin 0 -> 22004 bytes elpa/magit-20191122.2040/magit-fetch.el | 186 + elpa/magit-20191122.2040/magit-fetch.elc | Bin 0 -> 7101 bytes elpa/magit-20191122.2040/magit-files.el | 558 ++ elpa/magit-20191122.2040/magit-files.elc | Bin 0 -> 26952 bytes elpa/magit-20191122.2040/magit-git.el | 2302 +++++ elpa/magit-20191122.2040/magit-git.elc | Bin 0 -> 91005 bytes elpa/magit-20191122.2040/magit-gitignore.el | 197 + elpa/magit-20191122.2040/magit-gitignore.elc | Bin 0 -> 7378 bytes elpa/magit-20191122.2040/magit-imenu.el | 245 + elpa/magit-20191122.2040/magit-imenu.elc | Bin 0 -> 6830 bytes elpa/magit-20191122.2040/magit-log.el | 1774 ++++ elpa/magit-20191122.2040/magit-log.elc | Bin 0 -> 98207 bytes elpa/magit-20191122.2040/magit-margin.el | 241 + elpa/magit-20191122.2040/magit-margin.elc | Bin 0 -> 8237 bytes elpa/magit-20191122.2040/magit-merge.el | 302 + elpa/magit-20191122.2040/magit-merge.elc | Bin 0 -> 13563 bytes elpa/magit-20191122.2040/magit-mode.el | 1549 ++++ elpa/magit-20191122.2040/magit-mode.elc | Bin 0 -> 59591 bytes elpa/magit-20191122.2040/magit-notes.el | 200 + elpa/magit-20191122.2040/magit-notes.elc | Bin 0 -> 9045 bytes elpa/magit-20191122.2040/magit-obsolete.el | 106 + elpa/magit-20191122.2040/magit-obsolete.elc | Bin 0 -> 3795 bytes elpa/magit-20191122.2040/magit-patch.el | 267 + elpa/magit-20191122.2040/magit-patch.elc | Bin 0 -> 13403 bytes elpa/magit-20191122.2040/magit-pkg.el | 12 + elpa/magit-20191122.2040/magit-process.el | 1154 +++ elpa/magit-20191122.2040/magit-process.elc | Bin 0 -> 45899 bytes elpa/magit-20191122.2040/magit-pull.el | 163 + elpa/magit-20191122.2040/magit-pull.elc | Bin 0 -> 6144 bytes elpa/magit-20191122.2040/magit-push.el | 319 + elpa/magit-20191122.2040/magit-push.elc | Bin 0 -> 12261 bytes elpa/magit-20191122.2040/magit-reflog.el | 213 + elpa/magit-20191122.2040/magit-reflog.elc | Bin 0 -> 9998 bytes elpa/magit-20191122.2040/magit-refs.el | 757 ++ elpa/magit-20191122.2040/magit-refs.elc | Bin 0 -> 40256 bytes elpa/magit-20191122.2040/magit-remote.el | 341 + elpa/magit-20191122.2040/magit-remote.elc | Bin 0 -> 14859 bytes elpa/magit-20191122.2040/magit-repos.el | 339 + elpa/magit-20191122.2040/magit-repos.elc | Bin 0 -> 14542 bytes elpa/magit-20191122.2040/magit-reset.el | 127 + elpa/magit-20191122.2040/magit-reset.elc | Bin 0 -> 5544 bytes elpa/magit-20191122.2040/magit-section.el | 1666 ++++ elpa/magit-20191122.2040/magit-section.elc | Bin 0 -> 62655 bytes elpa/magit-20191122.2040/magit-sequence.el | 1029 +++ elpa/magit-20191122.2040/magit-sequence.elc | Bin 0 -> 52139 bytes elpa/magit-20191122.2040/magit-stash.el | 546 ++ elpa/magit-20191122.2040/magit-stash.elc | Bin 0 -> 35517 bytes elpa/magit-20191122.2040/magit-status.el | 793 ++ elpa/magit-20191122.2040/magit-status.elc | Bin 0 -> 57132 bytes elpa/magit-20191122.2040/magit-submodule.el | 665 ++ elpa/magit-20191122.2040/magit-submodule.elc | Bin 0 -> 38467 bytes elpa/magit-20191122.2040/magit-subtree.el | 182 + elpa/magit-20191122.2040/magit-subtree.elc | Bin 0 -> 9095 bytes elpa/magit-20191122.2040/magit-tag.el | 193 + elpa/magit-20191122.2040/magit-tag.elc | Bin 0 -> 7151 bytes elpa/magit-20191122.2040/magit-transient.el | 202 + elpa/magit-20191122.2040/magit-transient.elc | Bin 0 -> 8360 bytes elpa/magit-20191122.2040/magit-utils.el | 1205 +++ elpa/magit-20191122.2040/magit-utils.elc | Bin 0 -> 40322 bytes elpa/magit-20191122.2040/magit-wip.el | 432 + elpa/magit-20191122.2040/magit-wip.elc | Bin 0 -> 26804 bytes elpa/magit-20191122.2040/magit-worktree.el | 184 + elpa/magit-20191122.2040/magit-worktree.elc | Bin 0 -> 8598 bytes elpa/magit-20191122.2040/magit.el | 596 ++ elpa/magit-20191122.2040/magit.elc | Bin 0 -> 20434 bytes elpa/magit-20191122.2040/magit.info | 189 + elpa/magit-20191122.2040/magit.info-1 | 7784 +++++++++++++++++ elpa/magit-20191122.2040/magit.info-2 | 3497 ++++++++ .../org-clock-csv-autoloads.el | 55 + .../org-clock-csv-pkg.el | 2 + .../org-clock-csv.el | 305 + .../org-clock-csv.elc | Bin 0 -> 9306 bytes .../org-clock-today-autoloads.el | 38 + .../org-clock-today-pkg.el | 2 + .../org-clock-today.el | 140 + .../org-clock-today.elc | Bin 0 -> 5722 bytes 110 files changed, 44419 insertions(+), 11 deletions(-) create mode 100644 elpa/berrys-theme-20191106.1423/berrys-theme-autoloads.el create mode 100644 elpa/berrys-theme-20191106.1423/berrys-theme-pkg.el create mode 100644 elpa/berrys-theme-20191106.1423/berrys-theme.el create mode 100644 elpa/magit-20191122.2040/AUTHORS.md create mode 100644 elpa/magit-20191122.2040/LICENSE create mode 100644 elpa/magit-20191122.2040/dir create mode 100644 elpa/magit-20191122.2040/git-rebase.el create mode 100644 elpa/magit-20191122.2040/git-rebase.elc create mode 100644 elpa/magit-20191122.2040/magit-apply.el create mode 100644 elpa/magit-20191122.2040/magit-apply.elc create mode 100644 elpa/magit-20191122.2040/magit-autoloads.el create mode 100644 elpa/magit-20191122.2040/magit-autorevert.el create mode 100644 elpa/magit-20191122.2040/magit-autorevert.elc create mode 100644 elpa/magit-20191122.2040/magit-bisect.el create mode 100644 elpa/magit-20191122.2040/magit-bisect.elc create mode 100644 elpa/magit-20191122.2040/magit-blame.el create mode 100644 elpa/magit-20191122.2040/magit-blame.elc create mode 100644 elpa/magit-20191122.2040/magit-bookmark.el create mode 100644 elpa/magit-20191122.2040/magit-bookmark.elc create mode 100644 elpa/magit-20191122.2040/magit-branch.el create mode 100644 elpa/magit-20191122.2040/magit-branch.elc create mode 100644 elpa/magit-20191122.2040/magit-clone.el create mode 100644 elpa/magit-20191122.2040/magit-clone.elc create mode 100644 elpa/magit-20191122.2040/magit-commit.el create mode 100644 elpa/magit-20191122.2040/magit-commit.elc create mode 100644 elpa/magit-20191122.2040/magit-core.el create mode 100644 elpa/magit-20191122.2040/magit-core.elc create mode 100644 elpa/magit-20191122.2040/magit-diff.el create mode 100644 elpa/magit-20191122.2040/magit-diff.elc create mode 100644 elpa/magit-20191122.2040/magit-ediff.el create mode 100644 elpa/magit-20191122.2040/magit-ediff.elc create mode 100644 elpa/magit-20191122.2040/magit-extras.el create mode 100644 elpa/magit-20191122.2040/magit-extras.elc create mode 100644 elpa/magit-20191122.2040/magit-fetch.el create mode 100644 elpa/magit-20191122.2040/magit-fetch.elc create mode 100644 elpa/magit-20191122.2040/magit-files.el create mode 100644 elpa/magit-20191122.2040/magit-files.elc create mode 100644 elpa/magit-20191122.2040/magit-git.el create mode 100644 elpa/magit-20191122.2040/magit-git.elc create mode 100644 elpa/magit-20191122.2040/magit-gitignore.el create mode 100644 elpa/magit-20191122.2040/magit-gitignore.elc create mode 100644 elpa/magit-20191122.2040/magit-imenu.el create mode 100644 elpa/magit-20191122.2040/magit-imenu.elc create mode 100644 elpa/magit-20191122.2040/magit-log.el create mode 100644 elpa/magit-20191122.2040/magit-log.elc create mode 100644 elpa/magit-20191122.2040/magit-margin.el create mode 100644 elpa/magit-20191122.2040/magit-margin.elc create mode 100644 elpa/magit-20191122.2040/magit-merge.el create mode 100644 elpa/magit-20191122.2040/magit-merge.elc create mode 100644 elpa/magit-20191122.2040/magit-mode.el create mode 100644 elpa/magit-20191122.2040/magit-mode.elc create mode 100644 elpa/magit-20191122.2040/magit-notes.el create mode 100644 elpa/magit-20191122.2040/magit-notes.elc create mode 100644 elpa/magit-20191122.2040/magit-obsolete.el create mode 100644 elpa/magit-20191122.2040/magit-obsolete.elc create mode 100644 elpa/magit-20191122.2040/magit-patch.el create mode 100644 elpa/magit-20191122.2040/magit-patch.elc create mode 100644 elpa/magit-20191122.2040/magit-pkg.el create mode 100644 elpa/magit-20191122.2040/magit-process.el create mode 100644 elpa/magit-20191122.2040/magit-process.elc create mode 100644 elpa/magit-20191122.2040/magit-pull.el create mode 100644 elpa/magit-20191122.2040/magit-pull.elc create mode 100644 elpa/magit-20191122.2040/magit-push.el create mode 100644 elpa/magit-20191122.2040/magit-push.elc create mode 100644 elpa/magit-20191122.2040/magit-reflog.el create mode 100644 elpa/magit-20191122.2040/magit-reflog.elc create mode 100644 elpa/magit-20191122.2040/magit-refs.el create mode 100644 elpa/magit-20191122.2040/magit-refs.elc create mode 100644 elpa/magit-20191122.2040/magit-remote.el create mode 100644 elpa/magit-20191122.2040/magit-remote.elc create mode 100644 elpa/magit-20191122.2040/magit-repos.el create mode 100644 elpa/magit-20191122.2040/magit-repos.elc create mode 100644 elpa/magit-20191122.2040/magit-reset.el create mode 100644 elpa/magit-20191122.2040/magit-reset.elc create mode 100644 elpa/magit-20191122.2040/magit-section.el create mode 100644 elpa/magit-20191122.2040/magit-section.elc create mode 100644 elpa/magit-20191122.2040/magit-sequence.el create mode 100644 elpa/magit-20191122.2040/magit-sequence.elc create mode 100644 elpa/magit-20191122.2040/magit-stash.el create mode 100644 elpa/magit-20191122.2040/magit-stash.elc create mode 100644 elpa/magit-20191122.2040/magit-status.el create mode 100644 elpa/magit-20191122.2040/magit-status.elc create mode 100644 elpa/magit-20191122.2040/magit-submodule.el create mode 100644 elpa/magit-20191122.2040/magit-submodule.elc create mode 100644 elpa/magit-20191122.2040/magit-subtree.el create mode 100644 elpa/magit-20191122.2040/magit-subtree.elc create mode 100644 elpa/magit-20191122.2040/magit-tag.el create mode 100644 elpa/magit-20191122.2040/magit-tag.elc create mode 100644 elpa/magit-20191122.2040/magit-transient.el create mode 100644 elpa/magit-20191122.2040/magit-transient.elc create mode 100644 elpa/magit-20191122.2040/magit-utils.el create mode 100644 elpa/magit-20191122.2040/magit-utils.elc create mode 100644 elpa/magit-20191122.2040/magit-wip.el create mode 100644 elpa/magit-20191122.2040/magit-wip.elc create mode 100644 elpa/magit-20191122.2040/magit-worktree.el create mode 100644 elpa/magit-20191122.2040/magit-worktree.elc create mode 100644 elpa/magit-20191122.2040/magit.el create mode 100644 elpa/magit-20191122.2040/magit.elc create mode 100644 elpa/magit-20191122.2040/magit.info create mode 100644 elpa/magit-20191122.2040/magit.info-1 create mode 100644 elpa/magit-20191122.2040/magit.info-2 create mode 100644 elpa/org-clock-csv-20190418.1505/org-clock-csv-autoloads.el create mode 100644 elpa/org-clock-csv-20190418.1505/org-clock-csv-pkg.el create mode 100644 elpa/org-clock-csv-20190418.1505/org-clock-csv.el create mode 100644 elpa/org-clock-csv-20190418.1505/org-clock-csv.elc create mode 100644 elpa/org-clock-today-20190915.701/org-clock-today-autoloads.el create mode 100644 elpa/org-clock-today-20190915.701/org-clock-today-pkg.el create mode 100644 elpa/org-clock-today-20190915.701/org-clock-today.el create mode 100644 elpa/org-clock-today-20190915.701/org-clock-today.elc diff --git a/elpa/archives/melpa/archive-contents b/elpa/archives/melpa/archive-contents index a71ef40b..8a527dbf 100644 --- a/elpa/archives/melpa/archive-contents +++ b/elpa/archives/melpa/archive-contents @@ -651,7 +651,7 @@ (sly-macrostep . [(20191013 2138) ((sly (1 0 0 -2 2)) (macrostep (0 9))) "fancy macro-expansion via macrostep.el" tar ((:commit . "be2d24545092d164be1a91031d8881afd29c9ec0") (:keywords "languages" "lisp" "sly") (:url . "https://github.com/capitaomorte/sly-macrostep"))]) (sly-hello-world . [(20191013 2137) ((sly (1 0 0 -2 2))) "A template SLY contrib" tar ((:commit . "ae8fe0a0ebcce50425a1d411c027db06ddec39ce") (:keywords "languages" "lisp" "sly") (:authors ("João Távora" . "joaotavora@gmail.com")) (:maintainer "João Távora" . "joaotavora@gmail.com") (:url . "https://github.com/capitaomorte/sly-hello-world"))]) (sly-asdf . [(20191021 718) ((emacs (24 3)) (sly (1 0 0 -2 2))) "ASDF system support for SLY" tar ((:commit . "69123fcebe63bb4d6e40e3dcb187299622401b74") (:keywords "languages" "lisp" "sly" "asdf") (:maintainer "Matt George" . "mmge93@gmail.com") (:url . "https://github.com/mmgeorge/sly-asdf"))]) -(sly . [(20191031 1436) ((emacs (24 3))) "Sylvester the Cat's Common Lisp IDE" tar ((:commit . "bf041ba035c34600e5470feac0d988abd89d8770") (:keywords "languages" "lisp" "sly") (:url . "https://github.com/joaotavora/sly"))]) +(sly . [(20191122 1849) ((emacs (24 3))) "Sylvester the Cat's Common Lisp IDE" tar ((:commit . "a41e69006cf921679283896f85b6afacf91aa06f") (:keywords "languages" "lisp" "sly") (:url . "https://github.com/joaotavora/sly"))]) (slstats . [(20170823 849) ((cl-lib (0 5)) (emacs (24))) "Acquire and display stats about Second Life" single ((:commit . "e9696066abf3f2b7b818a57c062530dfd9377033") (:keywords "games") (:authors ("Dave Pearson" . "davep@davep.org")) (:maintainer "Dave Pearson" . "davep@davep.org") (:url . "https://github.com/davep/slstats.el"))]) (slow-keys . [(20180831 459) ((emacs (24 1))) "Slow keys mode to avoid RSI" single ((:commit . "b93ad77f9fc1d14e080d7d64864fc9cb222248b6") (:keywords "convenience") (:authors ("Manuel Uberti" . "manuel.uberti@inventati.org")) (:maintainer "Manuel Uberti" . "manuel.uberti@inventati.org") (:url . "https://github.com/manuel-uberti/slow-keys"))]) (slovak-holidays . [(20150418 855) nil "Adds a list of slovak holidays to Emacs calendar" single ((:commit . "effb16dfcd14797bf7448f5113085479db339c02") (:keywords "calendar") (:authors ("Matúš Goljer" . "matus.goljer@gmail.com")) (:maintainer "Matúš Goljer" . "matus.goljer@gmail.com"))]) @@ -1030,7 +1030,7 @@ (psc-ide . [(20190326 2110) ((emacs (25)) (dash (2 13 0)) (dash-functional (1 2 0)) (company (0 8 7)) (s (1 10 0)) (flycheck (0 24)) (let-alist (1 0 4)) (seq (1 11))) "Minor mode for PureScript's psc-ide tool." tar ((:commit . "a10cc85565f330ee277698b27f3f715fef2e1ce2") (:keywords "languages") (:authors ("Erik Post" . "erik@shinsetsu.nl") ("Dmitry Bushenko" . "d.bushenko@gmail.com") ("Christoph Hegemann") ("Brian Sermons")) (:maintainer "Erik Post" . "erik@shinsetsu.nl") (:url . "https://github.com/epost/psc-ide-emacs"))]) (proxy-mode . [(20190130 8) ((emacs (25))) "A minor mode to toggle proxy." single ((:commit . "a6c55e97dbe4ec4df9dc21d234cabe806dce3a29") (:keywords "comm" "proxy") (:url . "https://github.com/stardiviner/proxy-mode"))]) (protocols . [(20170802 1132) ((cl-lib (0 5))) "Protocol database access functions." single ((:commit . "d0f7c4acb05465f1a0d4be54363bbd2802647e77") (:keywords "convenience" "net" "protocols") (:authors ("Dave Pearson" . "davep@davep.org")) (:maintainer "Dave Pearson" . "davep@davep.org") (:url . "https://github.com/davep/protocols.el"))]) -(protobuf-mode . [(20170526 1650) nil "major mode for editing protocol buffers." single ((:commit . "6d7bb7e7143ea2b93dfaa411510c96b0b47d141c") (:keywords "google" "protobuf" "languages") (:authors ("Alexandre Vassalotti" . "alexandre@peadrop.com")) (:maintainer "Alexandre Vassalotti" . "alexandre@peadrop.com"))]) +(protobuf-mode . [(20170526 1650) nil "major mode for editing protocol buffers." single ((:commit . "a9f390f44e3d138e1e94fd17046f865517b3b62d") (:keywords "google" "protobuf" "languages") (:authors ("Alexandre Vassalotti" . "alexandre@peadrop.com")) (:maintainer "Alexandre Vassalotti" . "alexandre@peadrop.com"))]) (prosjekt . [(20151127 1416) ((dash (2 8 0))) "a software project tool for emacs" tar ((:commit . "a864a8be5842223043702395f311e3350c28e9db") (:authors ("Austin Bingham" . "austin.bingham@gmail.com")) (:maintainer "Austin Bingham" . "austin.bingham@gmail.com") (:url . "https://github.com/abingham/prosjekt"))]) (proportional . [(20190806 1901) ((emacs (25 1))) "use a proportional font everywhere" single ((:commit . "f600b7ed2ab19a3072adad3f47048a5bbdb82703") (:keywords "faces") (:authors ("Johannes Goslar")) (:maintainer "Johannes Goslar") (:url . "https://github.com/ksjogo/proportional"))]) (propfont-mixed . [(20150113 2211) ((emacs (24)) (cl-lib (0 5))) "Use proportional fonts with space-based indentation." single ((:commit . "0b461ef4754a469610dba71874a34b6da42176bf") (:keywords "faces") (:authors ("Kirill Ignatiev ")) (:maintainer "Kirill Ignatiev ") (:url . "https://github.com/ikirill/propfont-mixed"))]) @@ -1892,7 +1892,7 @@ (magit-popup . [(20190223 2234) ((emacs (24 4)) (async (1 9 2)) (dash (2 13 0))) "Define prefix-infix-suffix command combos" tar ((:commit . "4250c3a606011e3ff2477e3b5bbde2b493f3c85c") (:keywords "bindings") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:url . "https://github.com/magit/magit-popup"))]) (magit-p4 . [(20170414 1246) ((magit (2 1)) (magit-popup (2 1)) (p4 (12 0)) (cl-lib (0 5))) "git-p4 plug-in for Magit" single ((:commit . "cdc05f2d564409baac9ca15b1a2a0110a6ff12b7") (:keywords "vc" "tools") (:authors ("Damian T. Dobroczy\\\\'nski" . "qoocku@gmail.com")) (:maintainer "Aleksey Fedotov" . "lexa@cfotr.com") (:url . "https://github.com/qoocku/magit-p4"))]) (magit-org-todos . [(20180709 1950) ((magit (2 0 0)) (emacs (24))) "Add local todo items to the magit status buffer" single ((:commit . "9ffa3efb098434d837cab4bacd1601fdfc6fe999") (:keywords "org-mode" "magit" "tools") (:authors ("Daniel Ma")) (:maintainer "Daniel Ma") (:url . "http://github.com/danielma/magit-org-todos"))]) -(magit-libgit . [(20190419 1545) ((emacs (26 1)) (magit (0)) (libgit (0))) "Libgit functionality" single ((:commit . "c8e76221a28b7ec02ed6f29c0392f7bed8521a63") (:keywords "git" "tools" "vc") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:url . "https://github.com/magit/magit"))]) +(magit-libgit . [(20190419 1545) ((emacs (26 1)) (magit (0)) (libgit (0))) "Libgit functionality" single ((:commit . "5560f91fa51cb6a9add0cfb4dc2cf2635f5ae5bc") (:keywords "git" "tools" "vc") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:url . "https://github.com/magit/magit"))]) (magit-lfs . [(20190831 118) ((emacs (24 4)) (magit (2 10 3)) (dash (2 13 0))) "Magit plugin for Git LFS" single ((:commit . "75bf6d3310eae24889589a09e96a4a855e1a11c4") (:keywords "magit" "git" "lfs" "tools" "vc") (:authors ("Junyoung Clare Jang" . "jjc9310@gmail.com")) (:maintainer "Junyoung Clare Jang" . "jjc9310@gmail.com") (:url . "https://github.com/ailrun/magit-lfs"))]) (magit-imerge . [(20191105 2245) ((emacs (24 4)) (magit (2 10 0))) "Magit extension for git-imerge" single ((:commit . "a7357ab87c89187234fe333bb869727c417638d1") (:keywords "vc" "tools") (:authors ("Kyle Meyer" . "kyle@kyleam.com")) (:maintainer "Kyle Meyer" . "kyle@kyleam.com") (:url . "https://github.com/magit/magit-imerge"))]) (magit-gitflow . [(20170929 824) ((magit (2 1 0)) (magit-popup (2 2 0))) "gitflow extension for magit" single ((:commit . "cc41b561ec6eea947fe9a176349fb4f771ed865b") (:keywords "vc" "tools") (:authors ("Jan Tatarik" . "Jan.Tatarik@gmail.com")) (:maintainer "Jan Tatarik" . "Jan.Tatarik@gmail.com") (:url . "https://github.com/jtatarik/magit-gitflow"))]) @@ -1903,7 +1903,7 @@ (magit-diff-flycheck . [(20190524 551) ((magit (2)) (flycheck (31)) (seq (2)) (emacs (25 1))) "Report errors in diffs" single ((:commit . "28acf74f59e385865746cccf4b1e4c4025ae9433") (:keywords "convenience" "matching") (:authors ("Alex Ragone" . "ragonedk@gmail.com")) (:maintainer "Alex Ragone" . "ragonedk@gmail.com") (:url . "https://github.com/ragone/magit-diff-flycheck"))]) (magit-circleci . [(20190814 1723) ((dash (2 16 0)) (transient (0 1 0)) (magit (2 90 0)) (emacs (25 3))) "CircleCI integration for Magit" single ((:commit . "03101bd9cdbdfd779471a4c6d3d00ebadc8ca4a2") (:keywords "circleci" "continuous" "integration" "magit" "vc" "tools") (:authors ("Adrien Brochard")) (:maintainer "Adrien Brochard") (:url . "https://github.com/abrochard/magit-circleci"))]) (magit-annex . [(20190421 241) ((cl-lib (0 3)) (magit (2 90 0))) "Control git-annex from Magit" single ((:commit . "d5d819c609256a3b7b11ccaf6664be61aa3597b6") (:keywords "vc" "tools") (:authors ("Kyle Meyer" . "kyle@kyleam.com") ("Rémi Vanicat" . "vanicat@debian.org")) (:maintainer "Kyle Meyer" . "kyle@kyleam.com") (:url . "https://github.com/magit/magit-annex"))]) -(magit . [(20191120 1637) ((emacs (25 1)) (async (20180527)) (dash (20180910)) (git-commit (20181104)) (transient (20190812)) (with-editor (20181103))) "A Git porcelain inside Emacs." tar ((:commit . "c8e76221a28b7ec02ed6f29c0392f7bed8521a63") (:keywords "git" "tools" "vc"))]) +(magit . [(20191122 2040) ((emacs (25 1)) (async (20180527)) (dash (20180910)) (git-commit (20181104)) (transient (20190812)) (with-editor (20181103))) "A Git porcelain inside Emacs." tar ((:commit . "5560f91fa51cb6a9add0cfb4dc2cf2635f5ae5bc") (:keywords "git" "tools" "vc"))]) (magik-mode . [(20191119 2050) nil "mode for editing Magik + some utils." tar ((:commit . "11ea02254f2bdfaecc12a75545c558fd37b98954") (:keywords "languages") (:url . "http://github.com/roadrunner1776/magik"))]) (magic-latex-buffer . [(20191106 241) ((cl-lib (0 5)) (emacs (24 3))) "Magically enhance LaTeX-mode font-locking for semi-WYSIWYG editing" single ((:commit . "8597f4db70732d6e479396e2f2a7e78742387253") (:authors ("zk_phi")) (:maintainer "zk_phi") (:url . "http://hins11.yu-yake.com/"))]) (magic-filetype . [(20180219 1552) ((emacs (24)) (s (1 9 0))) "Enhance filetype major mode" single ((:commit . "019494add5ff02dd36cb3f500142fc51125522cc") (:keywords "emulations" "vim" "ft" "file" "magic-mode") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:url . "https://github.com/zonuexe/magic-filetype.el"))]) @@ -1923,7 +1923,7 @@ (lush-theme . [(20180816 2200) ((emacs (24))) "A dark theme with lush colors" single ((:commit . "7cfc993709d712f75c51b505078608c9e1c11466") (:keywords "theme" "dark" "strong colors") (:authors ("Andre Richter" . "andre.o.richter@gmail.com")) (:maintainer "Andre Richter" . "andre.o.richter@gmail.com") (:url . "https://github.com/andre-richter/emacs-lush-theme"))]) (luarocks . [(20170430 2305) ((emacs (24)) (cl-lib (0 5))) "luarocks tools" single ((:commit . "cee27ba0716edf338077387969883226dd2b7484") (:keywords "convenience") (:authors ("Mario Rodas" . "marsam@users.noreply.github.com")) (:maintainer "Mario Rodas" . "marsam@users.noreply.github.com") (:url . "https://github.com/emacs-pe/luarocks.el"))]) (lua-mode . [(20191111 809) nil "a major-mode for editing Lua scripts" tar ((:commit . "dc302400e38d19cf2bd94d0c30d659ffaf10c6d2") (:keywords "languages" "processes" "tools") (:authors ("2011-2013 immerrr" . "immerrr+lua@gmail.com") ("2010-2011 Reuben Thomas" . "rrt@sc3d.org") ("2006 Juergen Hoetzel" . "juergen@hoetzel.info") ("2004 various (support for Lua 5 and byte compilation)") ("2001 Christian Vogler" . "cvogler@gradient.cis.upenn.edu") ("1997 Bret Mogilefsky" . "mogul-lua@gelatinous.com") ("tcl-mode by Gregor Schmid" . "schmid@fb3-s7.math.tu-berlin.de") ("with tons of assistance from") ("Paul Du Bois" . "pld-lua@gelatinous.com") ("Aaron Smith" . "aaron-lua@gelatinous.com")) (:maintainer "2011-2013 immerrr" . "immerrr+lua@gmail.com") (:url . "http://immerrr.github.com/lua-mode"))]) -(lsp-ui . [(20191120 1853) ((emacs (25 1)) (dash (2 14)) (dash-functional (1 2 0)) (lsp-mode (6 0)) (markdown-mode (2 3))) "UI modules for lsp-mode" tar ((:commit . "46f4d7d2c0b953b25c2d6414e842239d1bb3a71c") (:keywords "lsp") (:authors ("Sebastien Chapuis , Fangrui Song" . "i@maskray.me")) (:maintainer "Sebastien Chapuis , Fangrui Song" . "i@maskray.me") (:url . "https://github.com/emacs-lsp/lsp-ui"))]) +(lsp-ui . [(20191122 1942) ((emacs (25 1)) (dash (2 14)) (dash-functional (1 2 0)) (lsp-mode (6 0)) (markdown-mode (2 3))) "UI modules for lsp-mode" tar ((:commit . "c5a9221ac67f060a3f4e4be526893afee629b14f") (:keywords "lsp") (:authors ("Sebastien Chapuis , Fangrui Song" . "i@maskray.me")) (:maintainer "Sebastien Chapuis , Fangrui Song" . "i@maskray.me") (:url . "https://github.com/emacs-lsp/lsp-ui"))]) (lsp-treemacs . [(20191121 1951) ((emacs (25 1)) (dash (2 14 1)) (dash-functional (2 14 1)) (f (0 20 0)) (ht (2 0)) (treemacs (2 5)) (lsp-mode (6 0))) "LSP treemacs" tar ((:commit . "ee56c75ea342e6d5803518f7b577e0039c93e032") (:keywords "languages") (:authors ("Ivan Yonchovski")) (:maintainer "Ivan Yonchovski") (:url . "https://github.com/emacs-lsp/lsp-treemacs"))]) (lsp-sourcekit . [(20181216 1450) ((emacs (25 1)) (lsp-mode (5))) "sourcekit-lsp client for lsp-mode" single ((:commit . "04d75b6a0be5894fea4a55fec0b2ccedf5b3be58") (:keywords "languages" "lsp" "swift" "objective-c" "c++") (:authors ("Daniel Martín")) (:maintainer "Daniel Martín") (:url . "https://github.com/emacs-lsp/lsp-sourcekit"))]) (lsp-scala . [(20190604 1237) ((emacs (24 4)) (lsp-mode (5 0)) (sbt-mode (2 0))) "Scala support for lsp-mode" single ((:commit . "06f189aa5cafe93cecbdaa234bccd900def7bc68") (:keywords "languages" "tools" "scala" "lsp" "metals") (:authors ("Ross A. Baker" . "ross@rossabaker.com")) (:maintainer "Ross A. Baker" . "ross@rossabaker.com") (:url . "https://github.com/rossabaker/lsp-scala"))]) @@ -2123,7 +2123,7 @@ (jump . [(20161127 128) ((findr (0 7)) (inflections (2 4)) (cl-lib (0 5))) "build functions which contextually jump between files" single ((:commit . "e4f1372cf22e811faca52fc86bdd5d817498a4d8") (:keywords "project" "convenience" "navigation") (:authors ("Eric Schulte")) (:maintainer "Eric Schulte") (:url . "http://github.com/eschulte/jump.el"))]) (jumblr . [(20170727 2043) ((s (1 8 0)) (dash (2 2 0))) "an anagram game for emacs" tar ((:commit . "34533dfb9db8538c005f4eaffafeff7ed193729f") (:keywords "anagram" "word game" "games") (:url . "https://github.com/mkmcc/jumblr"))]) (julia-shell . [(20161125 1910) ((julia-mode (0 3))) "Major mode for an inferior Julia shell" tar ((:commit . "583a0b2ca20461ab4356929fd0f2212c22341b69") (:authors ("Dennis Ogbe" . "dogbe@purdue.edu")) (:maintainer "Dennis Ogbe" . "dogbe@purdue.edu"))]) -(julia-repl . [(20190908 1717) ((emacs (25))) "A minor mode for a Julia REPL" single ((:commit . "b8155b8a1e23e1ad740fd7bd49b5d841b1365c7d") (:keywords "languages") (:authors ("Tamas Papp" . "tkpapp@gmail.com")) (:maintainer "Tamas Papp" . "tkpapp@gmail.com") (:url . "https://github.com/tpapp/julia-repl"))]) +(julia-repl . [(20190908 1717) ((emacs (25))) "A minor mode for a Julia REPL" single ((:commit . "e3c38251cbd684188812f15aa039fb66034910b7") (:keywords "languages") (:authors ("Tamas Papp" . "tkpapp@gmail.com")) (:maintainer "Tamas Papp" . "tkpapp@gmail.com") (:url . "https://github.com/tpapp/julia-repl"))]) (julia-mode . [(20191108 1436) nil "Major mode for editing Julia source code" tar ((:commit . "addd3d461b21d83da13331b96f198e908cd9b95e") (:keywords "languages") (:url . "https://github.com/JuliaLang/julia"))]) (jtags . [(20160211 2029) nil "enhanced tags functionality for Java development" tar ((:commit . "b50daa48510f71e74ce0ec2eb85030896a79cf96") (:keywords "languages" "tools") (:authors ("Alexander Baltatzis" . "alexander@baltatzis.com") ("Johan Dykstrom" . "jody4711-sf@yahoo.se")) (:maintainer "Johan Dykstrom" . "jody4711-sf@yahoo.se") (:url . "http://jtags.sourceforge.net"))]) (jsx-mode . [(20191116 1044) nil "major mode for JSX, an altJS" single ((:commit . "e3f52e9c5ea2a61cbe288d8cd3525a335f5d3afd") (:authors ("Takeshi Arabiki (abicky)")) (:maintainer "Takeshi Arabiki (abicky)") (:url . "https://github.com/jsx/jsx-mode.el"))]) @@ -2817,7 +2817,7 @@ (git-gutter+ . [(20151204 1723) ((git-commit (0)) (dash (0))) "Manage Git hunks straight from the buffer" single ((:commit . "b7726997806d9a2da9fe84ff00ecf21d62b6f975") (:keywords "git" "vc") (:authors ("Syohei YOSHIDA" . "syohex@gmail.com")) (:maintainer "Syohei YOSHIDA" . "syohex@gmail.com") (:url . "https://github.com/nonsequitur/git-gutter-plus"))]) (git-dwim . [(20170126 1214) nil "Context-aware git commands such as branch handling" single ((:commit . "485c732130686c2f28a026e385366006435394b9") (:keywords "git" "tools" "convenience") (:authors ("rubikitch" . "rubikitch@ruby-lang.org")) (:maintainer "rubikitch" . "rubikitch@ruby-lang.org") (:url . "http://www.emacswiki.org/cgi-bin/wiki/download/git-dwim.el"))]) (git-commit-insert-issue . [(20191008 950) ((projectile (0)) (s (0)) (github-issues (0)) (gitlab (0)) (bitbucket (0))) "Get issues list when typing \"Fixes #\"" single ((:commit . "51c863d9ba21bf11f6681b54be19b4c04d50d1ba") (:keywords "git" "github" "gitlab" "bitbucket" "commit" "issues") (:authors ("Vindarel")) (:maintainer "Vindarel") (:url . "https://gitlab.com/emacs-stuff/git-commit-insert-issue/"))]) -(git-commit . [(20191116 2035) ((emacs (25 1)) (dash (20180910)) (with-editor (20181103))) "Edit Git commit messages" single ((:commit . "c8e76221a28b7ec02ed6f29c0392f7bed8521a63") (:keywords "git" "tools" "vc") (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:url . "https://github.com/magit/magit"))]) +(git-commit . [(20191116 2035) ((emacs (25 1)) (dash (20180910)) (with-editor (20181103))) "Edit Git commit messages" single ((:commit . "9711ddd07e9ad69a803ea91106dcb285c13f8943") (:keywords "git" "tools" "vc") (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:url . "https://github.com/magit/magit"))]) (git-command . [(20191028 333) ((term-run (0 1 4)) (with-editor (2 3 1))) "A Git Command-Line interface" single ((:commit . "a773d40da39dfb1c6ecf2b0758aa370ddea8f06d") (:keywords "utility" "git") (:authors ("10sr <8slashes+el [at] gmail [dot] com>")) (:maintainer "10sr <8slashes+el [at] gmail [dot] com>") (:url . "https://github.com/10sr/git-command-el"))]) (git-blamed . [(20161028 1926) nil "Minor mode for incremental blame for Git" single ((:commit . "cef196abf398e2dd11f775d1e6cd8690567408aa") (:keywords "git" "version control" "release management"))]) (git-auto-commit-mode . [(20191008 429) nil "Emacs Minor mode to automatically commit and push" single ((:commit . "2f05046731330c8643fc21c40a6840d40d70fc26") (:keywords "vc") (:authors ("Tom Willemse" . "tom@ryuslash.org")) (:maintainer "Tom Willemse" . "tom@ryuslash.org") (:url . "http://projects.ryuslash.org/git-auto-commit-mode/"))]) @@ -3334,7 +3334,7 @@ (engine-mode . [(20191105 750) ((cl-lib (0 5))) "Define and query search engines from within Emacs." single ((:commit . "96b3488a6de2f50b8ba3a101e04ebcbe9821a989") (:authors ("Harry R. Schwartz" . "hello@harryrschwartz.com")) (:maintainer "Harry R. Schwartz" . "hello@harryrschwartz.com") (:url . "https://github.com/hrs/engine-mode"))]) (encourage-mode . [(20151128 905) ((emacs (24 4))) "Encourages you in your work. :D" single ((:commit . "99edacf2d94d168d3da0609860dc7253db7c9815") (:keywords "fun") (:authors ("Patrick Mosby" . "patrick@schreiblogade.de")) (:maintainer "Patrick Mosby" . "patrick@schreiblogade.de") (:url . "https://github.com/halbtuerke/encourage-mode.el"))]) (enclose . [(20121008 1614) nil "Enclose cursor within punctuation pairs." tar ((:commit . "2747653e84af39017f503064bc66ed1812a77259"))]) -(emr . [(20191108 1103) ((s (1 3 1)) (dash (1 2 0)) (cl-lib (0 2)) (popup (0 5 0)) (emacs (24 1)) (list-utils (0 3 0)) (paredit (24 0 0)) (projectile (0 9 1)) (clang-format (0)) (iedit (0 97))) "Emacs refactoring system." tar ((:commit . "43a739d462b777a8cb347b758f3bcaac6dc775fc") (:keywords "tools" "convenience" "refactoring") (:authors ("Chris Barrett" . "chris.d.barrett@me.com")) (:maintainer "Chris Barrett" . "chris.d.barrett@me.com"))]) +(emr . [(20191122 1911) ((s (1 3 1)) (dash (1 2 0)) (cl-lib (0 2)) (popup (0 5 0)) (emacs (24 1)) (list-utils (0 3 0)) (paredit (24 0 0)) (projectile (0 9 1)) (clang-format (0 0 1)) (iedit (0 97))) "Emacs refactoring system." tar ((:commit . "8038ab88a000a835ca73af2068b1ef536bc7e33c") (:keywords "tools" "convenience" "refactoring") (:authors ("Chris Barrett" . "chris.d.barrett@me.com")) (:maintainer "Chris Barrett" . "chris.d.barrett@me.com") (:url . "https://github.com/Wilfred/emacs-refactor"))]) (empos . [(20151011 1916) nil "Locate bibtex citations from within emacs" single ((:commit . "7b99ad30e56937adb7e6349777e5a2045597d564") (:keywords "citations" "reference" "bibtex" "reftex") (:authors ("Dimitris Alikaniotis ")) (:maintainer "Dimitris Alikaniotis ") (:url . "http://github.com/dimalik/empos/"))]) (emojify-logos . [(20180814 917) ((emojify (0 4))) "Add logos to emojify" tar ((:commit . "a3e78bcbdf863092d4c9b026ac08bf7d1c7c0e8b") (:authors ("mxgoldstein" . "m_goldstein@gmx.net")) (:maintainer "mxgoldstein" . "m_goldstein@gmx.net") (:url . "https://github.com/mxgoldstein/emojify-logos"))]) (emojify . [(20191017 420) ((seq (1 11)) (ht (2 0)) (emacs (24 3))) "Display emojis in Emacs" tar ((:commit . "4c84ef9502988b52b1e296630bcee7f7c62cfc02") (:keywords "multimedia" "convenience") (:authors ("Iqbal Ansari" . "iqbalansari02@yahoo.com")) (:maintainer "Iqbal Ansari" . "iqbalansari02@yahoo.com") (:url . "https://github.com/iqbalansari/emacs-emojify"))]) @@ -3409,7 +3409,7 @@ (elisp-format . [(20160508 952) nil "Format elisp code" single ((:commit . "03cc293eb2f78ec58fc1d84279af06816a04b979") (:authors (nil . "Andy Stewart lazycat.manatee@gmail.com")) (:maintainer "Yuki Inoue inouetakahiroki _at_ gmail.com") (:url . "https://github.com/Yuki-Inoue/elisp-format"))]) (elisp-docstring-mode . [(20170304 1615) nil "Major mode for editing elisp docstrings." single ((:commit . "f512e509dd690f65133e55563ebbfd2dede5034f") (:keywords "languages") (:authors ("Matúš Goljer" . "matus.goljer@gmail.com")) (:maintainer "Matúš Goljer" . "matus.goljer@gmail.com"))]) (elisp-depend . [(20190325 1114) nil "Parse depend libraries of elisp file." single ((:commit . "6679da9a6be5a845bb4804224c8394a9bc62168f"))]) -(elisp-demos . [(20191119 1653) ((emacs (24 4))) "Elisp API Demos" tar ((:commit . "2bcf50c1ac6329515a0d1118b2beb085e0ab31c6") (:keywords "lisp" "docs") (:authors ("Xu Chunyang" . "mail@xuchunyang.me")) (:maintainer "Xu Chunyang" . "mail@xuchunyang.me") (:url . "https://github.com/xuchunyang/elisp-demos"))]) +(elisp-demos . [(20191119 1653) ((emacs (24 4))) "Elisp API Demos" tar ((:commit . "821a5b91559afa30ef3ed7da358ac40b68df914b") (:keywords "lisp" "docs") (:authors ("Xu Chunyang" . "mail@xuchunyang.me")) (:maintainer "Xu Chunyang" . "mail@xuchunyang.me") (:url . "https://github.com/xuchunyang/elisp-demos"))]) (elisp-def . [(20180806 723) ((dash (2 12 0)) (f (0 19 0)) (s (1 11 0)) (emacs (24 3))) "macro-aware go-to-definition for elisp" single ((:commit . "368b04da68783601b52e3169312183381871cf9e") (:keywords "lisp") (:authors ("Wilfred Hughes" . "me@wilfred.me.uk")) (:maintainer "Wilfred Hughes" . "me@wilfred.me.uk"))]) (elhome . [(20161025 2042) ((initsplit (20120630))) "A framework for a \"home\" Emacs configuration" tar ((:commit . "e789e806469af3e9705f72298683c21f6c3a516d") (:keywords "lisp") (:authors ("Dave Abrahams" . "dave@boostpro.com")) (:maintainer "Demyan Rogozhin" . "demyan.rogozhin@gmail.com") (:url . "http://github.com/demyanrogozhin/elhome"))]) (elgrep . [(20191107 1339) ((emacs (26 1)) (async (1 5))) "Searching files for regular expressions" single ((:commit . "d52ed6d75450009995bbf98a40033b1d7cb12392") (:keywords "tools" "matching" "files" "unix") (:authors ("Tobias Zawada" . "naehring@smtp.1und1.de")) (:maintainer "Tobias Zawada" . "naehring@smtp.1und1.de") (:url . "https://github.com/TobiasZawada/elgrep"))]) @@ -3548,7 +3548,7 @@ (dotenv-mode . [(20191027 2129) ((emacs (24 3))) "Major mode for .env files" single ((:commit . "e3701bf739bde44f6484eb7753deadaf691b73fb") (:authors ("Preetpal S. Sohal")) (:maintainer "Preetpal S. Sohal") (:url . "https://github.com/preetpalS/emacs-dotenv-mode"))]) (dot-mode . [(20180312 2300) ((emacs (24 3))) "minor mode to repeat typing or commands" single ((:commit . "6ca22b73bcdae2363ee9641b822a60685df16a3e") (:keywords "convenience") (:authors ("Robert Wyrick" . "rob@wyrick.org")) (:maintainer "Robert Wyrick" . "rob@wyrick.org") (:url . "https://github.com/wyrickre/dot-mode"))]) (doom-themes . [(20191115 2240) ((emacs (25 1)) (cl-lib (0 5))) "an opinionated pack of modern color-themes" tar ((:commit . "3c6f874a03f378c4dfed5e913ea5490402d8a233") (:keywords "dark" "light" "blue" "atom" "one" "theme" "neotree" "icons" "faces" "nova") (:authors ("Henrik Lissner ")) (:maintainer "Henrik Lissner" . "henrik@lissner.net") (:url . "https://github.com/hlissner/emacs-doom-theme"))]) -(doom-modeline . [(20191122 1033) ((emacs (25 1)) (all-the-icons (1 0 0)) (shrink-path (0 2 0)) (dash (2 11 0))) "A minimal and modern mode-line" tar ((:commit . "d6165e6f3c6f7b9b7aca0c4581ebf695ba102aa4") (:keywords "faces" "mode-line") (:authors ("Vincent Zhang" . "seagle0128@gmail.com")) (:maintainer "Vincent Zhang" . "seagle0128@gmail.com") (:url . "https://github.com/seagle0128/doom-modeline"))]) +(doom-modeline . [(20191122 1744) ((emacs (25 1)) (all-the-icons (1 0 0)) (shrink-path (0 2 0)) (dash (2 11 0))) "A minimal and modern mode-line" tar ((:commit . "188b2bda5f44774011470edc85cb4e5da27be463") (:keywords "faces" "mode-line") (:authors ("Vincent Zhang" . "seagle0128@gmail.com")) (:maintainer "Vincent Zhang" . "seagle0128@gmail.com") (:url . "https://github.com/seagle0128/doom-modeline"))]) (doom . [(20180301 2308) ((cl-lib (0 5))) "DOM implementation and manipulation library" single ((:commit . "e59040aefc92dd9b3134eb623624307fb9e4327b") (:keywords "xml" "dom") (:authors ("Alex Schroeder" . "alex@gnu.org") ("Henrik.Motakef" . "elisp@henrik-motakef.de") ("Katherine Whitlock" . "toroidal-code@gmail.com") ("Syohei YOSHIDA" . "syohex@gmail.com")) (:maintainer "Alex Schroeder") (:url . "http://www.github.com/kensanata/doom.el/"))]) (doneburn-theme . [(20181110 1857) nil "A light theme based on Bozhidar Batsov's Zenburn" single ((:commit . "6421d9e28d57cb73212c61ab7304abfe6f950ec9") (:keywords "faces" "themes") (:authors ("Manuel Uberti" . "manuel.uberti@inventati.org")) (:maintainer "Manuel Uberti" . "manuel.uberti@inventati.org") (:url . "http://github.com/manuel-uberti/doneburn-emacs"))]) (dollaro . [(20151123 1302) ((s (1 6 0))) "simple text templates" single ((:commit . "500127f0172ac7a1eec627e026b59136580a74ac") (:keywords "tools" "convenience") (:authors ("Alessandro Piras" . "laynor@gmail.com")) (:maintainer "Alessandro Piras" . "laynor@gmail.com"))]) @@ -3995,7 +3995,7 @@ (cframe . [(20190616 1946) ((emacs (25)) (buffer-manage (0 9)) (dash (2 13 0))) "customize a frame and fast switch size and positions" single ((:commit . "38026cbd004231c5525bea31723ced39311bb408") (:keywords "frame" "customize") (:authors ("Paul Landes")) (:maintainer "Paul Landes") (:url . "https://github.com/plandes/cframe"))]) (cfml-mode . [(20190617 1130) ((emacs (25))) "Emacs mode for editing CFML files" single ((:commit . "b06d7cee2af0ed5d55a94f0db80fc1f429a1829a") (:authors ("Andrew Myers" . "am2605@gmail.com")) (:maintainer "Andrew Myers" . "am2605@gmail.com") (:url . "https://github.com/am2605/cfml-mode"))]) (cff . [(20160118 2018) ((cl-lib (0 5)) (emacs (24))) "Search of the C/C++ file header by the source and vice versa" single ((:commit . "b6ab2a28e64ef06f281ec74cfe3114e450644dfa") (:keywords "find-file") (:authors ("Alexey Veretennikov" . "alexey.veretennikov@gmail.com")) (:maintainer "Alexey Veretennikov" . "alexey.veretennikov@gmail.com") (:url . "https://github.com/fourier/cff"))]) -(cfengine-code-style . [(20171115 2108) nil "C code style for CFEngine project." single ((:commit . "90b67ded3eee9f92427d3d5ed16d485684f98743") (:authors ("Mikhail Gusarov" . "mikhail.gusarov@cfengine.com")) (:maintainer "Mikhail Gusarov" . "mikhail.gusarov@cfengine.com") (:url . "https://github.com/cfengine/core"))]) +(cfengine-code-style . [(20171115 2108) nil "C code style for CFEngine project." single ((:commit . "ba93fa9fb1c629f1a63b9b29d41e07b5802b6a9d") (:authors ("Mikhail Gusarov" . "mikhail.gusarov@cfengine.com")) (:maintainer "Mikhail Gusarov" . "mikhail.gusarov@cfengine.com") (:url . "https://github.com/cfengine/core"))]) (ceylon-mode . [(20180606 1324) ((emacs (25))) "Major mode for editing Ceylon source code" single ((:commit . "948515672bc596dc118e8e3ede3ede5ec6a3c95a") (:keywords "languages" "ceylon") (:authors ("Lucas Werkmeister" . "mail@lucaswerkmeister.de")) (:maintainer "Lucas Werkmeister" . "mail@lucaswerkmeister.de") (:url . "https://github.com/lucaswerkmeister/ceylon-mode"))]) (cerbere . [(20181113 1641) ((pkg-info (0 5))) "Unit testing in Emacs for several programming languages" tar ((:commit . "c667c165d9c1657f13d2d46f09ba21b61f9402cc") (:keywords "python" "go" "php" "phpunit" "elisp" "ert" "tests" "tdd") (:authors ("Nicolas Lamirault" . "nicolas.lamirault@gmail.com")) (:maintainer "Nicolas Lamirault" . "nicolas.lamirault@gmail.com") (:url . "https://github.com/nlamirault/cerbere"))]) (centimacro . [(20140306 1427) nil "Assign multiple macros as global key bindings" single ((:commit . "1b97a9b558ed9c49d5da1bfbf29b2506575c2742") (:keywords "macros") (:authors ("Oleh Krehel" . "ohwoeowho@gmail.com")) (:maintainer "Oleh Krehel" . "ohwoeowho@gmail.com") (:url . "https://github.com/abo-abo/centimacro"))]) diff --git a/elpa/berrys-theme-20191106.1423/berrys-theme-autoloads.el b/elpa/berrys-theme-20191106.1423/berrys-theme-autoloads.el new file mode 100644 index 00000000..9bcc80a1 --- /dev/null +++ b/elpa/berrys-theme-20191106.1423/berrys-theme-autoloads.el @@ -0,0 +1,24 @@ +;;; berrys-theme-autoloads.el --- automatically extracted autoloads +;; +;;; Code: + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + + +;;;### (autoloads nil "berrys-theme" "berrys-theme.el" (0 0 0 0)) +;;; Generated autoloads from berrys-theme.el + +(when (and (boundp 'custom-theme-load-path) load-file-name) (add-to-list 'custom-theme-load-path (file-name-as-directory (file-name-directory load-file-name)))) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "berrys-theme" '("berrys"))) + +;;;*** + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; coding: utf-8 +;; End: +;;; berrys-theme-autoloads.el ends here diff --git a/elpa/berrys-theme-20191106.1423/berrys-theme-pkg.el b/elpa/berrys-theme-20191106.1423/berrys-theme-pkg.el new file mode 100644 index 00000000..a980eba3 --- /dev/null +++ b/elpa/berrys-theme-20191106.1423/berrys-theme-pkg.el @@ -0,0 +1,2 @@ +;;; -*- no-byte-compile: t -*- +(define-package "berrys-theme" "20191106.1423" "A light, clean and elegant theme" '((emacs "24.1")) :commit "1fcc22758abf33b42826750ed0774ee0f6601d2b" :authors '(("Slava Buzin" . "v8v.buzin@gmail.com")) :maintainer '("Slava Buzin" . "v8v.buzin@gmail.com") :url "https://github.com/vbuzin/berrys-theme") diff --git a/elpa/berrys-theme-20191106.1423/berrys-theme.el b/elpa/berrys-theme-20191106.1423/berrys-theme.el new file mode 100644 index 00000000..348ce2ed --- /dev/null +++ b/elpa/berrys-theme-20191106.1423/berrys-theme.el @@ -0,0 +1,399 @@ +;;; berrys-theme.el --- A light, clean and elegant theme -*- lexical-binding: t; -*- + +;; Copyright © 2019-present Slava Buzin + +;; Title: Berrys Theme +;; Project: berrys-theme +;; Version: 0.1.0 +;; Package-Version: 20191106.1423 +;; URL: https://github.com/vbuzin/berrys-theme +;; Author: Slava Buzin +;; Package-Requires: ((emacs "24.1")) +;; License: MIT + +;;; Commentary: + +;; Berrys is a 9 colorspace theme build to run in GUI mode +;; with support for some third-party syntax- and UI packages. + +;;; Code: + +(deftheme berrys "A light, clean and elegant theme") + +;;;; Colors +(let* ((class '((class color) (min-colors 89))) + (berrys00 nil) + + (berrys01 "#FAFAFA") + (berrys02 "#2C302E") + (berrys03 "#646881") + (berrys04 "#E2E3E8") + + (berrys05 "#1098F7") + (berrys06 "#B2EAFF") + + (berrys07 nil) + + (berrys08 "#00AC00") + + (berrys09 "#D89800") + + (berrys10 "#B80C09") + + (berrys-cursor berrys05) + (berrys-comment berrys03) + (berrys-string berrys03) + + (berrys-warning berrys09) + (berrys-error berrys10)) + + (custom-theme-set-faces + 'berrys + + ;;; Core + ;; ============================================================================= + ;; => Base + `(bold ((,class (:weight bold)))) + `(bold-italic ((,class (:weight bold :slant italic)))) + `(default ((,class (:foreground ,berrys02 :background ,berrys01)))) + `(error ((,class (:foreground ,berrys-error)))) + `(fixed-pitch-serif ((,class (:family unspecified)))) + `(font-lock-builtin-face ((,class (:foreground ,berrys02 :weight bold)))) + `(font-lock-comment-face ((,class (:foreground ,berrys-comment :slant italic)))) + `(font-lock-comment-delimiter-face ((,class (:foreground ,berrys-comment :slant italic)))) + `(font-lock-constant-face ((,class (:foreground ,berrys02 :weight bold)))) + `(font-lock-doc-face ((,class (:inherit (font-lock-comment-face))))) + `(font-lock-function-name-face ((,class (:foreground ,berrys02 :weight bold)))) + `(font-lock-keyword-face ((,class (:foreground ,berrys02 :weight bold)))) + `(font-lock-string-face ((,class (:foreground ,berrys-string)))) + `(font-lock-type-face ((,class (:foreground ,berrys02 :slant italic)))) + `(font-lock-variable-name-face ((,class (:foreground ,berrys02)))) + `(font-lock-warning-face ((,class (:inherit warning)))) + `(shadow ((,class (:foreground ,berrys03)))) + `(warning ((,class (:foreground ,berrys-warning)))) + + ;; => Core UI + `(cursor ((,class (:background ,berrys-cursor :inverse-video t)))) + `(custom-button ((,class (:background ,berrys05 :foreground ,berrys01)))) + `(custom-variable-tag ((,class (:foreground ,berrys02 :weight bold)))) + `(custom-visibility ((,class (:inherit link)))) + `(diff-added ((,class (:foreground ,berrys08)))) + `(diff-context ((,class (:foreground ,berrys-string)))) + `(diff-file-header ((,class (:inherit diff-header)))) + `(diff-header ((,class (:foreground ,berrys03)))) + `(diff-hunk-header ((,class (:inherit diff-header)))) + `(diff-indicator-added ((,class (:foreground ,berrys08)))) + `(diff-refine-added ((,class (:foreground ,berrys08)))) + `(diff-refine-changed ((,class (:foreground ,berrys09)))) + `(diff-refine-removed ((,class (:foreground ,berrys10)))) + `(diff-removed ((,class (:foreground ,berrys10)))) + `(dired-directory ((,class :foreground ,berrys02 :weight bold))) + `(header-line ((,class :foreground ,berrys02 :weight bold))) + `(highlight ((,class (:background ,berrys04)))) + `(hl-line ((,class (:background ,berrys04)))) + `(info-node ((,class (:foreground ,berrys05 :weight bold)))) + `(info-menu-header ((,class (:foreground ,berrys02 :weight bold)))) + `(info-menu-star ((,class (:foreground ,berrys05)))) + `(info-title-4 ((,class (:foreground ,berrys02 :weight bold)))) + `(isearch ((,class (:foreground ,berrys05 :weight bold)))) + `(isearch-fail ((,class (:foreground ,berrys01 :background ,berrys-error)))) + `(lazy-highlight ((,class (:inherit isearch)))) + `(link ((,class (:underline t)))) + `(link-visited ((,class (:underline t)))) + `(match ((,class (:inherit isearch)))) + + `(message-cited-text ((,class (:inherit font-lock-comment-face)))) + `(message-header-cc ((,class (:foreground ,berrys-string)))) + `(message-header-name ((,class (:foreground ,berrys-string)))) + `(message-header-newsgroups ((,class (:foreground ,berrys-string :slant italic :weight bold)))) + `(message-header-other ((,class (:foreground ,berrys-string)))) + `(message-header-subject ((,class (:foreground ,berrys-string)))) + `(message-header-to ((,class (:foreground ,berrys-string)))) + `(message-header-xheader ((,class (:foreground ,berrys-string)))) + `(message-mml ((,class (:foreground ,berrys-string)))) + `(message-separator ((,class (:inherit font-lock-comment-face)))) + + `(minibuffer-prompt ((,class (:foreground ,berrys02 :weight bold)))) + `(mode-line ((,class (:foreground ,berrys02 :background ,berrys04)))) + `(mode-line-buffer-id ((,class (:weight bold)))) + `(mode-line-highlight ((,class (:inherit highlight)))) + `(mode-line-inactive ((,class (:foreground ,berrys02 :background ,berrys01 :box (:color ,berrys04))))) + `(outline-1 ((,class (:foreground ,berrys02 :weight bold)))) + `(outline-2 ((,class (:inherit outline-1)))) + `(outline-3 ((,class (:inherit outline-1)))) + `(outline-4 ((,class (:inherit outline-1)))) + `(outline-5 ((,class (:inherit outline-1)))) + `(outline-6 ((,class (:inherit outline-1)))) + `(outline-7 ((,class (:inherit outline-1)))) + `(outline-8 ((,class (:inherit outline-1)))) + `(region ((,class (:background ,berrys06)))) + `(secondary-selection ((,class (:background ,berrys04 :foreground ,berrys02)))) + `(show-paren-match ((,class (:weight bold)))) + `(show-paren-mismatch ((,class (:foreground ,berrys-error :weight bold)))) + `(success ((,class (:foreground ,berrys08)))) + `(whitespace-big-indent ((,class (:foreground ,berrys01 :background ,berrys10)))) + `(whitespace-line ((,class (:background ,berrys01)))) + `(whitespace-trailing ((,class (:foreground ,berrys01 :background ,berrys10)))) + + ;;; Packages + ;; ============================================================================= + ;; => Ace jump + `(ace-jump-face-foreground ((,class (:foreground ,berrys05 :weight bold)))) + + ;; => Anzu + `(anzu-match-1 ((,class (:foreground ,berrys05 :weight bold :box (:color ,berrys05))))) + `(anzu-match-2 ((,class (:foreground ,berrys01 :background ,berrys05 :weight bold :box (:color ,berrys05))))) + `(anzu-match-3 ((,class (:foreground ,berrys01 :background ,berrys03 :weight bold :box (:color ,berrys03))))) + `(anzu-mode-line ((,class (:foreground ,berrys02 :weight bold)))) + `(anzu-mode-line-no-match ((,class (:foreground ,berrys10 :weight bold)))) + `(anzu-replace-to ((,class (:foreground ,berrys-string :weight bold)))) + + ;; => Company + `(company-echo-common ((,class (:foreground ,berrys01 :background ,berrys10)))) + `(company-scrollbar-bg ((,class (:foreground ,berrys04 :background ,berrys04)))) + `(company-scrollbar-fg ((,class (:foreground ,berrys02 :background ,berrys02)))) + `(company-template-field ((,class (:inherit region)))) + `(company-tooltip ((,class (:foreground ,berrys02 :background ,berrys04)))) + `(company-tooltip-annotation ((,class (:foreground ,berrys-string)))) + `(company-tooltip-common ((,class (:inherit company-tooltip)))) + `(company-tooltip-common-selection ((,class (:inherit company-tooltip-selection)))) + `(company-tooltip-mouse ((,class (:inherit highlight)))) + `(company-tooltip-search ((,class (:inherit isearch)))) + `(company-tooltip-search-selection ((,class (:inherit company-tooltip-search)))) + `(company-tooltip-selection ((,class (:background ,berrys06)))) + + ;; => bm + `(bm-face ((,class (:foreground ,berrys05 :background ,berrys01)))) + `(bm-fringe-face ((,class (:inherit bm-face)))) + `(bm-persistent-face ((,class (:foreground ,berrys01 :background ,berrys05)))) + `(bm-fringe-persistent-face ((,class (:inherit bm-persistent-face)))) + + ;; => Flx + `(flx-highlight-face ((,class (:foreground ,berrys05 :weight bold)))) + + ;; => Flycheck + `(flycheck-error ((,class (:underline (:style wave :color ,berrys-error))))) + `(flycheck-fringe-error ((,class (:foreground ,berrys-error :weight bold)))) + `(flycheck-fringe-info ((,class (:foreground ,berrys02 :weight bold)))) + `(flycheck-fringe-warning ((,class (:foreground ,berrys-warning :weight bold)))) + `(flycheck-info ((,class (:underline (:style wave :color ,berrys05))))) + `(flycheck-warning ((,class (:underline (:style wave :color ,berrys-warning))))) + + ;; => Gnus + `(gnus-header-content ((,class (:foreground ,berrys-string :italic t)))) + `(gnus-header-from ((,class (:foreground ,berrys-string)))) + `(gnus-header-name ((,class (:foreground ,berrys-string :weight bold)))) + `(gnus-header-subject ((,class (:foreground ,berrys-string)))) + + ;; => Haskell-mode + `(haskell-error-face ((,class (:underline (:style wave :color ,berrys-error))))) + `(haskell-hole-face ((,class (:underline (:style wave :color ,berrys05))))) + `(haskell-warning-face ((,class (:underline (:style wave :color ,berrys-warning))))) + + ;; => Helm + `(helm-M-x-key ((,class (:foreground ,berrys03 :underline t)))) + `(helm-buffer-directory ((,class (:inherit helm-buffer-file)))) + `(helm-buffer-not-saved ((,class (:foreground ,berrys03 :slant italic)))) + `(helm-buffer-process ((,class (:foreground ,berrys03)))) + `(helm-candidate-number ((,class (:weight bold)))) + `(helm-candidate-number-suspended ((,class (:foreground ,berrys03 :weight bold)))) + `(helm-ff-directory ((,class (:foreground ,berrys02 :weight bold)))) + `(helm-ff-dirs ((,class (:inherit helm-ff-file)))) + `(helm-ff-dotted-directory ((,class (:inherit helm-ff-directory)))) + `(helm-ff-dotted-symlink-directory ((,class (:inherit helm-ff-dotted-directory)))) + `(helm-ff-file ((,class (:foreground ,berrys02)))) + `(helm-ff-executable ((,class (:foreground ,berrys08)))) + `(helm-ff-invalid-symlink ((,class (:foreground ,berrys01 :background ,berrys10)))) + `(helm-ff-pipe ((,class (:foreground ,berrys09 :background ,berrys02)))) + `(helm-ff-prefix ((,class (:foreground ,berrys02 :background ,berrys06)))) + `(helm-ff-socket ((,class (:foreground ,berrys10 :box (:color ,berrys10))))) + `(helm-grep-file ((,class (:foreground ,berrys02 :weight bold)))) + `(helm-grep-finish ((,class (:foreground ,berrys08 :weight bold)))) + `(helm-grep-lineno ((,class (:foreground ,berrys03)))) + `(helm-grep-match ((,class (:inherit isearch)))) + `(helm-header ((,class (:inherit helm-source-header :background ,berrys01)))) + `(helm-header-line-left-margin ((,class (:foreground ,berrys01 :background ,berrys09)))) + `(helm-helper ((,class (:foreground ,berrys02)))) + `(helm-history-deleted ((,class (:foreground ,berrys01 :background ,berrys10)))) + `(helm-history-remote ((,class (:foreground ,berrys10)))) + `(helm-lisp-completion-info ((,class (:foreground ,berrys04 :weight bold)))) + `(helm-lisp-show-completion ((,class (:inherit isearch)))) + `(helm-locate-finish ((,class (:foreground ,berrys08)))) + `(helm-match ((,class (:foreground ,berrys05 :weight bold)))) + `(helm-match-item ((,class (:inherit isearch)))) + `(helm-moccur-buffer ((,class (:foreground ,berrys02)))) + `(helm-mode-prefix ((,class (:foreground ,berrys01 :background ,berrys06)))) + `(helm-resume-need-update ((,class (:foreground ,berrys01 :background ,berrys10)))) + `(helm-selection ((,class (:inherit highlight)))) + `(helm-selection-line ((,class (:inherit highlight)))) + `(helm-source-header ((,class (:foreground ,berrys02 :weight bold :height 1.3)))) + `(helm-separator ((,class (:foreground ,berrys02)))) + `(helm-visible-mark ((,class (:background ,berrys06)))) + `(helm-yas-key ((,class (:inherit helm-M-x-key)))) + + ;; => Ido + `(ido-indicator ((,class (:foreground ,berrys01 :background ,berrys10)))) + `(ido-only-match ((,class (:foreground ,berrys05 :weight bold)))) + `(ido-subdir ((,class (:foreground ,berrys02 :weight bold)))) + `(ido-virtual ((,class (:foreground ,berrys-string :weight bold)))) + + ;; => Indent guide + `(indent-guide-face ((,class (:foreground ,berrys-comment)))) + + ;; => Ivy + `(ivy-confirm-face ((,class (:foreground ,berrys08 :weight bold)))) + `(ivy-current-match ((,class (:inherit hl-line)))) + `(ivy-cursor ((,class (:foreground ,berrys01 :background ,berrys02)))) + `(ivy-match-required-face ((,class (:foreground ,berrys10 :weight bold)))) + `(ivy-remote ((,class (:foreground ,berrys02 :underline t)))) + `(ivy-minibuffer-match-face-2 ((,class (:foreground ,berrys05 :weight bold)))) + `(ivy-minibuffer-match-face-3 ((,class (:inherit ivy-minibuffer-match-face-2 :underline t)))) + `(ivy-minibuffer-match-face-4 ((,class (:inherit ivy-minibuffer-match-face-2 :box (:color ,berrys05))))) + + ;; => Markdown + `(markdown-code-face ((,class (:family unspecified)))) + `(markdown-header-face ((,class (:foreground ,berrys02 :weight bold)))) + `(markdown-header-face-1 ((,class (:inherit markdown-header-face :height 1.4)))) + `(markdown-header-face-2 ((,class (:inherit markdown-header-face :height 1.3)))) + `(markdown-header-face-3 ((,class (:inherit markdown-header-face :height 1.2)))) + `(markdown-header-face-4 ((,class (:inherit markdown-header-face :height 1.1)))) + `(markdown-inline-code-face ((,class (:inherit markdown-code-face)))) + `(markdown-italic-face ((,class (:inherit italic)))) + + ;; => Magit + `(magit-bisect-bad ((,class (:foreground ,berrys-error)))) + `(magit-bisect-good ((,class (:foreground ,berrys08)))) + `(magit-bisect-skip ((,class (:foreground ,berrys09)))) + `(magit-blame-highlight ((,class (:foreground ,berrys03 :background ,berrys04)))) + `(magit-branch-local ((,class (:foreground ,berrys05)))) + `(magit-branch-remote ((,class (:foreground ,berrys08)))) + `(magit-reflog-checkout ((,class (:foreground ,berrys05)))) + `(magit-diff-base ((,class (:foreground ,berrys09)))) + `(magit-diff-base-highlight ((,class (:inherit magit-diff-base)))) + `(magit-diff-context ((,class (:foreground ,berrys-string)))) + `(magit-diff-context-highlight ((,class (:inherit magit-diff-context)))) + `(magit-diff-added ((,class (:foreground ,berrys08)))) + `(magit-diff-added-highlight ((,class (:inherit magit-diff-added)))) + `(magit-diff-file-heading ((,class (:foreground ,berrys-string)))) + `(magit-diff-file-heading-selection ((,class (:inherit magit-diff-file-heading)))) + `(magit-diff-hunk-heading ((,class (:foreground ,berrys03)))) + `(magit-diff-hunk-heading-highlight ((,class (:inherit magit-diff-hunk-heading)))) + `(magit-diff-hunk-heading-selection ((,class (:inherit magit-diff-hunk-heading)))) + `(magit-diff-lines-boundary((,class (:inherit unspecified)))) + `(magit-diff-lines-heading ((,class (:inherit unspecified)))) + `(magit-diff-our-highlight ((,class (:inherit magit-diff-removed)))) + `(magit-diff-removed ((,class (:foreground ,berrys10)))) + `(magit-diff-removed-highlight ((,class (:inherit magit-diff-removed)))) + `(magit-diffstat-added ((,class (:foreground ,berrys08)))) + `(magit-diffstat-removed ((,class (:foreground ,berrys10)))) + `(magit-diff-their-highlight ((,class (:inherit magit-diff-added)))) + `(magit-diff-whitespace-warning ((,class (:foreground ,berrys01 :background ,berrys10)))) + `(magit-log-author ((,class (:foreground ,berrys02)))) + `(magit-log-date ((,class (:foreground ,berrys-comment)))) + `(magit-log-graph ((,class (:foreground ,berrys-comment)))) + `(magit-hash ((,class (:foreground ,berrys-comment)))) + `(magit-header-line ((,class (:foreground ,berrys-string)))) + `(magit-header-line-log-select ((,class (:foreground ,berrys02)))) + `(magit-process-ok ((,class (:foreground ,berrys08)))) + `(magit-reflog-cherry-pick ((,class (:foreground ,berrys08)))) + `(magit-reflog-commit ((,class (:foreground ,berrys08)))) + `(magit-reflog-merge ((,class (:foreground ,berrys08)))) + `(magit-reflog-reset ((,class (:foreground ,berrys10)))) + `(magit-refname ((,class (:foreground ,berrys-comment)))) + `(magit-section-heading ((,class (:foreground ,berrys02)))) + `(magit-section-heading-selection ((,class (:inherit magit-section-heading)))) + `(magit-section-highlight ((,class (:inherit unspecified)))) + `(magit-section-secondary-heading ((,class (:foreground ,berrys02)))) + `(magit-signature-bad ((,class (:foreground ,berrys-error)))) + `(magit-signature-error ((,class (:foreground ,berrys-error)))) + `(magit-signature-expired ((,class (:foreground ,berrys-warning)))) + `(magit-signature-expired-key ((,class (:inherit magit-signature-expired)))) + `(magit-signature-good ((,class (:foreground ,berrys08)))) + `(magit-signature-revoked ((,class (:foreground ,berrys10)))) + `(magit-signature-untrusted ((,class (:foreground ,berrys10)))) + `(magit-tag ((,class (:foreground ,berrys05)))) + + ;; => Mu4e + `(mu4e-attach-number-face ((,class (:foreground ,berrys05)))) + `(mu4e-contact-face ((,class (:foreground ,berrys-string :slant italic)))) + `(mu4e-context-face ((,class (:foreground ,berrys-string)))) + `(mu4e-flagged-face ((,class (:foreground ,berrys09)))) + `(mu4e-header-face ((,class (:foreground ,berrys02)))) + `(mu4e-header-highlight-face ((,class (:inherit highlight)))) + `(mu4e-header-key-face ((,class (:foreground ,berrys-string :weight bold)))) + `(mu4e-header-marks-face ((,class (:foreground ,berrys05 :weight bold)))) + `(mu4e-header-value-face ((,class (:foreground ,berrys-string :slant italic)))) + `(mu4e-highlight-face ((,class (:foreground ,berrys05)))) + `(mu4e-special-header-value-face ((,class (:foreground ,berrys-string :slant italic)))) + `(mu4e-region-code ((,class (:box (:color ,berrys05))))) + `(mu4e-replied-face ((,class :slant italic))) + `(mu4e-url-number-face ((,class (:foreground ,berrys05)))) + + ;; => Org mode + `(org-agenda-date ((,class (:foreground ,berrys02)))) + `(org-agenda-diary ((,class (:foreground ,berrys-string :slant italic)))) + `(org-agenda-dimmed-todo-face ((,class (:foreground ,berrys-comment :slant italic)))) + `(org-agenda-done ((,class (:foreground ,berrys-string :slant italic :strike-through t)))) + `(org-agenda-restriction-lock ((,class (:background ,berrys04)))) + `(org-agenda-structure ((,class (:foreground ,berrys05 :weight bold :height 1.3)))) + `(org-block ((,class (:inherit berrys02)))) + `(org-clock-overlay ((,class (:inherit secondary-selection)))) + `(org-column ((,class (:foreground ,berrys-string :slant normal)))) + `(org-column-title ((,class (:foreground ,berrys02 :weight bold)))) + `(org-date ((,class (:foreground ,berrys02 :slant italic)))) + `(org-date-selected ((,class (:foreground ,berrys05 :weight bold)))) + `(org-document-info ((,class (:foreground ,berrys03)))) + `(org-document-title ((,class (:foreground ,berrys03 :weight bold)))) + `(org-done ((,class(:inherit org-level-1 :foreground ,berrys08)))) + `(org-ellipsis ((,class (:inherit unspecified)))) + `(org-footnote ((,class (:foreground ,berrys02 :underline t)))) + `(org-formula ((,class (:foreground ,berrys-string)))) + `(org-headline-done ((,class (:inherit org-level-1 :strike-through t)))) + `(org-latex-and-related ((,class (:foreground ,berrys-string)))) + `(org-level-1 ((,class (:foreground ,berrys02 :weight bold)))) + `(org-level-2 ((,class (:inherit org-level-1)))) + `(org-level-3 ((,class (:inherit org-level-1)))) + `(org-level-4 ((,class (:inherit org-level-1)))) + `(org-level-5 ((,class (:inherit org-level-1)))) + `(org-level-6 ((,class (:inherit org-level-1)))) + `(org-level-7 ((,class (:inherit org-level-1)))) + `(org-level-8 ((,class (:inherit org-level-1)))) + `(org-link ((,class (:inherit unspecified :underline t)))) + `(org-mode-line-clock ((,class (:inherit mode-line)))) + `(org-mode-line-clock-overrun ((,class (:foreground ,berrys09)))) + `(org-priority ((,class(:inherit org-level-1 :foreground ,berrys05)))) + `(org-scheduled ((,class (:foreground ,berrys02 :slant italic)))) + `(org-scheduled-previously ((,class (:foreground ,berrys10 :slant italic)))) + `(org-scheduled-today ((,class (:inherit org-scheduled)))) + `(org-sexp-date ((,class (:foreground ,berrys-string :slant italic)))) + `(org-special-keyword ((,class (:foreground ,berrys-string)))) + `(org-table ((,class (:foreground ,berrys02)))) + `(org-tag ((,class(:inherit org-level-1 :foreground ,berrys05)))) + `(org-time-grid ((,class (:foreground ,berrys-string :slant italic)))) + `(org-todo ((,class (:inherit org-level-1 :foreground ,berrys05)))) + `(org-upcoming-deadline ((,class (:foreground ,berrys09 :slant italic)))) + `(org-warning ((,class (:foreground ,berrys09 :slant italic)))) + `(org-verbatim ((,class (:inherit default)))) + + ;; Org Pomodoro + `(org-pomodoro-mode-line ((,class (:foreground ,berrys05 :weight bold)))) + `(org-pomodoro-mode-line-break ((,class (:foreground ,berrys08 :weight bold)))) + `(org-pomodoro-mode-line-overtime ((,class (:foreground ,berrys-error :weight bold)))) + + ;; => Which key + `(which-key-key-face ((,class (:foreground ,berrys05 :weight bold)))))) + +;;;###autoload +(when (and (boundp 'custom-theme-load-path) load-file-name) + (add-to-list 'custom-theme-load-path + (file-name-as-directory (file-name-directory load-file-name)))) + +(provide-theme 'berrys) +(provide 'berrys-theme) + +;; Local Variables: +;; no-byte-compile: t +;; indent-tabs-mode: nil +;; End: + +;;; berrys-theme.el ends here diff --git a/elpa/magit-20191122.2040/AUTHORS.md b/elpa/magit-20191122.2040/AUTHORS.md new file mode 100644 index 00000000..52a4e4da --- /dev/null +++ b/elpa/magit-20191122.2040/AUTHORS.md @@ -0,0 +1,341 @@ +Authors +======= + +The following people have contributed to Magit, including the +libraries `git-commit.el`, `magit-popup.el`, and `with-editor.el` +which are distributed as separate Elpa packages. + +For statistics see https://magit.vc/stats/authors.html. + +Names below are sorted alphabetically. + +Author +------ + +- Marius Vollmer + +Maintainer +---------- + +- Jonas Bernoulli + +Developers +---------- + +- Kyle Meyer +- Noam Postavsky + +Retired Maintainers and Developers +---------------------------------- + +- Nicolas Dudebout +- Peter J. Weisberg +- Pieter Praet +- Phil Jackson +- Rémi Vanicat +- Yann Hodique + +Contributors +------------ + +- Aaron Culich +- Aaron Madlon-Kay +- Abdo Roig-Maranges +- Adam Benanti <0entropy@protonmail.com> +- Adam Porter +- Adam Spiers +- Adeodato Simó +- Ævar Arnfjörð Bjarmason +- Alan Falloon +- Alban Gruin +- Aleksey Uimanov +- Alexander Gramiak +- Alexander Miller +- Alex Branham +- Alex Dunn +- Alexey Voinov +- Alex Kost +- Alex Ott +- Allen +- Allen Li +- Andreas Fuchs +- Andreas Liljeqvist +- Andreas Rottmann +- Andrei Chițu +- Andrew Eggenberger +- Andrew Kirkpatrick +- Andrew Schwartzmeyer +- Andrey Smirnov +- Andriy Kmit' +- Andy Sawyer +- Aria Edmonds +- Arialdo Martini +- Barak A. Pearlmutter +- Bar Magal +- Bart Bakker +- Basil L. Contovounesios +- Bastian Beischer +- Benjamin Motz +- Ben North +- Ben Walton +- Bob Uhl +- Bradley Wright +- Brandon W Maister +- Brian Warner +- Bryan Shell +- Buster Copley +- Carl Lieberman +- Chillar Anand +- Chris Bernard +- Chris Done +- Chris LaRose +- Chris Moore +- Chris Ring +- Chris Shoemaker +- Christian Dietrich +- Christian Kluge +- Christophe Junke +- Christopher Monsanto +- Cornelius Mika +- Craig Andera +- Dale Hagglund +- Damien Cassou +- Dan Erikson +- Daniel Brockman +- Daniel Farina +- Daniel Gröber +- Daniel Hackney +- Daniel Kraus +- Daniel Mai +- Daniel Martín +- Dan LaManna +- Danny Zhu +- Dato Simó +- David Abrahams +- David Ellison +- David Ellison +- David Hull +- David L. Rager +- David Wallin +- Dean Kariniemi <8913263+d3k4r@users.noreply.github.com> +- Dennis Paskorz +- Divye Kapoor +- Dominique Quatravaux +- Dominique Quatravaux +- Duianto Vebotci +- Eli Barzilay +- Eric Davis +- Eric Prud'hommeaux +- Eric Schulte +- Erik Anderson +- Evan Torrie +- Evgkeni Sampelnikof +- Eyal Lotem +- Fabian Wiget +- Felix Geller +- Felix Yan +- Feng Li +- Florian Ragwitz +- Fritz Grabo +- Fritz Stelzer +- Geoff Shannon +- George Kadianakis +- Graham Clark +- Graham Dobbins +- Greg A. Woods +- Greg Lucas +- Greg Sexton +- Guillaume Martres +- Hannu Koivisto +- Hans-Peter Deifel +- Hussein Ait-Lahcen +- Ian Eure +- Ingo Lohmar +- Ioan-Adrian Ratiu +- Ivan Brennan +- Jan Tatarik +- Jasper St. Pierre +- Jeff Bellegarde +- Jeff Dairiki +- Jeremy Meng +- Jesse Alama +- Jim Blandy +- Joakim Jalap +- Johannes Altmanninger +- Johann Klähn +- John Mastro +- John Morris +- John Wiegley +- Jonas Bernoulli +- Jonathan Arnett +- Jonathan Leech-Pepin +- Jonathan Roes +- Jon Vanderwijk +- Jordan Galby +- Jordan Greenberg +- Josh Elsasser +- Josiah Schwab +- Julien Danjou +- Justin Burkett +- Justin Caratzas +- Justin Guenther +- Justin Thomas +- Kan-Ru Chen +- Kenny Ballou +- Keshav Kini +- Kevin Brubeck Unhammer +- Kevin J. Foley +- Kévin Le Gouguec +- Kimberly Wolk +- Knut Olav Bøhmer +- Kyle Meyer +- Laurent Laffont +- Laverne Schrock +- Leandro Facchinetti +- Lele Gaifax +- Leo Liu +- Leonardo Etcheverry +- Lingchao Xin +- Li-Yun Chang +- Lluís Vilanova +- Loic Dachary +- Louis Roché +- Luís Oliveira +- Luke Amdor +- Mak Kolybabi +- Manuel Vázquez Acosta +- Marcel Wolf +- Marc Herbert +- Marcin Bachry +- Marco Craveiro +- Marco Wahl +- Marc Sherry +- Marian Schubert +- Mario Rodas +- Marius Vollmer +- Mark Hepburn +- Mark Karpov +- Mark Oteiza +- Matthew Fluet +- Matthieu Hauglustaine +- Matus Goljer +- Michael Fogleman +- Michael Griffiths +- Michael Heerdegen +- Michal Sojka +- Miciah Masters +- Miles Bader +- Miloš Mošić +- Mitchel Humpherys +- Moritz Bunkus +- Naoya Yamashita +- Natalie Weizenbaum +- Nguyễn Tuấn Anh +- Nic Ferier +- Nick Alcock +- Nick Alexander +- Nick Dimiduk +- Nicklas Lindgren +- Nicolas Dudebout +- Nicolas Petton +- Nicolas Richard +- Nikolay Martynov +- Noam Postavsky +- N. Troy de Freitas +- Ole Arndt +- Oleh Krehel +- Orivej Desh +- Óscar Fuentes +- Paul Stadig +- Pavel Holejsovsky +- Pekka Pessi +- Peter Eisentraut +- Peter Jaros +- Peter J. Weisberg +- Peter Vasil +- Philippe Vaucher +- Philipp Haselwarter +- Philipp Stephani +- Philip Weaver +- Phil Jackson +- Phil Sainty +- Pierre Neidhardt +- Pieter Praet +- Prathamesh Sonpatki +- rabio +- Radon Rosborough +- Rafael Laboissiere +- Raimon Grau +- Ramkumar Ramachandra +- Remco van 't Veer +- Rémi Vanicat +- René Stadler +- Richard Kim +- Robert Boone +- Robin Green +- Roger Crew +- Romain Francoise +- Ron Parker +- Roy Crihfield +- Rüdiger Sonderfeld +- Russell Black +- Ryan C. Thompson +- Samuel Bronson +- Samuel W. Flint +- Sanjoy Das +- Sean Allred +- Sean Bryant +- Sean Whitton +- Sebastian Wiesner +- Sébastien Gross +- Seong-Kook Shin +- Sergey Pashinin +- Sergey Vinokurov +- Servilio Afre Puentes +- Silent Sphere +- Štěpán Němec +- Steven Chow +- Steven E. Harris +- Steven Thomas +- Steven Vancoillie +- Steve Purcell +- Suhail Shergill +- Sylvain Rousseau +- Syohei Yoshida +- Takafumi Arakaki +- Tassilo Horn +- Teemu Likonen +- Teruki Shigitani +- Thierry Volpiatto +- Thomas A Caswell +- Thomas Fini Hansen +- Thomas Frössman +- Thomas Jost +- Thomas Riccardi +- Tibor Simko +- Timo Juhani Lindfors +- Tim Perkins +- Tim Wraight +- Ting-Yu Lin +- Tom Feist +- Topi Miettinen +- Troy Hinckley +- Tunc Uzlu +- Vineet Naik +- Vitaly Ostashov +- Vladimir Panteleev +- Wei Huang +- Wilfred Hughes +- Win Treese +- Wouter Bolsterlee +- Xavier Noria +- Xu Chunyang +- Yann Hodique +- Ynilu +- York Zhao +- Yuichi Higashi +- Yuri Khan +- Zach Latta +- zakora +- Zhu Zihao +- zilongshanren diff --git a/elpa/magit-20191122.2040/LICENSE b/elpa/magit-20191122.2040/LICENSE new file mode 100644 index 00000000..44325404 --- /dev/null +++ b/elpa/magit-20191122.2040/LICENSE @@ -0,0 +1,676 @@ + + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. + diff --git a/elpa/magit-20191122.2040/dir b/elpa/magit-20191122.2040/dir new file mode 100644 index 00000000..dfdbd715 --- /dev/null +++ b/elpa/magit-20191122.2040/dir @@ -0,0 +1,18 @@ +This is the file .../info/dir, which contains the +topmost node of the Info hierarchy, called (dir)Top. +The first time you invoke Info you start off looking at this node. + +File: dir, Node: Top This is the top of the INFO tree + + This (the Directory node) gives a menu of major topics. + Typing "q" exits, "H" lists all Info commands, "d" returns here, + "h" gives a primer for first-timers, + "mEmacs" visits the Emacs manual, etc. + + In Emacs, you can click mouse button 2 on a menu item or cross reference + to select it. + +* Menu: + +Emacs +* Magit: (magit). Using Git from Emacs with Magit. diff --git a/elpa/magit-20191122.2040/git-rebase.el b/elpa/magit-20191122.2040/git-rebase.el new file mode 100644 index 00000000..af3824e3 --- /dev/null +++ b/elpa/magit-20191122.2040/git-rebase.el @@ -0,0 +1,818 @@ +;;; git-rebase.el --- Edit Git rebase files -*- lexical-binding: t -*- + +;; Copyright (C) 2010-2019 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Phil Jackson +;; Maintainer: Jonas Bernoulli + +;; This file is not part of GNU Emacs. + +;; This file is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + +;; This file is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this file. If not, see . + +;;; Commentary: + +;; This package assists the user in editing the list of commits to be +;; rewritten during an interactive rebase. + +;; When the user initiates an interactive rebase, e.g. using "r e" in +;; a Magit buffer or on the command line using "git rebase -i REV", +;; Git invokes the `$GIT_SEQUENCE_EDITOR' (or if that is undefined +;; `$GIT_EDITOR' or even `$EDITOR') letting the user rearrange, drop, +;; reword, edit, and squash commits. + +;; This package provides the major-mode `git-rebase-mode' which makes +;; doing so much more fun, by making the buffer more colorful and +;; providing the following commands: +;; +;; C-c C-c Tell Git to make it happen. +;; C-c C-k Tell Git that you changed your mind, i.e. abort. +;; +;; p Move point to previous line. +;; n Move point to next line. +;; +;; M-p Move the commit at point up. +;; M-n Move the commit at point down. +;; +;; k Drop the commit at point. +;; c Don't drop the commit at point. +;; r Change the message of the commit at point. +;; e Edit the commit at point. +;; s Squash the commit at point, into the one above. +;; f Like "s" but don't also edit the commit message. +;; b Break for editing at this point in the sequence. +;; x Add a script to be run with the commit at point +;; being checked out. +;; z Add noop action at point. +;; +;; SPC Show the commit at point in another buffer. +;; RET Show the commit at point in another buffer and +;; select its window. +;; C-/ Undo last change. +;; +;; Commands for --rebase-merges: +;; l Associate label with current HEAD in sequence. +;; MM Merge specified revisions into HEAD. +;; Mt Toggle whether the merge will invoke an editor +;; before committing. +;; t Reset HEAD to the specified label. + +;; You should probably also read the `git-rebase' manpage. + +;;; Code: + +(require 'dash) +(require 'easymenu) +(require 'server) +(require 'with-editor) +(require 'magit) + +(and (require 'async-bytecomp nil t) + (let ((pkgs (bound-and-true-p async-bytecomp-allowed-packages))) + (if (consp pkgs) + (cl-intersection '(all magit) pkgs) + (memq pkgs '(all t)))) + (fboundp 'async-bytecomp-package-mode) + (async-bytecomp-package-mode 1)) + +(eval-when-compile (require 'recentf)) + +;;; Options +;;;; Variables + +(defgroup git-rebase nil + "Edit Git rebase sequences." + :link '(info-link "(magit)Editing Rebase Sequences") + :group 'tools) + +(defcustom git-rebase-auto-advance t + "Whether to move to next line after changing a line." + :group 'git-rebase + :type 'boolean) + +(defcustom git-rebase-show-instructions t + "Whether to show usage instructions inside the rebase buffer." + :group 'git-rebase + :type 'boolean) + +(defcustom git-rebase-confirm-cancel t + "Whether confirmation is required to cancel." + :group 'git-rebase + :type 'boolean) + +;;;; Faces + +(defgroup git-rebase-faces nil + "Faces used by Git-Rebase mode." + :group 'faces + :group 'git-rebase) + +(defface git-rebase-hash '((t (:inherit magit-hash))) + "Face for commit hashes." + :group 'git-rebase-faces) + +(defface git-rebase-label '((t (:inherit magit-refname))) + "Face for labels in label, merge, and reset lines." + :group 'git-rebase-faces) + +(defface git-rebase-description nil + "Face for commit descriptions." + :group 'git-rebase-faces) + +(defface git-rebase-killed-action + '((t (:inherit font-lock-comment-face :strike-through t))) + "Face for commented commit action lines." + :group 'git-rebase-faces) + +(defface git-rebase-comment-hash + '((t (:inherit git-rebase-hash :weight bold))) + "Face for commit hashes in commit message comments." + :group 'git-rebase-faces) + +(defface git-rebase-comment-heading + '((t :inherit font-lock-keyword-face)) + "Face for headings in rebase message comments." + :group 'git-commit-faces) + +;;; Keymaps + +(defvar git-rebase-mode-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map special-mode-map) + (cond ((featurep 'jkl) + (define-key map [return] 'git-rebase-show-commit) + (define-key map (kbd "i") 'git-rebase-backward-line) + (define-key map (kbd "k") 'forward-line) + (define-key map (kbd "M-i") 'git-rebase-move-line-up) + (define-key map (kbd "M-k") 'git-rebase-move-line-down) + (define-key map (kbd "p") 'git-rebase-pick) + (define-key map (kbd ",") 'git-rebase-kill-line)) + (t + (define-key map (kbd "C-m") 'git-rebase-show-commit) + (define-key map (kbd "p") 'git-rebase-backward-line) + (define-key map (kbd "n") 'forward-line) + (define-key map (kbd "M-p") 'git-rebase-move-line-up) + (define-key map (kbd "M-n") 'git-rebase-move-line-down) + (define-key map (kbd "c") 'git-rebase-pick) + (define-key map (kbd "k") 'git-rebase-kill-line) + (define-key map (kbd "C-k") 'git-rebase-kill-line))) + (define-key map (kbd "b") 'git-rebase-break) + (define-key map (kbd "e") 'git-rebase-edit) + (define-key map (kbd "l") 'git-rebase-label) + (define-key map (kbd "MM") 'git-rebase-merge) + (define-key map (kbd "Mt") 'git-rebase-merge-toggle-editmsg) + (define-key map (kbd "m") 'git-rebase-edit) + (define-key map (kbd "f") 'git-rebase-fixup) + (define-key map (kbd "q") 'undefined) + (define-key map (kbd "r") 'git-rebase-reword) + (define-key map (kbd "w") 'git-rebase-reword) + (define-key map (kbd "s") 'git-rebase-squash) + (define-key map (kbd "t") 'git-rebase-reset) + (define-key map (kbd "x") 'git-rebase-exec) + (define-key map (kbd "y") 'git-rebase-insert) + (define-key map (kbd "z") 'git-rebase-noop) + (define-key map (kbd "SPC") 'git-rebase-show-or-scroll-up) + (define-key map (kbd "DEL") 'git-rebase-show-or-scroll-down) + (define-key map (kbd "C-x C-t") 'git-rebase-move-line-up) + (define-key map [M-up] 'git-rebase-move-line-up) + (define-key map [M-down] 'git-rebase-move-line-down) + (define-key map [remap undo] 'git-rebase-undo) + map) + "Keymap for Git-Rebase mode.") + +(cond ((featurep 'jkl) + (put 'git-rebase-reword :advertised-binding "r") + (put 'git-rebase-move-line-up :advertised-binding (kbd "M-i")) + (put 'git-rebase-kill-line :advertised-binding ",")) + (t + (put 'git-rebase-reword :advertised-binding "r") + (put 'git-rebase-move-line-up :advertised-binding (kbd "M-p")) + (put 'git-rebase-kill-line :advertised-binding "k"))) + +(easy-menu-define git-rebase-mode-menu git-rebase-mode-map + "Git-Rebase mode menu" + '("Rebase" + ["Pick" git-rebase-pick t] + ["Reword" git-rebase-reword t] + ["Edit" git-rebase-edit t] + ["Squash" git-rebase-squash t] + ["Fixup" git-rebase-fixup t] + ["Kill" git-rebase-kill-line t] + ["Noop" git-rebase-noop t] + ["Execute" git-rebase-exec t] + ["Move Down" git-rebase-move-line-down t] + ["Move Up" git-rebase-move-line-up t] + "---" + ["Cancel" with-editor-cancel t] + ["Finish" with-editor-finish t])) + +(defvar git-rebase-command-descriptions + '((with-editor-finish . "tell Git to make it happen") + (with-editor-cancel . "tell Git that you changed your mind, i.e. abort") + (git-rebase-backward-line . "move point to previous line") + (forward-line . "move point to next line") + (git-rebase-move-line-up . "move the commit at point up") + (git-rebase-move-line-down . "move the commit at point down") + (git-rebase-show-or-scroll-up . "show the commit at point in another buffer") + (git-rebase-show-commit + . "show the commit at point in another buffer and select its window") + (undo . "undo last change") + (git-rebase-kill-line . "drop the commit at point") + (git-rebase-insert . "insert a line for an arbitrary commit") + (git-rebase-noop . "add noop action at point"))) + +;;; Commands + +(defun git-rebase-pick () + "Use commit on current line." + (interactive) + (git-rebase-set-action "pick")) + +(defun git-rebase-reword () + "Edit message of commit on current line." + (interactive) + (git-rebase-set-action "reword")) + +(defun git-rebase-edit () + "Stop at the commit on the current line." + (interactive) + (git-rebase-set-action "edit")) + +(defun git-rebase-squash () + "Meld commit on current line into previous commit, edit message." + (interactive) + (git-rebase-set-action "squash")) + +(defun git-rebase-fixup () + "Meld commit on current line into previous commit, discard its message." + (interactive) + (git-rebase-set-action "fixup")) + +(defvar-local git-rebase-comment-re nil) + +(defvar git-rebase-short-options + '((?b . "break") + (?e . "edit") + (?f . "fixup") + (?l . "label") + (?m . "merge") + (?p . "pick") + (?r . "reword") + (?s . "squash") + (?t . "reset") + (?x . "exec")) + "Alist mapping single key of an action to the full name.") + +(defclass git-rebase-action () + (;; action-type: commit, exec, bare, label, merge + (action-type :initarg :action-type :initform nil) + ;; Examples for each action type: + ;; | action | action options | target | trailer | + ;; |--------+----------------+---------+---------| + ;; | pick | | hash | subject | + ;; | exec | | command | | + ;; | noop | | | | + ;; | reset | | name | subject | + ;; | merge | -C hash | name | subject | + (action :initarg :action :initform nil) + (action-options :initarg :action-options :initform nil) + (target :initarg :target :initform nil) + (trailer :initarg :trailer :initform nil) + (comment-p :initarg :comment-p :initform nil))) + +(defvar git-rebase-line-regexps + `((commit . ,(concat + (regexp-opt '("e" "edit" + "f" "fixup" + "p" "pick" + "r" "reword" + "s" "squash") + "\\(?1:") + " \\(?3:[^ \n]+\\) \\(?4:.*\\)")) + (exec . "\\(?1:x\\|exec\\) \\(?3:.*\\)") + (bare . ,(concat (regexp-opt '("b" "break" "noop") "\\(?1:") + " *$")) + (label . ,(concat (regexp-opt '("l" "label" + "t" "reset") + "\\(?1:") + " \\(?3:[^ \n]+\\) ?\\(?4:.*\\)")) + (merge . ,(concat "\\(?1:m\\|merge\\) " + "\\(?:\\(?2:-[cC] [^ \n]+\\) \\)?" + "\\(?3:[^ \n]+\\)" + " ?\\(?4:.*\\)")))) + +;;;###autoload +(defun git-rebase-current-line () + "Parse current line into a `git-rebase-action' instance. +If the current line isn't recognized as a rebase line, an +instance with all nil values is returned." + (save-excursion + (goto-char (line-beginning-position)) + (if-let ((re-start (concat "^\\(?5:" (regexp-quote comment-start) + "\\)? *")) + (type (-some (lambda (arg) + (let ((case-fold-search nil)) + (and (looking-at (concat re-start (cdr arg))) + (car arg)))) + git-rebase-line-regexps))) + (git-rebase-action + :action-type type + :action (when-let ((action (match-string-no-properties 1))) + (or (cdr (assoc action git-rebase-short-options)) + action)) + :action-options (match-string-no-properties 2) + :target (match-string-no-properties 3) + :trailer (match-string-no-properties 4) + :comment-p (and (match-string 5) t)) + ;; Use default empty class rather than nil to ease handling. + (git-rebase-action)))) + +(defun git-rebase-set-action (action) + (goto-char (line-beginning-position)) + (with-slots (action-type target trailer) + (git-rebase-current-line) + (if (eq action-type 'commit) + (let ((inhibit-read-only t)) + (magit-delete-line) + (insert (concat action " " target " " trailer "\n")) + (unless git-rebase-auto-advance + (forward-line -1))) + (ding)))) + +(defun git-rebase-line-p (&optional pos) + (save-excursion + (when pos (goto-char pos)) + (and (oref (git-rebase-current-line) action-type) + t))) + +(defun git-rebase-region-bounds () + (when (use-region-p) + (let ((beg (save-excursion (goto-char (region-beginning)) + (line-beginning-position))) + (end (save-excursion (goto-char (region-end)) + (line-end-position)))) + (when (and (git-rebase-line-p beg) + (git-rebase-line-p end)) + (list beg (1+ end)))))) + +(defun git-rebase-move-line-down (n) + "Move the current commit (or command) N lines down. +If N is negative, move the commit up instead. With an active +region, move all the lines that the region touches, not just the +current line." + (interactive "p") + (pcase-let* ((`(,beg ,end) + (or (git-rebase-region-bounds) + (list (line-beginning-position) + (1+ (line-end-position))))) + (pt-offset (- (point) beg)) + (mark-offset (and mark-active (- (mark) beg)))) + (save-restriction + (narrow-to-region + (point-min) + (1- + (if git-rebase-show-instructions + (save-excursion + (goto-char (point-min)) + (while (or (git-rebase-line-p) + ;; The output for --rebase-merges has empty + ;; lines and "Branch" comments interspersed. + (looking-at-p "^$") + (looking-at-p (concat git-rebase-comment-re + " Branch"))) + (forward-line)) + (line-beginning-position)) + (point-max)))) + (if (or (and (< n 0) (= beg (point-min))) + (and (> n 0) (= end (point-max))) + (> end (point-max))) + (ding) + (goto-char (if (< n 0) beg end)) + (forward-line n) + (atomic-change-group + (let ((inhibit-read-only t)) + (insert (delete-and-extract-region beg end))) + (let ((new-beg (- (point) (- end beg)))) + (when (use-region-p) + (setq deactivate-mark nil) + (set-mark (+ new-beg mark-offset))) + (goto-char (+ new-beg pt-offset)))))))) + +(defun git-rebase-move-line-up (n) + "Move the current commit (or command) N lines up. +If N is negative, move the commit down instead. With an active +region, move all the lines that the region touches, not just the +current line." + (interactive "p") + (git-rebase-move-line-down (- n))) + +(defun git-rebase-highlight-region (start end window rol) + (let ((inhibit-read-only t) + (deactivate-mark nil) + (bounds (git-rebase-region-bounds))) + (mapc #'delete-overlay magit-section-highlight-overlays) + (when bounds + (magit-section-make-overlay (car bounds) (cadr bounds) + 'magit-section-heading-selection)) + (if (and bounds (not magit-keep-region-overlay)) + (funcall (default-value 'redisplay-unhighlight-region-function) rol) + (funcall (default-value 'redisplay-highlight-region-function) + start end window rol)))) + +(defun git-rebase-unhighlight-region (rol) + (mapc #'delete-overlay magit-section-highlight-overlays) + (funcall (default-value 'redisplay-unhighlight-region-function) rol)) + +(defun git-rebase-kill-line () + "Kill the current action line." + (interactive) + (goto-char (line-beginning-position)) + (unless (oref (git-rebase-current-line) comment-p) + (let ((inhibit-read-only t)) + (insert comment-start) + (insert " ")) + (goto-char (line-beginning-position)) + (when git-rebase-auto-advance + (forward-line)))) + +(defun git-rebase-insert (rev) + "Read an arbitrary commit and insert it below current line." + (interactive (list (magit-read-branch-or-commit "Insert revision"))) + (forward-line) + (--if-let (magit-rev-format "%h %s" rev) + (let ((inhibit-read-only t)) + (insert "pick " it ?\n)) + (user-error "Unknown revision"))) + +(defun git-rebase-set-noncommit-action (action value-fn arg) + (goto-char (line-beginning-position)) + (pcase-let* ((inhibit-read-only t) + (`(,initial ,trailer ,comment-p) + (and (not arg) + (with-slots ((ln-action action) + target trailer comment-p) + (git-rebase-current-line) + (and (equal ln-action action) + (list target trailer comment-p))))) + (value (funcall value-fn initial))) + (pcase (list value initial comment-p) + (`("" nil ,_) + (ding)) + (`("" ,_ ,_) + (magit-delete-line)) + (_ + (if initial + (magit-delete-line) + (forward-line)) + (insert (concat action " " value + (and (equal value initial) + trailer + (concat " " trailer)) + "\n")) + (unless git-rebase-auto-advance + (forward-line -1)))))) + +(defun git-rebase-exec (arg) + "Insert a shell command to be run after the current commit. + +If there already is such a command on the current line, then edit +that instead. With a prefix argument insert a new command even +when there already is one on the current line. With empty input +remove the command on the current line, if any." + (interactive "P") + (git-rebase-set-noncommit-action + "exec" + (lambda (initial) (read-shell-command "Execute: " initial)) + arg)) + +(defun git-rebase-label (arg) + "Add a label after the current commit. +If there already is a label on the current line, then edit that +instead. With a prefix argument, insert a new label even when +there is already a label on the current line. With empty input, +remove the label on the current line, if any." + (interactive "P") + (git-rebase-set-noncommit-action + "label" + (lambda (initial) + (read-from-minibuffer + "Label: " initial magit-minibuffer-local-ns-map)) + arg)) + +(defun git-rebase-buffer-labels () + (let (labels) + (save-excursion + (goto-char (point-min)) + (while (re-search-forward "^\\(?:l\\|label\\) \\([^ \n]+\\)" nil t) + (push (match-string-no-properties 1) labels))) + (nreverse labels))) + +(defun git-rebase-reset (arg) + "Reset the current HEAD to a label. +If there already is a reset command on the current line, then +edit that instead. With a prefix argument, insert a new reset +line even when point is already on a reset line. With empty +input, remove the reset command on the current line, if any." + (interactive "P") + (git-rebase-set-noncommit-action + "reset" + (lambda (initial) + (or (magit-completing-read "Label" (git-rebase-buffer-labels) + nil t initial) + "")) + arg)) + +(defun git-rebase-merge (arg) + "Add a merge command after the current commit. +If there is already a merge command on the current line, then +replace that command instead. With a prefix argument, insert a +new merge command even when there is already one on the current +line. With empty input, remove the merge command on the current +line, if any." + (interactive "P") + (git-rebase-set-noncommit-action + "merge" + (lambda (_) + (or (magit-completing-read "Merge" (git-rebase-buffer-labels)) + "")) + arg)) + +(defun git-rebase-merge-toggle-editmsg () + "Toggle whether an editor is invoked when performing the merge at point. +When a merge command uses a lower-case -c, the message for the +specified commit will be opened in an editor before creating the +commit. For an upper-case -C, the message will be used as is." + (interactive) + (with-slots (action-type target action-options trailer) + (git-rebase-current-line) + (if (eq action-type 'merge) + (let ((inhibit-read-only t)) + (magit-delete-line) + (insert + (format "merge %s %s %s\n" + (replace-regexp-in-string + "-[cC]" (lambda (c) + (if (equal c "-c") "-C" "-c")) + action-options t t) + target + trailer))) + (ding)))) + +(defun git-rebase-set-bare-action (action arg) + (goto-char (line-beginning-position)) + (with-slots ((ln-action action) comment-p) + (git-rebase-current-line) + (let ((same-action-p (equal action ln-action)) + (inhibit-read-only t)) + (when (or arg + (not ln-action) + (not same-action-p) + (and same-action-p comment-p)) + (unless (or arg (not same-action-p)) + (magit-delete-line)) + (insert action ?\n) + (unless git-rebase-auto-advance + (forward-line -1)))))) + +(defun git-rebase-noop (&optional arg) + "Add noop action at point. + +If the current line already contains a noop action, leave it +unchanged. If there is a commented noop action present, remove +the comment. Otherwise add a new noop action. With a prefix +argument insert a new noop action regardless of what is already +present on the current line. + +A noop action can be used to make git perform a rebase even if +no commits are selected. Without the noop action present, git +would see an empty file and therefore do nothing." + (interactive "P") + (git-rebase-set-bare-action "noop" arg)) + +(defun git-rebase-break (&optional arg) + "Add break action at point. + +If there is a commented break action present, remove the comment. +If the current line already contains a break action, add another +break action only if a prefix argument is given. + +A break action can be used to interrupt the rebase at the +specified point. It is particularly useful for pausing before +the first commit in the sequence. For other cases, the +equivalent behavior can be achieved with `git-rebase-edit'." + (interactive "P") + (git-rebase-set-bare-action "break" arg)) + +(defun git-rebase-undo (&optional arg) + "Undo some previous changes. +Like `undo' but works in read-only buffers." + (interactive "P") + (let ((inhibit-read-only t)) + (undo arg))) + +(defun git-rebase--show-commit (&optional scroll) + (let ((disable-magit-save-buffers t)) + (save-excursion + (goto-char (line-beginning-position)) + (--if-let (with-slots (action-type target) (git-rebase-current-line) + (and (eq action-type 'commit) + target)) + (pcase scroll + (`up (magit-diff-show-or-scroll-up)) + (`down (magit-diff-show-or-scroll-down)) + (_ (apply #'magit-show-commit it + (magit-diff-arguments 'magit-revision-mode)))) + (ding))))) + +(defun git-rebase-show-commit () + "Show the commit on the current line if any." + (interactive) + (git-rebase--show-commit)) + +(defun git-rebase-show-or-scroll-up () + "Update the commit buffer for commit on current line. + +Either show the commit at point in the appropriate buffer, or if +that buffer is already being displayed in the current frame and +contains information about that commit, then instead scroll the +buffer up." + (interactive) + (git-rebase--show-commit 'up)) + +(defun git-rebase-show-or-scroll-down () + "Update the commit buffer for commit on current line. + +Either show the commit at point in the appropriate buffer, or if +that buffer is already being displayed in the current frame and +contains information about that commit, then instead scroll the +buffer down." + (interactive) + (git-rebase--show-commit 'down)) + +(defun git-rebase-backward-line (&optional n) + "Move N lines backward (forward if N is negative). +Like `forward-line' but go into the opposite direction." + (interactive "p") + (forward-line (- (or n 1)))) + +;;; Mode + +;;;###autoload +(define-derived-mode git-rebase-mode special-mode "Git Rebase" + "Major mode for editing of a Git rebase file. + +Rebase files are generated when you run 'git rebase -i' or run +`magit-interactive-rebase'. They describe how Git should perform +the rebase. See the documentation for git-rebase (e.g., by +running 'man git-rebase' at the command line) for details." + :group 'git-rebase + (setq comment-start (or (magit-get "core.commentChar") "#")) + (setq git-rebase-comment-re (concat "^" (regexp-quote comment-start))) + (setq font-lock-defaults (list (git-rebase-mode-font-lock-keywords) t t)) + (unless git-rebase-show-instructions + (let ((inhibit-read-only t)) + (flush-lines git-rebase-comment-re))) + (unless with-editor-mode + ;; Maybe already enabled when using `shell-command' or an Emacs shell. + (with-editor-mode 1)) + (when git-rebase-confirm-cancel + (add-hook 'with-editor-cancel-query-functions + 'git-rebase-cancel-confirm nil t)) + (setq-local redisplay-highlight-region-function 'git-rebase-highlight-region) + (setq-local redisplay-unhighlight-region-function 'git-rebase-unhighlight-region) + (add-hook 'with-editor-pre-cancel-hook 'git-rebase-autostash-save nil t) + (add-hook 'with-editor-post-cancel-hook 'git-rebase-autostash-apply nil t) + (setq imenu-prev-index-position-function + #'magit-imenu--rebase-prev-index-position-function) + (setq imenu-extract-index-name-function + #'magit-imenu--rebase-extract-index-name-function) + (when (boundp 'save-place) + (setq save-place nil))) + +(defun git-rebase-cancel-confirm (force) + (or (not (buffer-modified-p)) + force + (magit-confirm 'abort-rebase "Abort this rebase" nil 'noabort))) + +(defun git-rebase-autostash-save () + (--when-let (magit-file-line (magit-git-dir "rebase-merge/autostash")) + (push (cons 'stash it) with-editor-cancel-alist))) + +(defun git-rebase-autostash-apply () + (--when-let (cdr (assq 'stash with-editor-cancel-alist)) + (magit-stash-apply it))) + +(defun git-rebase-match-comment-line (limit) + (re-search-forward (concat git-rebase-comment-re ".*") limit t)) + +(defun git-rebase-mode-font-lock-keywords () + "Font lock keywords for Git-Rebase mode." + `((,(concat "^" (cdr (assq 'commit git-rebase-line-regexps))) + (1 'font-lock-keyword-face) + (3 'git-rebase-hash) + (4 'git-rebase-description)) + (,(concat "^" (cdr (assq 'exec git-rebase-line-regexps))) + (1 'font-lock-keyword-face) + (3 'git-rebase-description)) + (,(concat "^" (cdr (assq 'bare git-rebase-line-regexps))) + (1 'font-lock-keyword-face)) + (,(concat "^" (cdr (assq 'label git-rebase-line-regexps))) + (1 'font-lock-keyword-face) + (3 'git-rebase-label) + (4 'font-lock-comment-face)) + ("^\\(m\\(?:erge\\)?\\) -[Cc] \\([^ \n]+\\) \\([^ \n]+\\)\\( #.*\\)?" + (1 'font-lock-keyword-face) + (2 'git-rebase-hash) + (3 'git-rebase-label) + (4 'font-lock-comment-face)) + ("^\\(m\\(?:erge\\)?\\) \\([^ \n]+\\)" + (1 'font-lock-keyword-face) + (2 'git-rebase-label)) + (,(concat git-rebase-comment-re " *" + (cdr (assq 'commit git-rebase-line-regexps))) + 0 'git-rebase-killed-action t) + (git-rebase-match-comment-line 0 'font-lock-comment-face) + ("\\[[^[]*\\]" + 0 'magit-keyword t) + ("\\(?:fixup!\\|squash!\\)" + 0 'magit-keyword-squash t) + (,(format "^%s Rebase \\([^ ]*\\) onto \\([^ ]*\\)" comment-start) + (1 'git-rebase-comment-hash t) + (2 'git-rebase-comment-hash t)) + (,(format "^%s \\(Commands:\\)" comment-start) + (1 'git-rebase-comment-heading t)) + (,(format "^%s Branch \\(.*\\)" comment-start) + (1 'git-rebase-label t)))) + +(defun git-rebase-mode-show-keybindings () + "Modify the \"Commands:\" section of the comment Git generates +at the bottom of the file so that in place of the one-letter +abbreviation for the command, it shows the command's keybinding. +By default, this is the same except for the \"pick\" command." + (let ((inhibit-read-only t)) + (save-excursion + (goto-char (point-min)) + (when (and git-rebase-show-instructions + (re-search-forward + (concat git-rebase-comment-re "\\s-+p, pick") + nil t)) + (goto-char (line-beginning-position)) + (pcase-dolist (`(,cmd . ,desc) git-rebase-command-descriptions) + (insert (format "%s %-8s %s\n" + comment-start + (substitute-command-keys (format "\\[%s]" cmd)) + desc))) + (while (re-search-forward (concat git-rebase-comment-re + "\\( ?\\)\\([^\n,],\\) " + "\\([^\n ]+\\) ") + nil t) + (let ((cmd (intern (concat "git-rebase-" (match-string 3))))) + (if (not (fboundp cmd)) + (delete-region (line-beginning-position) (1+ (line-end-position))) + (replace-match " " t t nil 1) + (replace-match + (format "%-8s" + (mapconcat #'key-description + (--remove (eq (elt it 0) 'menu-bar) + (reverse (where-is-internal + cmd git-rebase-mode-map))) + ", ")) + t t nil 2)))))))) + +(add-hook 'git-rebase-mode-hook 'git-rebase-mode-show-keybindings t) + +(defun git-rebase-mode-disable-before-save-hook () + (set (make-local-variable 'before-save-hook) nil)) + +(add-hook 'git-rebase-mode-hook 'git-rebase-mode-disable-before-save-hook) + +;;;###autoload +(defconst git-rebase-filename-regexp "/git-rebase-todo\\'") +;;;###autoload +(add-to-list 'auto-mode-alist + (cons git-rebase-filename-regexp 'git-rebase-mode)) + +(add-to-list 'with-editor-server-window-alist + (cons git-rebase-filename-regexp 'switch-to-buffer)) + +(eval-after-load 'recentf + '(add-to-list 'recentf-exclude git-rebase-filename-regexp)) + +(add-to-list 'with-editor-file-name-history-exclude git-rebase-filename-regexp) + +;;; _ +(provide 'git-rebase) +;;; git-rebase.el ends here diff --git a/elpa/magit-20191122.2040/git-rebase.elc b/elpa/magit-20191122.2040/git-rebase.elc new file mode 100644 index 0000000000000000000000000000000000000000..2b80d774ca36a71d864808bb016d0bc6507b2839 GIT binary patch literal 27987 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 V0InQUlYzij{C9Kefk}| +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; This library implements commands for applying Git diffs or parts +;; of such a diff. The supported "apply variants" are apply, stage, +;; unstage, discard, and reverse - more than Git itself knows about, +;; at least at the porcelain level. + +;;; Code: + +(eval-when-compile + (require 'subr-x)) + +(require 'magit-core) +(require 'magit-diff) +(require 'magit-wip) + +(require 'transient) ; See #3732. + +;; For `magit-apply' +(declare-function magit-am "magit-sequence" ()) +(declare-function magit-patch-apply "magit-files" ()) +;; For `magit-discard-files' +(declare-function magit-checkout-stage "magit-merge" (file arg)) +(declare-function magit-checkout-read-stage "magit-merge" (file)) +(defvar auto-revert-verbose) +;; For `magit-stage-untracked' +(declare-function magit-submodule-add-1 "magit-submodule" + (url &optional path name args)) +(declare-function magit-submodule-read-name-for-path "magit-submodule" + (path &optional prefer-short)) +(declare-function borg--maybe-absorb-gitdir "borg" (pkg)) +(declare-function borg--sort-submodule-sections "borg" (file)) +(defvar borg-user-emacs-directory) + +;;; Options + +(defcustom magit-delete-by-moving-to-trash t + "Whether Magit uses the system's trash can. + +You should absolutely not disable this and also remove `discard' +from `magit-no-confirm'. You shouldn't do that even if you have +all of the Magit-Wip modes enabled, because those modes do not +track any files that are not tracked in the proper branch." + :package-version '(magit . "2.1.0") + :group 'magit-essentials + :type 'boolean) + +(defcustom magit-unstage-committed t + "Whether unstaging a committed change reverts it instead. + +A committed change cannot be unstaged, because staging and +unstaging are actions that are concerned with the differences +between the index and the working tree, not with committed +changes. + +If this option is non-nil (the default), then typing \"u\" +\(`magit-unstage') on a committed change, causes it to be +reversed in the index but not the working tree. For more +information see command `magit-reverse-in-index'." + :package-version '(magit . "2.4.1") + :group 'magit-commands + :type 'boolean) + +(defcustom magit-reverse-atomically nil + "Whether to reverse changes atomically. + +If some changes can be reversed while others cannot, then nothing +is reversed if the value of this option is non-nil. But when it +is nil, then the changes that can be reversed are reversed and +for the other changes diff files are created that contain the +rejected reversals." + :package-version '(magit . "2.7.0") + :group 'magit-commands + :type 'boolean) + +(defcustom magit-post-stage-hook nil + "Hook run after staging changes. +This hook is run by `magit-refresh' if `this-command' +is a member of `magit-post-stage-hook-commands'." + :package-version '(magit . "2.90.0") + :group 'magit-commands + :type 'hook) + +(defvar magit-post-stage-hook-commands + '(magit-stage magit-stage-file magit-stage-modified)) + +(defcustom magit-post-unstage-hook nil + "Hook run after unstaging changes. +This hook is run by `magit-refresh' if `this-command' +is a member of `magit-post-unstage-hook-commands'." + :package-version '(magit . "2.90.0") + :group 'magit-commands + :type 'hook) + +(defvar magit-post-unstage-hook-commands + '(magit-unstage magit-unstage-file magit-unstage-all)) + +;;; Commands +;;;; Apply + +(defun magit-apply (&rest args) + "Apply the change at point to the working tree. +With a prefix argument fallback to a 3-way merge. Doing +so causes the change to be applied to the index as well." + (interactive (and current-prefix-arg (list "--3way"))) + (--when-let (magit-apply--get-selection) + (pcase (list (magit-diff-type) (magit-diff-scope)) + (`(,(or `unstaged `staged) ,_) + (user-error "Change is already in the working tree")) + (`(untracked ,(or `file `files)) + (call-interactively 'magit-am)) + (`(,_ region) (magit-apply-region it args)) + (`(,_ hunk) (magit-apply-hunk it args)) + (`(,_ hunks) (magit-apply-hunks it args)) + (`(rebase-sequence file) + (call-interactively 'magit-patch-apply)) + (`(,_ file) (magit-apply-diff it args)) + (`(,_ files) (magit-apply-diffs it args))))) + +(defun magit-apply--section-content (section) + (buffer-substring-no-properties (if (magit-hunk-section-p section) + (oref section start) + (oref section content)) + (oref section end))) + +(defun magit-apply-diffs (sections &rest args) + (setq sections (magit-apply--get-diffs sections)) + (magit-apply-patch sections args + (mapconcat + (lambda (s) + (concat (magit-diff-file-header s) + (magit-apply--section-content s))) + sections ""))) + +(defun magit-apply-diff (section &rest args) + (setq section (car (magit-apply--get-diffs (list section)))) + (magit-apply-patch section args + (concat (magit-diff-file-header section) + (magit-apply--section-content section)))) + +(defun magit-apply--adjust-hunk-new-starts (hunks) + "Adjust new line numbers in headers of HUNKS for partial application. +HUNKS should be a list of ordered, contiguous hunks to be applied +from a file. For example, if there is a sequence of hunks with +the headers + + @@ -2,6 +2,7 @@ + @@ -10,6 +11,7 @@ + @@ -18,6 +20,7 @@ + +and only the second and third are to be applied, they would be +adjusted as \"@@ -10,6 +10,7 @@\" and \"@@ -18,6 +19,7 @@\"." + (let* ((first-hunk (car hunks)) + (offset (if (string-match diff-hunk-header-re-unified first-hunk) + (- (string-to-number (match-string 3 first-hunk)) + (string-to-number (match-string 1 first-hunk))) + (error "Hunk does not have expected header")))) + (if (= offset 0) + hunks + (mapcar (lambda (hunk) + (if (string-match diff-hunk-header-re-unified hunk) + (replace-match (number-to-string + (- (string-to-number (match-string 3 hunk)) + offset)) + t t hunk 3) + (error "Hunk does not have expected header"))) + hunks)))) + +(defun magit-apply--adjust-hunk-new-start (hunk) + (car (magit-apply--adjust-hunk-new-starts (list hunk)))) + +(defun magit-apply-hunks (sections &rest args) + (let ((section (oref (car sections) parent))) + (when (string-match "^diff --cc" (oref section value)) + (user-error "Cannot un-/stage resolution hunks. Stage the whole file")) + (magit-apply-patch + section args + (concat (oref section header) + (mapconcat #'identity + (magit-apply--adjust-hunk-new-starts + (mapcar #'magit-apply--section-content sections)) + ""))))) + +(defun magit-apply-hunk (section &rest args) + (when (string-match "^diff --cc" (magit-section-parent-value section)) + (user-error "Cannot un-/stage resolution hunks. Stage the whole file")) + (magit-apply-patch (oref section parent) args + (concat (magit-diff-file-header section) + (magit-apply--adjust-hunk-new-start + (magit-apply--section-content section))))) + +(defun magit-apply-region (section &rest args) + (when (string-match "^diff --cc" (magit-section-parent-value section)) + (user-error "Cannot un-/stage resolution hunks. Stage the whole file")) + (magit-apply-patch (oref section parent) args + (concat (magit-diff-file-header section) + (magit-apply--adjust-hunk-new-start + (magit-diff-hunk-region-patch section args))))) + +(defun magit-apply-patch (section:s args patch) + (let* ((files (if (atom section:s) + (list (oref section:s value)) + (--map (oref it value) section:s))) + (command (symbol-name this-command)) + (command (if (and command (string-match "^magit-\\([^-]+\\)" command)) + (match-string 1 command) + "apply")) + (ignore-context (magit-diff-ignore-any-space-p))) + (unless (magit-diff-context-p) + (user-error "Not enough context to apply patch. Increase the context")) + (when (and magit-wip-before-change-mode (not inhibit-magit-refresh)) + (magit-wip-commit-before-change files (concat " before " command))) + (with-temp-buffer + (insert patch) + (magit-run-git-with-input + "apply" args "-p0" + (and ignore-context "-C0") + "--ignore-space-change" "-")) + (unless inhibit-magit-refresh + (when magit-wip-after-apply-mode + (magit-wip-commit-after-apply files (concat " after " command))) + (magit-refresh)))) + +(defun magit-apply--get-selection () + (or (magit-region-sections '(hunk file module) t) + (let ((section (magit-current-section))) + (pcase (oref section type) + ((or `hunk `file `module) section) + ((or `staged `unstaged `untracked + `stashed-index `stashed-worktree `stashed-untracked) + (oref section children)) + (_ (user-error "Cannot apply this, it's not a change")))))) + +(defun magit-apply--get-diffs (sections) + (magit-section-case + ([file diffstat] + (--map (or (magit-get-section + (append `((file . ,(oref it value))) + (magit-section-ident magit-root-section))) + (error "Cannot get required diff headers")) + sections)) + (t sections))) + +(defun magit-apply--diff-ignores-whitespace-p () + (and (cl-intersection magit-buffer-diff-args + '("--ignore-space-at-eol" + "--ignore-space-change" + "--ignore-all-space" + "--ignore-blank-lines") + :test #'equal) + t)) + +;;;; Stage + +(defun magit-stage (&optional intent) + "Add the change at point to the staging area. +With a prefix argument, INTENT, and an untracked file (or files) +at point, stage the file but not its content." + (interactive "P") + (--if-let (and (derived-mode-p 'magit-mode) (magit-apply--get-selection)) + (pcase (list (magit-diff-type) + (magit-diff-scope) + (magit-apply--diff-ignores-whitespace-p)) + (`(untracked ,_ ,_) (magit-stage-untracked intent)) + (`(unstaged region ,_) (magit-apply-region it "--cached")) + (`(unstaged hunk ,_) (magit-apply-hunk it "--cached")) + (`(unstaged hunks ,_) (magit-apply-hunks it "--cached")) + (`(unstaged file t) (magit-apply-diff it "--cached")) + (`(unstaged files t) (magit-apply-diffs it "--cached")) + (`(unstaged list t) (magit-apply-diffs it "--cached")) + (`(unstaged file nil) (magit-stage-1 "-u" (list (oref it value)))) + (`(unstaged files nil) (magit-stage-1 "-u" (magit-region-values nil t))) + (`(unstaged list nil) (magit-stage-modified)) + (`(staged ,_ ,_) (user-error "Already staged")) + (`(committed ,_ ,_) (user-error "Cannot stage committed changes")) + (`(undefined ,_ ,_) (user-error "Cannot stage this change"))) + (call-interactively 'magit-stage-file))) + +;;;###autoload +(defun magit-stage-file (file) + "Stage all changes to FILE. +With a prefix argument or when there is no file at point ask for +the file to be staged. Otherwise stage the file at point without +requiring confirmation." + (interactive + (let* ((atpoint (magit-section-value-if 'file)) + (current (magit-file-relative-name)) + (choices (nconc (magit-unstaged-files) + (magit-untracked-files))) + (default (car (member (or atpoint current) choices)))) + (list (if (or current-prefix-arg (not default)) + (magit-completing-read "Stage file" choices + nil t nil nil default) + default)))) + (magit-with-toplevel + (magit-stage-1 nil (list file)))) + +;;;###autoload +(defun magit-stage-modified (&optional all) + "Stage all changes to files modified in the worktree. +Stage all new content of tracked files and remove tracked files +that no longer exist in the working tree from the index also. +With a prefix argument also stage previously untracked (but not +ignored) files." + (interactive "P") + (when (magit-anything-staged-p) + (magit-confirm 'stage-all-changes)) + (magit-with-toplevel + (magit-stage-1 (if all "--all" "-u") magit-buffer-diff-files))) + +(defun magit-stage-1 (arg &optional files) + (magit-wip-commit-before-change files " before stage") + (magit-run-git "add" arg (if files (cons "--" files) ".")) + (when magit-auto-revert-mode + (mapc #'magit-turn-on-auto-revert-mode-if-desired files)) + (magit-wip-commit-after-apply files " after stage")) + +(defun magit-stage-untracked (&optional intent) + (let* ((section (magit-current-section)) + (files (pcase (magit-diff-scope) + (`file (list (oref section value))) + (`files (magit-region-values nil t)) + (`list (magit-untracked-files)))) + plain repos) + (dolist (file files) + (if (and (not (file-symlink-p file)) + (magit-git-repo-p file t)) + (push file repos) + (push file plain))) + (magit-wip-commit-before-change files " before stage") + (when plain + (magit-run-git "add" (and intent "--intent-to-add") + "--" plain) + (when magit-auto-revert-mode + (mapc #'magit-turn-on-auto-revert-mode-if-desired plain))) + (dolist (repo repos) + (save-excursion + (goto-char (oref (magit-get-section + `((file . ,repo) (untracked) (status))) + start)) + (let* ((topdir (magit-toplevel)) + (package + (and (equal (bound-and-true-p borg-user-emacs-directory) + topdir) + (file-name-nondirectory (directory-file-name repo))))) + (magit-submodule-add-1 + (let ((default-directory + (file-name-as-directory (expand-file-name repo)))) + (or (magit-get "remote" (magit-get-some-remote) "url") + (concat (file-name-as-directory ".") repo))) + repo + (magit-submodule-read-name-for-path repo package)) + (when package + (borg--sort-submodule-sections + (expand-file-name ".gitmodules" topdir)) + (let ((default-directory borg-user-emacs-directory)) + (borg--maybe-absorb-gitdir package)) + (when (and (y-or-n-p + (format "Also build and activate `%s' drone?" package)) + (fboundp 'borg-build) + (fboundp 'borg-activate)) + (borg-build package) + (borg-activate package)))))) + (magit-wip-commit-after-apply files " after stage"))) + +;;;; Unstage + +(defun magit-unstage () + "Remove the change at point from the staging area." + (interactive) + (--when-let (magit-apply--get-selection) + (pcase (list (magit-diff-type) + (magit-diff-scope) + (magit-apply--diff-ignores-whitespace-p)) + (`(untracked ,_ ,_) (user-error "Cannot unstage untracked changes")) + (`(unstaged file ,_) (magit-unstage-intent (list (oref it value)))) + (`(unstaged files ,_) (magit-unstage-intent (magit-region-values nil t))) + (`(unstaged ,_ ,_) (user-error "Already unstaged")) + (`(staged region ,_) (magit-apply-region it "--reverse" "--cached")) + (`(staged hunk ,_) (magit-apply-hunk it "--reverse" "--cached")) + (`(staged hunks ,_) (magit-apply-hunks it "--reverse" "--cached")) + (`(staged file t) (magit-apply-diff it "--reverse" "--cached")) + (`(staged files t) (magit-apply-diffs it "--reverse" "--cached")) + (`(staged list t) (magit-apply-diffs it "--reverse" "--cached")) + (`(staged file nil) (magit-unstage-1 (list (oref it value)))) + (`(staged files nil) (magit-unstage-1 (magit-region-values nil t))) + (`(staged list nil) (magit-unstage-all)) + (`(committed ,_ ,_) (if magit-unstage-committed + (magit-reverse-in-index) + (user-error "Cannot unstage committed changes"))) + (`(undefined ,_ ,_) (user-error "Cannot unstage this change"))))) + +;;;###autoload +(defun magit-unstage-file (file) + "Unstage all changes to FILE. +With a prefix argument or when there is no file at point ask for +the file to be unstaged. Otherwise unstage the file at point +without requiring confirmation." + (interactive + (let* ((atpoint (magit-section-value-if 'file)) + (current (magit-file-relative-name)) + (choices (magit-staged-files)) + (default (car (member (or atpoint current) choices)))) + (list (if (or current-prefix-arg (not default)) + (magit-completing-read "Unstage file" choices + nil t nil nil default) + default)))) + (magit-with-toplevel + (magit-unstage-1 (list file)))) + +(defun magit-unstage-1 (files) + (magit-wip-commit-before-change files " before unstage") + (if (magit-no-commit-p) + (magit-run-git "rm" "--cached" "--" files) + (magit-run-git "reset" "HEAD" "--" files)) + (magit-wip-commit-after-apply files " after unstage")) + +(defun magit-unstage-intent (files) + (if-let ((staged (magit-staged-files)) + (intent (--filter (member it staged) files))) + (magit-unstage-1 intent) + (user-error "Already unstaged"))) + +;;;###autoload +(defun magit-unstage-all () + "Remove all changes from the staging area." + (interactive) + (when (or (magit-anything-unstaged-p) + (magit-untracked-files)) + (magit-confirm 'unstage-all-changes)) + (magit-wip-commit-before-change nil " before unstage") + (magit-run-git "reset" "HEAD" "--" magit-buffer-diff-files) + (magit-wip-commit-after-apply nil " after unstage")) + +;;;; Discard + +(defun magit-discard () + "Remove the change at point." + (interactive) + (--when-let (magit-apply--get-selection) + (pcase (list (magit-diff-type) (magit-diff-scope)) + (`(committed ,_) (user-error "Cannot discard committed changes")) + (`(undefined ,_) (user-error "Cannot discard this change")) + (`(,_ region) (magit-discard-region it)) + (`(,_ hunk) (magit-discard-hunk it)) + (`(,_ hunks) (magit-discard-hunks it)) + (`(,_ file) (magit-discard-file it)) + (`(,_ files) (magit-discard-files it)) + (`(,_ list) (magit-discard-files it))))) + +(defun magit-discard-region (section) + (magit-confirm 'discard "Discard region") + (magit-discard-apply section 'magit-apply-region)) + +(defun magit-discard-hunk (section) + (magit-confirm 'discard "Discard hunk") + (magit-discard-apply section 'magit-apply-hunk)) + +(defun magit-discard-apply (section apply) + (if (eq (magit-diff-type section) 'unstaged) + (funcall apply section "--reverse") + (if (magit-anything-unstaged-p + nil (if (magit-file-section-p section) + (oref section value) + (magit-section-parent-value section))) + (progn (let ((inhibit-magit-refresh t)) + (funcall apply section "--reverse" "--cached") + (funcall apply section "--reverse" "--reject")) + (magit-refresh)) + (funcall apply section "--reverse" "--index")))) + +(defun magit-discard-hunks (sections) + (magit-confirm 'discard (format "Discard %s hunks from %s" + (length sections) + (magit-section-parent-value (car sections)))) + (magit-discard-apply-n sections 'magit-apply-hunks)) + +(defun magit-discard-apply-n (sections apply) + (let ((section (car sections))) + (if (eq (magit-diff-type section) 'unstaged) + (funcall apply sections "--reverse") + (if (magit-anything-unstaged-p + nil (if (magit-file-section-p section) + (oref section value) + (magit-section-parent-value section))) + (progn (let ((inhibit-magit-refresh t)) + (funcall apply sections "--reverse" "--cached") + (funcall apply sections "--reverse" "--reject")) + (magit-refresh)) + (funcall apply sections "--reverse" "--index"))))) + +(defun magit-discard-file (section) + (magit-discard-files (list section))) + +(defun magit-discard-files (sections) + (let ((auto-revert-verbose nil) + (type (magit-diff-type (car sections))) + (status (magit-file-status)) + files delete resurrect rename discard discard-new resolve) + (dolist (section sections) + (let ((file (oref section value))) + (push file files) + (pcase (cons (pcase type + (`staged ?X) + (`unstaged ?Y) + (`untracked ?Z)) + (cddr (assoc file status))) + (`(?Z) (dolist (f (magit-untracked-files nil file)) + (push f delete))) + ((or `(?Z ?? ??) `(?Z ?! ?!)) (push file delete)) + ((or `(?Z ?D ? ) `(,_ ?D ?D)) (push file delete)) + ((or `(,_ ?U ,_) `(,_ ,_ ?U)) (push file resolve)) + (`(,_ ?A ?A) (push file resolve)) + (`(?X ?M ,(or ? ?M ?D)) (push section discard)) + (`(?Y ,_ ?M ) (push section discard)) + (`(?X ?A ?M ) (push file discard-new)) + (`(?X ?C ?M ) (push file discard-new)) + (`(?X ?A ,(or ? ?D)) (push file delete)) + (`(?X ?C ,(or ? ?D)) (push file delete)) + (`(?X ?D ,(or ? ?M )) (push file resurrect)) + (`(?Y ,_ ?D ) (push file resurrect)) + (`(?X ?R ,(or ? ?M ?D)) (push file rename))))) + (unwind-protect + (let ((inhibit-magit-refresh t)) + (magit-wip-commit-before-change files " before discard") + (when resolve + (magit-discard-files--resolve (nreverse resolve))) + (when resurrect + (magit-discard-files--resurrect (nreverse resurrect))) + (when delete + (magit-discard-files--delete (nreverse delete) status)) + (when rename + (magit-discard-files--rename (nreverse rename) status)) + (when (or discard discard-new) + (magit-discard-files--discard (nreverse discard) + (nreverse discard-new))) + (magit-wip-commit-after-apply files " after discard")) + (magit-refresh)))) + +(defun magit-discard-files--resolve (files) + (if-let ((arg (and (cdr files) + (magit-read-char-case + (format "For these %i files\n%s\ncheckout:\n" + (length files) + (mapconcat (lambda (file) + (concat " " file)) + files "\n")) + t + (?o "[o]ur stage" "--ours") + (?t "[t]heir stage" "--theirs") + (?c "[c]onflict" "--merge") + (?i "decide [i]ndividually" nil))))) + (dolist (file files) + (magit-checkout-stage file arg)) + (dolist (file files) + (magit-checkout-stage file (magit-checkout-read-stage file))))) + +(defun magit-discard-files--resurrect (files) + (magit-confirm-files 'resurrect files) + (if (eq (magit-diff-type) 'staged) + (magit-call-git "reset" "--" files) + (magit-call-git "checkout" "--" files))) + +(defun magit-discard-files--delete (files status) + (magit-confirm-files (if magit-delete-by-moving-to-trash 'trash 'delete) + files) + (let ((delete-by-moving-to-trash magit-delete-by-moving-to-trash)) + (dolist (file files) + (when (string-match-p "\\`\\\\?~" file) + (error "Refusing to delete %S, too dangerous" file)) + (pcase (nth 3 (assoc file status)) + ((guard (memq (magit-diff-type) '(unstaged untracked))) + (dired-delete-file file dired-recursive-deletes + magit-delete-by-moving-to-trash) + (dired-clean-up-after-deletion file)) + (?\s (delete-file file t) + (magit-call-git "rm" "--cached" "--" file)) + (?M (let ((temp (magit-git-string "checkout-index" "--temp" file))) + (string-match + (format "\\(.+?\\)\t%s" (regexp-quote file)) temp) + (rename-file (match-string 1 temp) + (setq temp (concat file ".~{index}~"))) + (delete-file temp t)) + (magit-call-git "rm" "--cached" "--force" "--" file)) + (?D (magit-call-git "checkout" "--" file) + (delete-file file t) + (magit-call-git "rm" "--cached" "--force" "--" file)))))) + +(defun magit-discard-files--rename (files status) + (magit-confirm 'rename "Undo rename %s" "Undo %i renames" nil + (mapcar (lambda (file) + (setq file (assoc file status)) + (format "%s -> %s" (cadr file) (car file))) + files)) + (dolist (file files) + (let ((orig (cadr (assoc file status)))) + (if (file-exists-p file) + (progn + (--when-let (file-name-directory orig) + (make-directory it t)) + (magit-call-git "mv" file orig)) + (magit-call-git "rm" "--cached" "--" file) + (magit-call-git "reset" "--" orig))))) + +(defun magit-discard-files--discard (sections new-files) + (let ((files (--map (oref it value) sections))) + (magit-confirm-files 'discard (append files new-files) + (format "Discard %s changes in" (magit-diff-type))) + (if (eq (magit-diff-type (car sections)) 'unstaged) + (magit-call-git "checkout" "--" files) + (when new-files + (magit-call-git "add" "--" new-files) + (magit-call-git "reset" "--" new-files)) + (let ((binaries (magit-binary-files "--cached"))) + (when binaries + (setq sections + (--remove (member (oref it value) binaries) + sections))) + (cond ((= (length sections) 1) + (magit-discard-apply (car sections) 'magit-apply-diff)) + (sections + (magit-discard-apply-n sections 'magit-apply-diffs))) + (when binaries + (let ((modified (magit-unstaged-files t))) + (setq binaries (--separate (member it modified) binaries))) + (when (cadr binaries) + (magit-call-git "reset" "--" (cadr binaries))) + (when (car binaries) + (user-error + (concat + "Cannot discard staged changes to binary files, " + "which also have unstaged changes. Unstage instead.")))))))) + +;;;; Reverse + +(defun magit-reverse (&rest args) + "Reverse the change at point in the working tree. +With a prefix argument fallback to a 3-way merge. Doing +so causes the change to be applied to the index as well." + (interactive (and current-prefix-arg (list "--3way"))) + (--when-let (magit-apply--get-selection) + (pcase (list (magit-diff-type) (magit-diff-scope)) + (`(untracked ,_) (user-error "Cannot reverse untracked changes")) + (`(unstaged ,_) (user-error "Cannot reverse unstaged changes")) + (`(,_ region) (magit-reverse-region it args)) + (`(,_ hunk) (magit-reverse-hunk it args)) + (`(,_ hunks) (magit-reverse-hunks it args)) + (`(,_ file) (magit-reverse-file it args)) + (`(,_ files) (magit-reverse-files it args)) + (`(,_ list) (magit-reverse-files it args))))) + +(defun magit-reverse-region (section args) + (magit-confirm 'reverse "Reverse region") + (magit-reverse-apply section 'magit-apply-region args)) + +(defun magit-reverse-hunk (section args) + (magit-confirm 'reverse "Reverse hunk") + (magit-reverse-apply section 'magit-apply-hunk args)) + +(defun magit-reverse-hunks (sections args) + (magit-confirm 'reverse + (format "Reverse %s hunks from %s" + (length sections) + (magit-section-parent-value (car sections)))) + (magit-reverse-apply sections 'magit-apply-hunks args)) + +(defun magit-reverse-file (section args) + (magit-reverse-files (list section) args)) + +(defun magit-reverse-files (sections args) + (pcase-let ((`(,binaries ,sections) + (let ((bs (magit-binary-files + (cond ((derived-mode-p 'magit-revision-mode) + magit-buffer-range) + ((derived-mode-p 'magit-diff-mode) + magit-buffer-range) + (t + "--cached"))))) + (--separate (member (oref it value) bs) + sections)))) + (magit-confirm-files 'reverse (--map (oref it value) sections)) + (cond ((= (length sections) 1) + (magit-reverse-apply (car sections) 'magit-apply-diff args)) + (sections + (magit-reverse-apply sections 'magit-apply-diffs args))) + (when binaries + (user-error "Cannot reverse binary files")))) + +(defun magit-reverse-apply (section:s apply args) + (funcall apply section:s "--reverse" args + (and (not magit-reverse-atomically) + (not (member "--3way" args)) + "--reject"))) + +(defun magit-reverse-in-index (&rest args) + "Reverse the change at point in the index but not the working tree. + +Use this command to extract a change from `HEAD', while leaving +it in the working tree, so that it can later be committed using +a separate commit. A typical workflow would be: + +0. Optionally make sure that there are no uncommitted changes. +1. Visit the `HEAD' commit and navigate to the change that should + not have been included in that commit. +2. Type \"u\" (`magit-unstage') to reverse it in the index. + This assumes that `magit-unstage-committed-changes' is non-nil. +3. Type \"c e\" to extend `HEAD' with the staged changes, + including those that were already staged before. +4. Optionally stage the remaining changes using \"s\" or \"S\" + and then type \"c c\" to create a new commit." + (interactive) + (magit-reverse (cons "--cached" args))) + +;;; _ +(provide 'magit-apply) +;;; magit-apply.el ends here diff --git a/elpa/magit-20191122.2040/magit-apply.elc b/elpa/magit-20191122.2040/magit-apply.elc new file mode 100644 index 0000000000000000000000000000000000000000..8b68625c67a9625dd1948cfbffcfe03a5a200937 GIT binary patch literal 31993 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 OR7jg;rB@VgZ~T96H>)ZD literal 0 HcmV?d00001 diff --git a/elpa/magit-20191122.2040/magit-autoloads.el b/elpa/magit-20191122.2040/magit-autoloads.el new file mode 100644 index 00000000..93b28475 --- /dev/null +++ b/elpa/magit-20191122.2040/magit-autoloads.el @@ -0,0 +1,2510 @@ +;;; magit-autoloads.el --- automatically extracted autoloads +;; +;;; Code: + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + + +;;;### (autoloads nil "git-rebase" "git-rebase.el" (0 0 0 0)) +;;; Generated autoloads from git-rebase.el + +(autoload 'git-rebase-current-line "git-rebase" "\ +Parse current line into a `git-rebase-action' instance. +If the current line isn't recognized as a rebase line, an +instance with all nil values is returned. + +\(fn)" nil nil) + +(autoload 'git-rebase-mode "git-rebase" "\ +Major mode for editing of a Git rebase file. + +Rebase files are generated when you run 'git rebase -i' or run +`magit-interactive-rebase'. They describe how Git should perform +the rebase. See the documentation for git-rebase (e.g., by +running 'man git-rebase' at the command line) for details. + +\(fn)" t nil) + +(defconst git-rebase-filename-regexp "/git-rebase-todo\\'") + +(add-to-list 'auto-mode-alist (cons git-rebase-filename-regexp 'git-rebase-mode)) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "git-rebase" '("git-rebase-"))) + +;;;*** + +;;;### (autoloads nil "magit" "magit.el" (0 0 0 0)) +;;; Generated autoloads from magit.el + (autoload 'magit-dispatch "magit" nil t) + (autoload 'magit-run "magit" nil t) + +(autoload 'magit-git-command "magit" "\ +Execute COMMAND asynchronously; display output. + +Interactively, prompt for COMMAND in the minibuffer. \"git \" is +used as initial input, but can be deleted to run another command. + +With a prefix argument COMMAND is run in the top-level directory +of the current working tree, otherwise in `default-directory'. + +\(fn COMMAND)" t nil) + +(autoload 'magit-git-command-topdir "magit" "\ +Execute COMMAND asynchronously; display output. + +Interactively, prompt for COMMAND in the minibuffer. \"git \" is +used as initial input, but can be deleted to run another command. + +COMMAND is run in the top-level directory of the current +working tree. + +\(fn COMMAND)" t nil) + +(autoload 'magit-shell-command "magit" "\ +Execute COMMAND asynchronously; display output. + +Interactively, prompt for COMMAND in the minibuffer. With a +prefix argument COMMAND is run in the top-level directory of +the current working tree, otherwise in `default-directory'. + +\(fn COMMAND)" t nil) + +(autoload 'magit-shell-command-topdir "magit" "\ +Execute COMMAND asynchronously; display output. + +Interactively, prompt for COMMAND in the minibuffer. COMMAND +is run in the top-level directory of the current working tree. + +\(fn COMMAND)" t nil) + +(autoload 'magit-version "magit" "\ +Return the version of Magit currently in use. +If optional argument PRINT-DEST is non-nil, output +stream (interactively, the echo area, or the current buffer with +a prefix argument), also print the used versions of Magit, Git, +and Emacs to it. + +\(fn &optional PRINT-DEST)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit" '("magit-"))) + +;;;*** + +;;;### (autoloads nil "magit-apply" "magit-apply.el" (0 0 0 0)) +;;; Generated autoloads from magit-apply.el + +(autoload 'magit-stage-file "magit-apply" "\ +Stage all changes to FILE. +With a prefix argument or when there is no file at point ask for +the file to be staged. Otherwise stage the file at point without +requiring confirmation. + +\(fn FILE)" t nil) + +(autoload 'magit-stage-modified "magit-apply" "\ +Stage all changes to files modified in the worktree. +Stage all new content of tracked files and remove tracked files +that no longer exist in the working tree from the index also. +With a prefix argument also stage previously untracked (but not +ignored) files. + +\(fn &optional ALL)" t nil) + +(autoload 'magit-unstage-file "magit-apply" "\ +Unstage all changes to FILE. +With a prefix argument or when there is no file at point ask for +the file to be unstaged. Otherwise unstage the file at point +without requiring confirmation. + +\(fn FILE)" t nil) + +(autoload 'magit-unstage-all "magit-apply" "\ +Remove all changes from the staging area. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-apply" '("magit-"))) + +;;;*** + +;;;### (autoloads nil "magit-autorevert" "magit-autorevert.el" (0 +;;;;;; 0 0 0)) +;;; Generated autoloads from magit-autorevert.el + +(defvar magit-auto-revert-mode (not (or global-auto-revert-mode noninteractive)) "\ +Non-nil if Magit-Auto-Revert mode is enabled. +See the `magit-auto-revert-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `magit-auto-revert-mode'.") + +(custom-autoload 'magit-auto-revert-mode "magit-autorevert" nil) + +(autoload 'magit-auto-revert-mode "magit-autorevert" "\ +Toggle Auto-Revert mode in all buffers. +With prefix ARG, enable Magit-Auto-Revert mode if ARG is positive; +otherwise, disable it. If called from Lisp, enable the mode if +ARG is omitted or nil. + +Auto-Revert mode is enabled in all buffers where +`magit-turn-on-auto-revert-mode-if-desired' would do it. +See `auto-revert-mode' for more information on Auto-Revert mode. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-autorevert" '("auto-revert-buffer" "magit-"))) + +;;;*** + +;;;### (autoloads nil "magit-bisect" "magit-bisect.el" (0 0 0 0)) +;;; Generated autoloads from magit-bisect.el + (autoload 'magit-bisect "magit-bisect" nil t) + +(autoload 'magit-bisect-start "magit-bisect" "\ +Start a bisect session. + +Bisecting a bug means to find the commit that introduced it. +This command starts such a bisect session by asking for a know +good and a bad commit. To move the session forward use the +other actions from the bisect transient command (\\\\[magit-bisect]). + +\(fn BAD GOOD)" t nil) + +(autoload 'magit-bisect-reset "magit-bisect" "\ +After bisecting, cleanup bisection state and return to original `HEAD'. + +\(fn)" t nil) + +(autoload 'magit-bisect-good "magit-bisect" "\ +While bisecting, mark the current commit as good. +Use this after you have asserted that the commit does not contain +the bug in question. + +\(fn)" t nil) + +(autoload 'magit-bisect-bad "magit-bisect" "\ +While bisecting, mark the current commit as bad. +Use this after you have asserted that the commit does contain the +bug in question. + +\(fn)" t nil) + +(autoload 'magit-bisect-skip "magit-bisect" "\ +While bisecting, skip the current commit. +Use this if for some reason the current commit is not a good one +to test. This command lets Git choose a different one. + +\(fn)" t nil) + +(autoload 'magit-bisect-run "magit-bisect" "\ +Bisect automatically by running commands after each step. + +Unlike `git bisect run' this can be used before bisecting has +begun. In that case it behaves like `git bisect start; git +bisect run'. + +\(fn CMDLINE &optional BAD GOOD)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-bisect" '("magit-"))) + +;;;*** + +;;;### (autoloads nil "magit-blame" "magit-blame.el" (0 0 0 0)) +;;; Generated autoloads from magit-blame.el + (autoload 'magit-blame-echo "magit-blame" nil t) + (autoload 'magit-blame-addition "magit-blame" nil t) + (autoload 'magit-blame-removal "magit-blame" nil t) + (autoload 'magit-blame-reverse "magit-blame" nil t) + (autoload 'magit-blame "magit-blame" nil t) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-blame" '("magit-"))) + +;;;*** + +;;;### (autoloads nil "magit-bookmark" "magit-bookmark.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from magit-bookmark.el + +(autoload 'magit--handle-bookmark "magit-bookmark" "\ +Open a bookmark created by `magit--make-bookmark'. +Call the `magit-*-setup-buffer' function of the the major-mode +with the variables' values as arguments, which were recorded by +`magit--make-bookmark'. Ignore `magit-display-buffer-function'. + +\(fn BOOKMARK)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-bookmark" '("magit--make-bookmark"))) + +;;;*** + +;;;### (autoloads nil "magit-branch" "magit-branch.el" (0 0 0 0)) +;;; Generated autoloads from magit-branch.el + (autoload 'magit-branch "magit" nil t) + +(autoload 'magit-checkout "magit-branch" "\ +Checkout REVISION, updating the index and the working tree. +If REVISION is a local branch, then that becomes the current +branch. If it is something else, then `HEAD' becomes detached. +Checkout fails if the working tree or the staging area contain +changes. + +\(git checkout REVISION). + +\(fn REVISION)" t nil) + +(autoload 'magit-branch-create "magit-branch" "\ +Create BRANCH at branch or revision START-POINT. + +\(fn BRANCH START-POINT)" t nil) + +(autoload 'magit-branch-and-checkout "magit-branch" "\ +Create and checkout BRANCH at branch or revision START-POINT. + +\(fn BRANCH START-POINT)" t nil) + +(autoload 'magit-branch-or-checkout "magit-branch" "\ +Hybrid between `magit-checkout' and `magit-branch-and-checkout'. + +Ask the user for an existing branch or revision. If the user +input actually can be resolved as a branch or revision, then +check that out, just like `magit-checkout' would. + +Otherwise create and checkout a new branch using the input as +its name. Before doing so read the starting-point for the new +branch. This is similar to what `magit-branch-and-checkout' +does. + +\(fn ARG &optional START-POINT)" t nil) + +(autoload 'magit-branch-checkout "magit-branch" "\ +Checkout an existing or new local branch. + +Read a branch name from the user offering all local branches and +a subset of remote branches as candidates. Omit remote branches +for which a local branch by the same name exists from the list +of candidates. The user can also enter a completely new branch +name. + +- If the user selects an existing local branch, then check that + out. + +- If the user selects a remote branch, then create and checkout + a new local branch with the same name. Configure the selected + remote branch as push target. + +- If the user enters a new branch name, then create and check + that out, after also reading the starting-point from the user. + +In the latter two cases the upstream is also set. Whether it is +set to the chosen START-POINT or something else depends on the +value of `magit-branch-adjust-remote-upstream-alist', just like +when using `magit-branch-and-checkout'. + +\(fn BRANCH &optional START-POINT)" t nil) + +(autoload 'magit-branch-orphan "magit-branch" "\ +Create and checkout an orphan BRANCH with contents from revision START-POINT. + +\(fn BRANCH START-POINT)" t nil) + +(autoload 'magit-branch-spinout "magit-branch" "\ +Create new branch from the unpushed commits. +Like `magit-branch-spinoff' but remain on the current branch. +If there are any uncommitted changes, then behave exactly like +`magit-branch-spinoff'. + +\(fn BRANCH &optional FROM)" t nil) + +(autoload 'magit-branch-spinoff "magit-branch" "\ +Create new branch from the unpushed commits. + +Create and checkout a new branch starting at and tracking the +current branch. That branch in turn is reset to the last commit +it shares with its upstream. If the current branch has no +upstream or no unpushed commits, then the new branch is created +anyway and the previously current branch is not touched. + +This is useful to create a feature branch after work has already +began on the old branch (likely but not necessarily \"master\"). + +If the current branch is a member of the value of option +`magit-branch-prefer-remote-upstream' (which see), then the +current branch will be used as the starting point as usual, but +the upstream of the starting-point may be used as the upstream +of the new branch, instead of the starting-point itself. + +If optional FROM is non-nil, then the source branch is reset +to `FROM~', instead of to the last commit it shares with its +upstream. Interactively, FROM is only ever non-nil, if the +region selects some commits, and among those commits, FROM is +the commit that is the fewest commits ahead of the source +branch. + +The commit at the other end of the selection actually does not +matter, all commits between FROM and `HEAD' are moved to the new +branch. If FROM is not reachable from `HEAD' or is reachable +from the source branch's upstream, then an error is raised. + +\(fn BRANCH &optional FROM)" t nil) + +(autoload 'magit-branch-reset "magit-branch" "\ +Reset a branch to the tip of another branch or any other commit. + +When the branch being reset is the current branch, then do a +hard reset. If there are any uncommitted changes, then the user +has to confirm the reset because those changes would be lost. + +This is useful when you have started work on a feature branch but +realize it's all crap and want to start over. + +When resetting to another branch and a prefix argument is used, +then also set the target branch as the upstream of the branch +that is being reset. + +\(fn BRANCH TO &optional SET-UPSTREAM)" t nil) + +(autoload 'magit-branch-delete "magit-branch" "\ +Delete one or multiple branches. +If the region marks multiple branches, then offer to delete +those, otherwise prompt for a single branch to be deleted, +defaulting to the branch at point. + +\(fn BRANCHES &optional FORCE)" t nil) + +(autoload 'magit-branch-rename "magit-branch" "\ +Rename the branch named OLD to NEW. + +With a prefix argument FORCE, rename even if a branch named NEW +already exists. + +If `branch.OLD.pushRemote' is set, then unset it. Depending on +the value of `magit-branch-rename-push-target' (which see) maybe +set `branch.NEW.pushRemote' and maybe rename the push-target on +the remote. + +\(fn OLD NEW &optional FORCE)" t nil) + +(autoload 'magit-branch-shelve "magit-branch" "\ +Shelve a BRANCH. +Rename \"refs/heads/BRANCH\" to \"refs/shelved/BRANCH\", +and also rename the respective reflog file. + +\(fn BRANCH)" t nil) + +(autoload 'magit-branch-unshelve "magit-branch" "\ +Unshelve a BRANCH +Rename \"refs/shelved/BRANCH\" to \"refs/heads/BRANCH\", +and also rename the respective reflog file. + +\(fn BRANCH)" t nil) + (autoload 'magit-branch-configure "magit-branch" nil t) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-branch" '("magit-"))) + +;;;*** + +;;;### (autoloads nil "magit-clone" "magit-clone.el" (0 0 0 0)) +;;; Generated autoloads from magit-clone.el + (autoload 'magit-clone "magit-clone" nil t) + +(autoload 'magit-clone-regular "magit-clone" "\ +Create a clone of REPOSITORY in DIRECTORY. +Then show the status buffer for the new repository. + +\(fn REPOSITORY DIRECTORY ARGS)" t nil) + +(autoload 'magit-clone-shallow "magit-clone" "\ +Create a shallow clone of REPOSITORY in DIRECTORY. +Then show the status buffer for the new repository. +With a prefix argument read the DEPTH of the clone; +otherwise use 1. + +\(fn REPOSITORY DIRECTORY ARGS DEPTH)" t nil) + +(autoload 'magit-clone-shallow-since "magit-clone" "\ +Create a shallow clone of REPOSITORY in DIRECTORY. +Then show the status buffer for the new repository. +Exclude commits before DATE, which is read from the +user. + +\(fn REPOSITORY DIRECTORY ARGS DATE)" t nil) + +(autoload 'magit-clone-shallow-exclude "magit-clone" "\ +Create a shallow clone of REPOSITORY in DIRECTORY. +Then show the status buffer for the new repository. +Exclude commits reachable from EXCLUDE, which is a +branch or tag read from the user. + +\(fn REPOSITORY DIRECTORY ARGS EXCLUDE)" t nil) + +(autoload 'magit-clone-bare "magit-clone" "\ +Create a bare clone of REPOSITORY in DIRECTORY. +Then show the status buffer for the new repository. + +\(fn REPOSITORY DIRECTORY ARGS)" t nil) + +(autoload 'magit-clone-mirror "magit-clone" "\ +Create a mirror of REPOSITORY in DIRECTORY. +Then show the status buffer for the new repository. + +\(fn REPOSITORY DIRECTORY ARGS)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-clone" '("magit-clone"))) + +;;;*** + +;;;### (autoloads nil "magit-commit" "magit-commit.el" (0 0 0 0)) +;;; Generated autoloads from magit-commit.el + (autoload 'magit-commit "magit-commit" nil t) + +(autoload 'magit-commit-create "magit-commit" "\ +Create a new commit on `HEAD'. +With a prefix argument, amend to the commit at `HEAD' instead. + +\(git commit [--amend] ARGS) + +\(fn &optional ARGS)" t nil) + +(autoload 'magit-commit-amend "magit-commit" "\ +Amend the last commit. + +\(git commit --amend ARGS) + +\(fn &optional ARGS)" t nil) + +(autoload 'magit-commit-extend "magit-commit" "\ +Amend the last commit, without editing the message. + +With a prefix argument keep the committer date, otherwise change +it. The option `magit-commit-extend-override-date' can be used +to inverse the meaning of the prefix argument. +\(git commit +--amend --no-edit) + +\(fn &optional ARGS OVERRIDE-DATE)" t nil) + +(autoload 'magit-commit-reword "magit-commit" "\ +Reword the last commit, ignoring staged changes. + +With a prefix argument keep the committer date, otherwise change +it. The option `magit-commit-reword-override-date' can be used +to inverse the meaning of the prefix argument. + +Non-interactively respect the optional OVERRIDE-DATE argument +and ignore the option. + +\(git commit --amend --only) + +\(fn &optional ARGS OVERRIDE-DATE)" t nil) + +(autoload 'magit-commit-fixup "magit-commit" "\ +Create a fixup commit. + +With a prefix argument the target COMMIT has to be confirmed. +Otherwise the commit at point may be used without confirmation +depending on the value of option `magit-commit-squash-confirm'. + +\(fn &optional COMMIT ARGS)" t nil) + +(autoload 'magit-commit-squash "magit-commit" "\ +Create a squash commit, without editing the squash message. + +With a prefix argument the target COMMIT has to be confirmed. +Otherwise the commit at point may be used without confirmation +depending on the value of option `magit-commit-squash-confirm'. + +\(fn &optional COMMIT ARGS)" t nil) + +(autoload 'magit-commit-augment "magit-commit" "\ +Create a squash commit, editing the squash message. + +With a prefix argument the target COMMIT has to be confirmed. +Otherwise the commit at point may be used without confirmation +depending on the value of option `magit-commit-squash-confirm'. + +\(fn &optional COMMIT ARGS)" t nil) + +(autoload 'magit-commit-instant-fixup "magit-commit" "\ +Create a fixup commit targeting COMMIT and instantly rebase. + +\(fn &optional COMMIT ARGS)" t nil) + +(autoload 'magit-commit-instant-squash "magit-commit" "\ +Create a squash commit targeting COMMIT and instantly rebase. + +\(fn &optional COMMIT ARGS)" t nil) + +(autoload 'magit-commit-reshelve "magit-commit" "\ +Change the committer date and possibly the author date of `HEAD'. + +If you are the author of `HEAD', then both dates are changed, +otherwise only the committer date. The current time is used +as the initial minibuffer input and the original author (if +that is you) or committer date is available as the previous +history element. + +\(fn DATE)" t nil) + (autoload 'magit-commit-absorb "magit-commit" nil t) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-commit" '("magit"))) + +;;;*** + +;;;### (autoloads nil "magit-diff" "magit-diff.el" (0 0 0 0)) +;;; Generated autoloads from magit-diff.el + (autoload 'magit-diff "magit-diff" nil t) + (autoload 'magit-diff-refresh "magit-diff" nil t) + +(autoload 'magit-diff-dwim "magit-diff" "\ +Show changes for the thing at point. + +\(fn &optional ARGS FILES)" t nil) + +(autoload 'magit-diff-range "magit-diff" "\ +Show differences between two commits. + +REV-OR-RANGE should be a range or a single revision. If it is a +revision, then show changes in the working tree relative to that +revision. If it is a range, but one side is omitted, then show +changes relative to `HEAD'. + +If the region is active, use the revisions on the first and last +line of the region as the two sides of the range. With a prefix +argument, instead of diffing the revisions, choose a revision to +view changes along, starting at the common ancestor of both +revisions (i.e., use a \"...\" range). + +\(fn REV-OR-RANGE &optional ARGS FILES)" t nil) + +(autoload 'magit-diff-working-tree "magit-diff" "\ +Show changes between the current working tree and the `HEAD' commit. +With a prefix argument show changes between the working tree and +a commit read from the minibuffer. + +\(fn &optional REV ARGS FILES)" t nil) + +(autoload 'magit-diff-staged "magit-diff" "\ +Show changes between the index and the `HEAD' commit. +With a prefix argument show changes between the index and +a commit read from the minibuffer. + +\(fn &optional REV ARGS FILES)" t nil) + +(autoload 'magit-diff-unstaged "magit-diff" "\ +Show changes between the working tree and the index. + +\(fn &optional ARGS FILES)" t nil) + +(autoload 'magit-diff-unmerged "magit-diff" "\ +Show changes that are being merged. + +\(fn &optional ARGS FILES)" t nil) + +(autoload 'magit-diff-while-committing "magit-diff" "\ +While committing, show the changes that are about to be committed. +While amending, invoking the command again toggles between +showing just the new changes or all the changes that will +be committed. + +\(fn &optional ARGS)" t nil) + +(autoload 'magit-diff-buffer-file "magit-diff" "\ +Show diff for the blob or file visited in the current buffer. + +When the buffer visits a blob, then show the respective commit. +When the buffer visits a file, then show the differenced between +`HEAD' and the working tree. In both cases limit the diff to +the file or blob. + +\(fn)" t nil) + +(autoload 'magit-diff-paths "magit-diff" "\ +Show changes between any two files on disk. + +\(fn A B)" t nil) + +(autoload 'magit-show-commit "magit-diff" "\ +Visit the revision at point in another buffer. +If there is no revision at point or with a prefix argument prompt +for a revision. + +\(fn REV &optional ARGS FILES MODULE)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-diff" '("magit"))) + +;;;*** + +;;;### (autoloads nil "magit-ediff" "magit-ediff.el" (0 0 0 0)) +;;; Generated autoloads from magit-ediff.el + (autoload 'magit-ediff "magit-ediff" nil) + +(autoload 'magit-ediff-resolve "magit-ediff" "\ +Resolve outstanding conflicts in FILE using Ediff. +FILE has to be relative to the top directory of the repository. + +In the rare event that you want to manually resolve all +conflicts, including those already resolved by Git, use +`ediff-merge-revisions-with-ancestor'. + +\(fn FILE)" t nil) + +(autoload 'magit-ediff-stage "magit-ediff" "\ +Stage and unstage changes to FILE using Ediff. +FILE has to be relative to the top directory of the repository. + +\(fn FILE)" t nil) + +(autoload 'magit-ediff-compare "magit-ediff" "\ +Compare REVA:FILEA with REVB:FILEB using Ediff. + +FILEA and FILEB have to be relative to the top directory of the +repository. If REVA or REVB is nil, then this stands for the +working tree state. + +If the region is active, use the revisions on the first and last +line of the region. With a prefix argument, instead of diffing +the revisions, choose a revision to view changes along, starting +at the common ancestor of both revisions (i.e., use a \"...\" +range). + +\(fn REVA REVB FILEA FILEB)" t nil) + +(autoload 'magit-ediff-dwim "magit-ediff" "\ +Compare, stage, or resolve using Ediff. +This command tries to guess what file, and what commit or range +the user wants to compare, stage, or resolve using Ediff. It +might only be able to guess either the file, or range or commit, +in which case the user is asked about the other. It might not +always guess right, in which case the appropriate `magit-ediff-*' +command has to be used explicitly. If it cannot read the user's +mind at all, then it asks the user for a command to run. + +\(fn)" t nil) + +(autoload 'magit-ediff-show-staged "magit-ediff" "\ +Show staged changes using Ediff. + +This only allows looking at the changes; to stage, unstage, +and discard changes using Ediff, use `magit-ediff-stage'. + +FILE must be relative to the top directory of the repository. + +\(fn FILE)" t nil) + +(autoload 'magit-ediff-show-unstaged "magit-ediff" "\ +Show unstaged changes using Ediff. + +This only allows looking at the changes; to stage, unstage, +and discard changes using Ediff, use `magit-ediff-stage'. + +FILE must be relative to the top directory of the repository. + +\(fn FILE)" t nil) + +(autoload 'magit-ediff-show-working-tree "magit-ediff" "\ +Show changes between `HEAD' and working tree using Ediff. +FILE must be relative to the top directory of the repository. + +\(fn FILE)" t nil) + +(autoload 'magit-ediff-show-commit "magit-ediff" "\ +Show changes introduced by COMMIT using Ediff. + +\(fn COMMIT)" t nil) + +(autoload 'magit-ediff-show-stash "magit-ediff" "\ +Show changes introduced by STASH using Ediff. +`magit-ediff-show-stash-with-index' controls whether a +three-buffer Ediff is used in order to distinguish changes in the +stash that were staged. + +\(fn STASH)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-ediff" '("magit-ediff"))) + +;;;*** + +;;;### (autoloads nil "magit-extras" "magit-extras.el" (0 0 0 0)) +;;; Generated autoloads from magit-extras.el + +(autoload 'magit-run-git-gui "magit-extras" "\ +Run `git gui' for the current git repository. + +\(fn)" t nil) + +(autoload 'magit-run-git-gui-blame "magit-extras" "\ +Run `git gui blame' on the given FILENAME and COMMIT. +Interactively run it for the current file and the `HEAD', with a +prefix or when the current file cannot be determined let the user +choose. When the current buffer is visiting FILENAME instruct +blame to center around the line point is on. + +\(fn COMMIT FILENAME &optional LINENUM)" t nil) + +(autoload 'magit-run-gitk "magit-extras" "\ +Run `gitk' in the current repository. + +\(fn)" t nil) + +(autoload 'magit-run-gitk-branches "magit-extras" "\ +Run `gitk --branches' in the current repository. + +\(fn)" t nil) + +(autoload 'magit-run-gitk-all "magit-extras" "\ +Run `gitk --all' in the current repository. + +\(fn)" t nil) + +(autoload 'ido-enter-magit-status "magit-extras" "\ +Drop into `magit-status' from file switching. + +This command does not work in Emacs 26.1. +See https://github.com/magit/magit/issues/3634 +and https://debbugs.gnu.org/cgi/bugreport.cgi?bug=31707. + +To make this command available use something like: + + (add-hook \\='ido-setup-hook + (lambda () + (define-key ido-completion-map + (kbd \"C-x g\") \\='ido-enter-magit-status))) + +Starting with Emacs 25.1 the Ido keymaps are defined just once +instead of every time Ido is invoked, so now you can modify it +like pretty much every other keymap: + + (define-key ido-common-completion-map + (kbd \"C-x g\") \\='ido-enter-magit-status) + +\(fn)" t nil) + +(autoload 'magit-dired-jump "magit-extras" "\ +Visit file at point using Dired. +With a prefix argument, visit in another window. If there +is no file at point, then instead visit `default-directory'. + +\(fn &optional OTHER-WINDOW)" t nil) + +(autoload 'magit-dired-log "magit-extras" "\ +Show log for all marked files, or the current file. + +\(fn &optional FOLLOW)" t nil) + +(autoload 'magit-do-async-shell-command "magit-extras" "\ +Open FILE with `dired-do-async-shell-command'. +Interactively, open the file at point. + +\(fn FILE)" t nil) + +(autoload 'magit-previous-line "magit-extras" "\ +Like `previous-line' but with Magit-specific shift-selection. + +Magit's selection mechanism is based on the region but selects an +area that is larger than the region. This causes `previous-line' +when invoked while holding the shift key to move up one line and +thereby select two lines. When invoked inside a hunk body this +command does not move point on the first invocation and thereby +it only selects a single line. Which inconsistency you prefer +is a matter of preference. + +\(fn &optional ARG TRY-VSCROLL)" t nil) + +(function-put 'magit-previous-line 'interactive-only '"use `forward-line' with negative argument instead.") + +(autoload 'magit-next-line "magit-extras" "\ +Like `next-line' but with Magit-specific shift-selection. + +Magit's selection mechanism is based on the region but selects +an area that is larger than the region. This causes `next-line' +when invoked while holding the shift key to move down one line +and thereby select two lines. When invoked inside a hunk body +this command does not move point on the first invocation and +thereby it only selects a single line. Which inconsistency you +prefer is a matter of preference. + +\(fn &optional ARG TRY-VSCROLL)" t nil) + +(function-put 'magit-next-line 'interactive-only 'forward-line) + +(autoload 'magit-clean "magit-extras" "\ +Remove untracked files from the working tree. +With a prefix argument also remove ignored files, +with two prefix arguments remove ignored files only. + +\(git clean -f -d [-x|-X]) + +\(fn &optional ARG)" t nil) + +(autoload 'magit-add-change-log-entry "magit-extras" "\ +Find change log file and add date entry and item for current change. +This differs from `add-change-log-entry' (which see) in that +it acts on the current hunk in a Magit buffer instead of on +a position in a file-visiting buffer. + +\(fn &optional WHOAMI FILE-NAME OTHER-WINDOW)" t nil) + +(autoload 'magit-add-change-log-entry-other-window "magit-extras" "\ +Find change log file in other window and add entry and item. +This differs from `add-change-log-entry-other-window' (which see) +in that it acts on the current hunk in a Magit buffer instead of +on a position in a file-visiting buffer. + +\(fn &optional WHOAMI FILE-NAME)" t nil) + +(autoload 'magit-edit-line-commit "magit-extras" "\ +Edit the commit that added the current line. + +With a prefix argument edit the commit that removes the line, +if any. The commit is determined using `git blame' and made +editable using `git rebase --interactive' if it is reachable +from `HEAD', or by checking out the commit (or a branch that +points at it) otherwise. + +\(fn &optional TYPE)" t nil) + +(autoload 'magit-diff-edit-hunk-commit "magit-extras" "\ +From a hunk, edit the respective commit and visit the file. + +First visit the file being modified by the hunk at the correct +location using `magit-diff-visit-file'. This actually visits a +blob. When point is on a diff header, not within an individual +hunk, then this visits the blob the first hunk is about. + +Then invoke `magit-edit-line-commit', which uses an interactive +rebase to make the commit editable, or if that is not possible +because the commit is not reachable from `HEAD' by checking out +that commit directly. This also causes the actual worktree file +to be visited. + +Neither the blob nor the file buffer are killed when finishing +the rebase. If that is undesirable, then it might be better to +use `magit-rebase-edit-command' instead of this command. + +\(fn FILE)" t nil) + +(autoload 'magit-reshelve-since "magit-extras" "\ +Change the author and committer dates of the commits since REV. + +Ask the user for the first reachable commit whose dates should +be changed. Then read the new date for that commit. The initial +minibuffer input and the previous history element offer good +values. The next commit will be created one minute later and so +on. + +This command is only intended for interactive use and should only +be used on highly rearranged and unpublished history. + +\(fn REV)" t nil) + +(autoload 'magit-pop-revision-stack "magit-extras" "\ +Insert a representation of a revision into the current buffer. + +Pop a revision from the `magit-revision-stack' and insert it into +the current buffer according to `magit-pop-revision-stack-format'. +Revisions can be put on the stack using `magit-copy-section-value' +and `magit-copy-buffer-revision'. + +If the stack is empty or with a prefix argument, instead read a +revision in the minibuffer. By using the minibuffer history this +allows selecting an item which was popped earlier or to insert an +arbitrary reference or revision without first pushing it onto the +stack. + +When reading the revision from the minibuffer, then it might not +be possible to guess the correct repository. When this command +is called inside a repository (e.g. while composing a commit +message), then that repository is used. Otherwise (e.g. while +composing an email) then the repository recorded for the top +element of the stack is used (even though we insert another +revision). If not called inside a repository and with an empty +stack, or with two prefix arguments, then read the repository in +the minibuffer too. + +\(fn REV TOPLEVEL)" t nil) + +(autoload 'magit-copy-section-value "magit-extras" "\ +Save the value of the current section for later use. + +Save the section value to the `kill-ring', and, provided that +the current section is a commit, branch, or tag section, push +the (referenced) revision to the `magit-revision-stack' for use +with `magit-pop-revision-stack'. + +When the current section is a branch or a tag, and a prefix +argument is used, then save the revision at its tip to the +`kill-ring' instead of the reference name. + +When the region is active, then save that to the `kill-ring', +like `kill-ring-save' would, instead of behaving as described +above. If a prefix argument is used and the region is within a +hunk, strip the outer diff marker column. + +\(fn)" t nil) + +(autoload 'magit-copy-buffer-revision "magit-extras" "\ +Save the revision of the current buffer for later use. + +Save the revision shown in the current buffer to the `kill-ring' +and push it to the `magit-revision-stack'. + +This command is mainly intended for use in `magit-revision-mode' +buffers, the only buffers where it is always unambiguous exactly +which revision should be saved. + +Most other Magit buffers usually show more than one revision, in +some way or another, so this command has to select one of them, +and that choice might not always be the one you think would have +been the best pick. + +In such buffers it is often more useful to save the value of +the current section instead, using `magit-copy-section-value'. + +When the region is active, then save that to the `kill-ring', +like `kill-ring-save' would, instead of behaving as described +above. + +\(fn)" t nil) + +(autoload 'magit-abort-dwim "magit-extras" "\ +Abort current operation. +Depending on the context, this will abort a merge, a rebase, a +patch application, a cherry-pick, a revert, or a bisect. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-extras" '("magit-"))) + +;;;*** + +;;;### (autoloads nil "magit-fetch" "magit-fetch.el" (0 0 0 0)) +;;; Generated autoloads from magit-fetch.el + (autoload 'magit-fetch "magit-fetch" nil t) + (autoload 'magit-fetch-from-pushremote "magit-fetch" nil t) + (autoload 'magit-fetch-from-upstream "magit-fetch" nil t) + +(autoload 'magit-fetch-other "magit-fetch" "\ +Fetch from another repository. + +\(fn REMOTE ARGS)" t nil) + +(autoload 'magit-fetch-branch "magit-fetch" "\ +Fetch a BRANCH from a REMOTE. + +\(fn REMOTE BRANCH ARGS)" t nil) + +(autoload 'magit-fetch-refspec "magit-fetch" "\ +Fetch a REFSPEC from a REMOTE. + +\(fn REMOTE REFSPEC ARGS)" t nil) + +(autoload 'magit-fetch-all "magit-fetch" "\ +Fetch from all remotes. + +\(fn ARGS)" t nil) + +(autoload 'magit-fetch-all-prune "magit-fetch" "\ +Fetch from all remotes, and prune. +Prune remote tracking branches for branches that have been +removed on the respective remote. + +\(fn)" t nil) + +(autoload 'magit-fetch-all-no-prune "magit-fetch" "\ +Fetch from all remotes. + +\(fn)" t nil) + +(autoload 'magit-fetch-modules "magit-fetch" "\ +Fetch all submodules. + +Option `magit-fetch-modules-jobs' controls how many submodules +are being fetched in parallel. Also fetch the super-repository, +because `git-fetch' does not support not doing that. With a +prefix argument fetch all remotes. + +\(fn &optional ALL)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-fetch" '("magit-"))) + +;;;*** + +;;;### (autoloads nil "magit-files" "magit-files.el" (0 0 0 0)) +;;; Generated autoloads from magit-files.el + +(autoload 'magit-find-file "magit-files" "\ +View FILE from REV. +Switch to a buffer visiting blob REV:FILE, creating one if none +already exists. If prior to calling this command the current +buffer and/or cursor position is about the same file, then go +to the line and column corresponding to that location. + +\(fn REV FILE)" t nil) + +(autoload 'magit-find-file-other-window "magit-files" "\ +View FILE from REV, in another window. +Switch to a buffer visiting blob REV:FILE, creating one if none +already exists. If prior to calling this command the current +buffer and/or cursor position is about the same file, then go to +the line and column corresponding to that location. + +\(fn REV FILE)" t nil) + +(autoload 'magit-find-file-other-frame "magit-files" "\ +View FILE from REV, in another frame. +Switch to a buffer visiting blob REV:FILE, creating one if none +already exists. If prior to calling this command the current +buffer and/or cursor position is about the same file, then go to +the line and column corresponding to that location. + +\(fn REV FILE)" t nil) + (autoload 'magit-file-dispatch "magit" nil t) + +(defvar global-magit-file-mode t "\ +Non-nil if Global Magit-File mode is enabled. +See the `global-magit-file-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `global-magit-file-mode'.") + +(custom-autoload 'global-magit-file-mode "magit-files" nil) + +(autoload 'global-magit-file-mode "magit-files" "\ +Toggle Magit-File mode in all buffers. +With prefix ARG, enable Global Magit-File mode if ARG is positive; +otherwise, disable it. If called from Lisp, enable the mode if +ARG is omitted or nil. + +Magit-File mode is enabled in all buffers where +`magit-file-mode-turn-on' would do it. +See `magit-file-mode' for more information on Magit-File mode. + +\(fn &optional ARG)" t nil) + +(autoload 'magit-blob-visit-file "magit-files" "\ +View the file from the worktree corresponding to the current blob. +When visiting a blob or the version from the index, then go to +the same location in the respective file in the working tree. + +\(fn)" t nil) + +(autoload 'magit-file-checkout "magit-files" "\ +Checkout FILE from REV. + +\(fn REV FILE)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-files" '("magit-"))) + +;;;*** + +;;;### (autoloads nil "magit-git" "magit-git.el" (0 0 0 0)) +;;; Generated autoloads from magit-git.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-git" '("magit-"))) + +;;;*** + +;;;### (autoloads nil "magit-gitignore" "magit-gitignore.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from magit-gitignore.el + (autoload 'magit-gitignore "magit-gitignore" nil t) + +(autoload 'magit-gitignore-in-topdir "magit-gitignore" "\ +Add the Git ignore RULE to the top-level \".gitignore\" file. +Since this file is tracked, it is shared with other clones of the +repository. Also stage the file. + +\(fn RULE)" t nil) + +(autoload 'magit-gitignore-in-subdir "magit-gitignore" "\ +Add the Git ignore RULE to a \".gitignore\" file. +Prompted the user for a directory and add the rule to the +\".gitignore\" file in that directory. Since such files are +tracked, they are shared with other clones of the repository. +Also stage the file. + +\(fn RULE DIRECTORY)" t nil) + +(autoload 'magit-gitignore-in-gitdir "magit-gitignore" "\ +Add the Git ignore RULE to \"$GIT_DIR/info/exclude\". +Rules in that file only affects this clone of the repository. + +\(fn RULE)" t nil) + +(autoload 'magit-gitignore-on-system "magit-gitignore" "\ +Add the Git ignore RULE to the file specified by `core.excludesFile'. +Rules that are defined in that file affect all local repositories. + +\(fn RULE)" t nil) + +(autoload 'magit-skip-worktree "magit-gitignore" "\ +Call \"git update-index --skip-worktree -- FILE\". + +\(fn FILE)" t nil) + +(autoload 'magit-no-skip-worktree "magit-gitignore" "\ +Call \"git update-index --no-skip-worktree -- FILE\". + +\(fn FILE)" t nil) + +(autoload 'magit-assume-unchanged "magit-gitignore" "\ +Call \"git update-index --assume-unchanged -- FILE\". + +\(fn FILE)" t nil) + +(autoload 'magit-no-assume-unchanged "magit-gitignore" "\ +Call \"git update-index --no-assume-unchanged -- FILE\". + +\(fn FILE)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-gitignore" '("magit-"))) + +;;;*** + +;;;### (autoloads nil "magit-imenu" "magit-imenu.el" (0 0 0 0)) +;;; Generated autoloads from magit-imenu.el + +(autoload 'magit-imenu--log-prev-index-position-function "magit-imenu" "\ +Move point to previous line in current buffer. +This function is used as a value for +`imenu-prev-index-position-function'. + +\(fn)" nil nil) + +(autoload 'magit-imenu--log-extract-index-name-function "magit-imenu" "\ +Return imenu name for line at point. +This function is used as a value for +`imenu-extract-index-name-function'. Point should be at the +beginning of the line. + +\(fn)" nil nil) + +(autoload 'magit-imenu--diff-prev-index-position-function "magit-imenu" "\ +Move point to previous file line in current buffer. +This function is used as a value for +`imenu-prev-index-position-function'. + +\(fn)" nil nil) + +(autoload 'magit-imenu--diff-extract-index-name-function "magit-imenu" "\ +Return imenu name for line at point. +This function is used as a value for +`imenu-extract-index-name-function'. Point should be at the +beginning of the line. + +\(fn)" nil nil) + +(autoload 'magit-imenu--status-create-index-function "magit-imenu" "\ +Return an alist of all imenu entries in current buffer. +This function is used as a value for +`imenu-create-index-function'. + +\(fn)" nil nil) + +(autoload 'magit-imenu--refs-create-index-function "magit-imenu" "\ +Return an alist of all imenu entries in current buffer. +This function is used as a value for +`imenu-create-index-function'. + +\(fn)" nil nil) + +(autoload 'magit-imenu--cherry-create-index-function "magit-imenu" "\ +Return an alist of all imenu entries in current buffer. +This function is used as a value for +`imenu-create-index-function'. + +\(fn)" nil nil) + +(autoload 'magit-imenu--submodule-prev-index-position-function "magit-imenu" "\ +Move point to previous line in magit-submodule-list buffer. +This function is used as a value for +`imenu-prev-index-position-function'. + +\(fn)" nil nil) + +(autoload 'magit-imenu--submodule-extract-index-name-function "magit-imenu" "\ +Return imenu name for line at point. +This function is used as a value for +`imenu-extract-index-name-function'. Point should be at the +beginning of the line. + +\(fn)" nil nil) + +(autoload 'magit-imenu--repolist-prev-index-position-function "magit-imenu" "\ +Move point to previous line in magit-repolist buffer. +This function is used as a value for +`imenu-prev-index-position-function'. + +\(fn)" nil nil) + +(autoload 'magit-imenu--repolist-extract-index-name-function "magit-imenu" "\ +Return imenu name for line at point. +This function is used as a value for +`imenu-extract-index-name-function'. Point should be at the +beginning of the line. + +\(fn)" nil nil) + +(autoload 'magit-imenu--process-prev-index-position-function "magit-imenu" "\ +Move point to previous process in magit-process buffer. +This function is used as a value for +`imenu-prev-index-position-function'. + +\(fn)" nil nil) + +(autoload 'magit-imenu--process-extract-index-name-function "magit-imenu" "\ +Return imenu name for line at point. +This function is used as a value for +`imenu-extract-index-name-function'. Point should be at the +beginning of the line. + +\(fn)" nil nil) + +(autoload 'magit-imenu--rebase-prev-index-position-function "magit-imenu" "\ +Move point to previous commit in git-rebase buffer. +This function is used as a value for +`imenu-prev-index-position-function'. + +\(fn)" nil nil) + +(autoload 'magit-imenu--rebase-extract-index-name-function "magit-imenu" "\ +Return imenu name for line at point. +This function is used as a value for +`imenu-extract-index-name-function'. Point should be at the +beginning of the line. + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-imenu" '("magit-imenu--index-function"))) + +;;;*** + +;;;### (autoloads nil "magit-log" "magit-log.el" (0 0 0 0)) +;;; Generated autoloads from magit-log.el + (autoload 'magit-log "magit-log" nil t) + (autoload 'magit-log-refresh "magit-log" nil t) + +(autoload 'magit-log-current "magit-log" "\ +Show log for the current branch. +When `HEAD' is detached or with a prefix argument show log for +one or more revs read from the minibuffer. + +\(fn REVS &optional ARGS FILES)" t nil) + +(autoload 'magit-log-other "magit-log" "\ +Show log for one or more revs read from the minibuffer. +The user can input any revision or revisions separated by a +space, or even ranges, but only branches and tags, and a +representation of the commit at point, are available as +completion candidates. + +\(fn REVS &optional ARGS FILES)" t nil) + +(autoload 'magit-log-head "magit-log" "\ +Show log for `HEAD'. + +\(fn &optional ARGS FILES)" t nil) + +(autoload 'magit-log-branches "magit-log" "\ +Show log for all local branches and `HEAD'. + +\(fn &optional ARGS FILES)" t nil) + +(autoload 'magit-log-matching-branches "magit-log" "\ +Show log for all branches matching PATTERN and `HEAD'. + +\(fn PATTERN &optional ARGS FILES)" t nil) + +(autoload 'magit-log-matching-tags "magit-log" "\ +Show log for all tags matching PATTERN and `HEAD'. + +\(fn PATTERN &optional ARGS FILES)" t nil) + +(autoload 'magit-log-all-branches "magit-log" "\ +Show log for all local and remote branches and `HEAD'. + +\(fn &optional ARGS FILES)" t nil) + +(autoload 'magit-log-all "magit-log" "\ +Show log for all references and `HEAD'. + +\(fn &optional ARGS FILES)" t nil) + +(autoload 'magit-log-buffer-file "magit-log" "\ +Show log for the blob or file visited in the current buffer. +With a prefix argument or when `--follow' is an active log +argument, then follow renames. When the region is active, +restrict the log to the lines that the region touches. + +\(fn &optional FOLLOW BEG END)" t nil) + +(autoload 'magit-log-trace-definition "magit-log" "\ +Show log for the definition at point. + +\(fn FILE FN REV)" t nil) + +(autoload 'magit-log-merged "magit-log" "\ +Show log for the merge of COMMIT into BRANCH. + +More precisely, find merge commit M that brought COMMIT into +BRANCH, and show the log of the range \"M^1..M\". If COMMIT is +directly on BRANCH, then show approximately twenty surrounding +commits instead. + +This command requires git-when-merged, which is available from +https://github.com/mhagger/git-when-merged. + +\(fn COMMIT BRANCH &optional ARGS FILES)" t nil) + +(autoload 'magit-log-move-to-parent "magit-log" "\ +Move to the Nth parent of the current commit. + +\(fn &optional N)" t nil) + +(autoload 'magit-cherry "magit-log" "\ +Show commits in a branch that are not merged in the upstream branch. + +\(fn HEAD UPSTREAM)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-log" '("magit"))) + +;;;*** + +;;;### (autoloads nil "magit-margin" "magit-margin.el" (0 0 0 0)) +;;; Generated autoloads from magit-margin.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-margin" '("magit-"))) + +;;;*** + +;;;### (autoloads nil "magit-merge" "magit-merge.el" (0 0 0 0)) +;;; Generated autoloads from magit-merge.el + (autoload 'magit-merge "magit" nil t) + +(autoload 'magit-merge-plain "magit-merge" "\ +Merge commit REV into the current branch; using default message. + +Unless there are conflicts or a prefix argument is used create a +merge commit using a generic commit message and without letting +the user inspect the result. With a prefix argument pretend the +merge failed to give the user the opportunity to inspect the +merge. + +\(git merge --no-edit|--no-commit [ARGS] REV) + +\(fn REV &optional ARGS NOCOMMIT)" t nil) + +(autoload 'magit-merge-editmsg "magit-merge" "\ +Merge commit REV into the current branch; and edit message. +Perform the merge and prepare a commit message but let the user +edit it. + +\(git merge --edit --no-ff [ARGS] REV) + +\(fn REV &optional ARGS)" t nil) + +(autoload 'magit-merge-nocommit "magit-merge" "\ +Merge commit REV into the current branch; pretending it failed. +Pretend the merge failed to give the user the opportunity to +inspect the merge and change the commit message. + +\(git merge --no-commit --no-ff [ARGS] REV) + +\(fn REV &optional ARGS)" t nil) + +(autoload 'magit-merge-into "magit-merge" "\ +Merge the current branch into BRANCH and remove the former. + +Before merging, force push the source branch to its push-remote, +provided the respective remote branch already exists, ensuring +that the respective pull-request (if any) won't get stuck on some +obsolete version of the commits that are being merged. Finally +if `forge-branch-pullreq' was used to create the merged branch, +branch, then also remove the respective remote branch. + +\(fn BRANCH &optional ARGS)" t nil) + +(autoload 'magit-merge-absorb "magit-merge" "\ +Merge BRANCH into the current branch and remove the former. + +Before merging, force push the source branch to its push-remote, +provided the respective remote branch already exists, ensuring +that the respective pull-request (if any) won't get stuck on some +obsolete version of the commits that are being merged. Finally +if `forge-branch-pullreq' was used to create the merged branch, +then also remove the respective remote branch. + +\(fn BRANCH &optional ARGS)" t nil) + +(autoload 'magit-merge-squash "magit-merge" "\ +Squash commit REV into the current branch; don't create a commit. + +\(git merge --squash REV) + +\(fn REV)" t nil) + +(autoload 'magit-merge-preview "magit-merge" "\ +Preview result of merging REV into the current branch. + +\(fn REV)" t nil) + +(autoload 'magit-merge-abort "magit-merge" "\ +Abort the current merge operation. + +\(git merge --abort) + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-merge" '("magit-"))) + +;;;*** + +;;;### (autoloads nil "magit-mode" "magit-mode.el" (0 0 0 0)) +;;; Generated autoloads from magit-mode.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-mode" '("magit-" "disable-magit-save-buffers" "inhibit-magit-refresh"))) + +;;;*** + +;;;### (autoloads nil "magit-notes" "magit-notes.el" (0 0 0 0)) +;;; Generated autoloads from magit-notes.el + (autoload 'magit-notes "magit" nil t) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-notes" '("magit-"))) + +;;;*** + +;;;### (autoloads nil "magit-obsolete" "magit-obsolete.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from magit-obsolete.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-obsolete" '("magit--magit-popup-warning"))) + +;;;*** + +;;;### (autoloads nil "magit-patch" "magit-patch.el" (0 0 0 0)) +;;; Generated autoloads from magit-patch.el + (autoload 'magit-patch "magit-patch" nil t) + (autoload 'magit-patch-create "magit-patch" nil t) + (autoload 'magit-patch-apply "magit-patch" nil t) + +(autoload 'magit-patch-save "magit-patch" "\ +Write current diff into patch FILE. + +What arguments are used to create the patch depends on the value +of `magit-patch-save-arguments' and whether a prefix argument is +used. + +If the value is the symbol `buffer', then use the same arguments +as the buffer. With a prefix argument use no arguments. + +If the value is a list beginning with the symbol `exclude', then +use the same arguments as the buffer except for those matched by +entries in the cdr of the list. The comparison is done using +`string-prefix-p'. With a prefix argument use the same arguments +as the buffer. + +If the value is a list of strings (including the empty list), +then use those arguments. With a prefix argument use the same +arguments as the buffer. + +Of course the arguments that are required to actually show the +same differences as those shown in the buffer are always used. + +\(fn FILE &optional ARG)" t nil) + +(autoload 'magit-request-pull "magit-patch" "\ +Request upstream to pull from you public repository. + +URL is the url of your publicly accessible repository. +START is a commit that already is in the upstream repository. +END is the last commit, usually a branch name, which upstream +is asked to pull. START has to be reachable from that commit. + +\(fn URL START END)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-patch" '("magit-"))) + +;;;*** + +;;;### (autoloads nil "magit-process" "magit-process.el" (0 0 0 0)) +;;; Generated autoloads from magit-process.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-process" '("magit-" "tramp-sh-handle-"))) + +;;;*** + +;;;### (autoloads nil "magit-pull" "magit-pull.el" (0 0 0 0)) +;;; Generated autoloads from magit-pull.el + (autoload 'magit-pull "magit-pull" nil t) + (autoload 'magit-pull-from-pushremote "magit-pull" nil t) + (autoload 'magit-pull-from-upstream "magit-pull" nil t) + +(autoload 'magit-pull-branch "magit-pull" "\ +Pull from a branch read in the minibuffer. + +\(fn SOURCE ARGS)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-pull" '("magit-pull"))) + +;;;*** + +;;;### (autoloads nil "magit-push" "magit-push.el" (0 0 0 0)) +;;; Generated autoloads from magit-push.el + (autoload 'magit-push "magit-push" nil t) + (autoload 'magit-push-current-to-pushremote "magit-push" nil t) + (autoload 'magit-push-current-to-upstream "magit-push" nil t) + +(autoload 'magit-push-current "magit-push" "\ +Push the current branch to a branch read in the minibuffer. + +\(fn TARGET ARGS)" t nil) + +(autoload 'magit-push-other "magit-push" "\ +Push an arbitrary branch or commit somewhere. +Both the source and the target are read in the minibuffer. + +\(fn SOURCE TARGET ARGS)" t nil) + +(autoload 'magit-push-refspecs "magit-push" "\ +Push one or multiple REFSPECS to a REMOTE. +Both the REMOTE and the REFSPECS are read in the minibuffer. To +use multiple REFSPECS, separate them with commas. Completion is +only available for the part before the colon, or when no colon +is used. + +\(fn REMOTE REFSPECS ARGS)" t nil) + +(autoload 'magit-push-matching "magit-push" "\ +Push all matching branches to another repository. +If multiple remotes exist, then read one from the user. +If just one exists, use that without requiring confirmation. + +\(fn REMOTE &optional ARGS)" t nil) + +(autoload 'magit-push-tags "magit-push" "\ +Push all tags to another repository. +If only one remote exists, then push to that. Otherwise prompt +for a remote, offering the remote configured for the current +branch as default. + +\(fn REMOTE &optional ARGS)" t nil) + +(autoload 'magit-push-tag "magit-push" "\ +Push a tag to another repository. + +\(fn TAG REMOTE &optional ARGS)" t nil) + +(autoload 'magit-push-implicitly "magit-push" "\ +Push somewhere without using an explicit refspec. + +This command simply runs \"git push -v [ARGS]\". ARGS are the +arguments specified in the popup buffer. No explicit refspec +arguments are used. Instead the behavior depends on at least +these Git variables: `push.default', `remote.pushDefault', +`branch..pushRemote', `branch..remote', +`branch..merge', and `remote..push'. + +The function `magit-push-implicitly--desc' attempts to predict +what this command will do. The value it returns is displayed in +the popup buffer. + +\(fn ARGS)" t nil) + +(autoload 'magit-push-to-remote "magit-push" "\ +Push to REMOTE without using an explicit refspec. +The REMOTE is read in the minibuffer. + +This command simply runs \"git push -v [ARGS] REMOTE\". ARGS +are the arguments specified in the popup buffer. No refspec +arguments are used. Instead the behavior depends on at least +these Git variables: `push.default', `remote.pushDefault', +`branch..pushRemote', `branch..remote', +`branch..merge', and `remote..push'. + +\(fn REMOTE ARGS)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-push" '("magit-"))) + +;;;*** + +;;;### (autoloads nil "magit-reflog" "magit-reflog.el" (0 0 0 0)) +;;; Generated autoloads from magit-reflog.el + +(autoload 'magit-reflog-current "magit-reflog" "\ +Display the reflog of the current branch. +If `HEAD' is detached, then show the reflog for that instead. + +\(fn)" t nil) + +(autoload 'magit-reflog-other "magit-reflog" "\ +Display the reflog of a branch or another ref. + +\(fn REF)" t nil) + +(autoload 'magit-reflog-head "magit-reflog" "\ +Display the `HEAD' reflog. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-reflog" '("magit-reflog-"))) + +;;;*** + +;;;### (autoloads nil "magit-refs" "magit-refs.el" (0 0 0 0)) +;;; Generated autoloads from magit-refs.el + (autoload 'magit-show-refs "magit-refs" nil t) + +(autoload 'magit-show-refs-head "magit-refs" "\ +List and compare references in a dedicated buffer. +Compared with `HEAD'. + +\(fn &optional ARGS)" t nil) + +(autoload 'magit-show-refs-current "magit-refs" "\ +List and compare references in a dedicated buffer. +Compare with the current branch or `HEAD' if it is detached. + +\(fn &optional ARGS)" t nil) + +(autoload 'magit-show-refs-other "magit-refs" "\ +List and compare references in a dedicated buffer. +Compared with a branch read from the user. + +\(fn &optional REF ARGS)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-refs" '("magit-"))) + +;;;*** + +;;;### (autoloads nil "magit-remote" "magit-remote.el" (0 0 0 0)) +;;; Generated autoloads from magit-remote.el + (autoload 'magit-remote "magit-remote" nil t) + +(autoload 'magit-remote-add "magit-remote" "\ +Add a remote named REMOTE and fetch it. + +\(fn REMOTE URL &optional ARGS)" t nil) + +(autoload 'magit-remote-rename "magit-remote" "\ +Rename the remote named OLD to NEW. + +\(fn OLD NEW)" t nil) + +(autoload 'magit-remote-remove "magit-remote" "\ +Delete the remote named REMOTE. + +\(fn REMOTE)" t nil) + +(autoload 'magit-remote-prune "magit-remote" "\ +Remove stale remote-tracking branches for REMOTE. + +\(fn REMOTE)" t nil) + +(autoload 'magit-remote-prune-refspecs "magit-remote" "\ +Remove stale refspecs for REMOTE. + +A refspec is stale if there no longer exists at least one branch +on the remote that would be fetched due to that refspec. A stale +refspec is problematic because its existence causes Git to refuse +to fetch according to the remaining non-stale refspecs. + +If only stale refspecs remain, then offer to either delete the +remote or to replace the stale refspecs with the default refspec. + +Also remove the remote-tracking branches that were created due to +the now stale refspecs. Other stale branches are not removed. + +\(fn REMOTE)" t nil) + +(autoload 'magit-remote-set-head "magit-remote" "\ +Set the local representation of REMOTE's default branch. +Query REMOTE and set the symbolic-ref refs/remotes//HEAD +accordingly. With a prefix argument query for the branch to be +used, which allows you to select an incorrect value if you fancy +doing that. + +\(fn REMOTE &optional BRANCH)" t nil) + +(autoload 'magit-remote-unset-head "magit-remote" "\ +Unset the local representation of REMOTE's default branch. +Delete the symbolic-ref \"refs/remotes//HEAD\". + +\(fn REMOTE)" t nil) + (autoload 'magit-remote-configure "magit-remote" nil t) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-remote" '("magit-"))) + +;;;*** + +;;;### (autoloads nil "magit-repos" "magit-repos.el" (0 0 0 0)) +;;; Generated autoloads from magit-repos.el + +(autoload 'magit-list-repositories "magit-repos" "\ +Display a list of repositories. + +Use the options `magit-repository-directories' to control which +repositories are displayed. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-repos" '("magit-"))) + +;;;*** + +;;;### (autoloads nil "magit-reset" "magit-reset.el" (0 0 0 0)) +;;; Generated autoloads from magit-reset.el + (autoload 'magit-reset "magit" nil t) + +(autoload 'magit-reset-mixed "magit-reset" "\ +Reset the `HEAD' and index to COMMIT, but not the working tree. + +\(git reset --mixed COMMIT) + +\(fn COMMIT)" t nil) + +(autoload 'magit-reset-soft "magit-reset" "\ +Reset the `HEAD' to COMMIT, but not the index and working tree. + +\(git reset --soft REVISION) + +\(fn COMMIT)" t nil) + +(autoload 'magit-reset-hard "magit-reset" "\ +Reset the `HEAD', index, and working tree to COMMIT. + +\(git reset --hard REVISION) + +\(fn COMMIT)" t nil) + +(autoload 'magit-reset-index "magit-reset" "\ +Reset the index to COMMIT. +Keep the `HEAD' and working tree as-is, so if COMMIT refers to the +head this effectively unstages all changes. + +\(git reset COMMIT .) + +\(fn COMMIT)" t nil) + +(autoload 'magit-reset-worktree "magit-reset" "\ +Reset the worktree to COMMIT. +Keep the `HEAD' and index as-is. + +\(fn COMMIT)" t nil) + +(autoload 'magit-reset-quickly "magit-reset" "\ +Reset the `HEAD' and index to COMMIT, and possibly the working tree. +With a prefix argument reset the working tree otherwise don't. + +\(git reset --mixed|--hard COMMIT) + +\(fn COMMIT &optional HARD)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-reset" '("magit-reset"))) + +;;;*** + +;;;### (autoloads nil "magit-section" "magit-section.el" (0 0 0 0)) +;;; Generated autoloads from magit-section.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-section" '("magit-"))) + +;;;*** + +;;;### (autoloads nil "magit-sequence" "magit-sequence.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from magit-sequence.el + +(autoload 'magit-sequencer-continue "magit-sequence" "\ +Resume the current cherry-pick or revert sequence. + +\(fn)" t nil) + +(autoload 'magit-sequencer-skip "magit-sequence" "\ +Skip the stopped at commit during a cherry-pick or revert sequence. + +\(fn)" t nil) + +(autoload 'magit-sequencer-abort "magit-sequence" "\ +Abort the current cherry-pick or revert sequence. +This discards all changes made since the sequence started. + +\(fn)" t nil) + (autoload 'magit-cherry-pick "magit-sequence" nil t) + +(autoload 'magit-cherry-copy "magit-sequence" "\ +Copy COMMITS from another branch onto the current branch. +Prompt for a commit, defaulting to the commit at point. If +the region selects multiple commits, then pick all of them, +without prompting. + +\(fn COMMITS &optional ARGS)" t nil) + +(autoload 'magit-cherry-apply "magit-sequence" "\ +Apply the changes in COMMITS but do not commit them. +Prompt for a commit, defaulting to the commit at point. If +the region selects multiple commits, then apply all of them, +without prompting. + +\(fn COMMITS &optional ARGS)" t nil) + +(autoload 'magit-cherry-harvest "magit-sequence" "\ +Move COMMITS from another BRANCH onto the current branch. +Remove the COMMITS from BRANCH and stay on the current branch. +If a conflict occurs, then you have to fix that and finish the +process manually. + +\(fn COMMITS BRANCH &optional ARGS)" t nil) + +(autoload 'magit-cherry-donate "magit-sequence" "\ +Move COMMITS from the current branch onto another existing BRANCH. +Remove COMMITS from the current branch and stay on that branch. +If a conflict occurs, then you have to fix that and finish the +process manually. + +\(fn COMMITS BRANCH &optional ARGS)" t nil) + +(autoload 'magit-cherry-spinout "magit-sequence" "\ +Move COMMITS from the current branch onto a new BRANCH. +Remove COMMITS from the current branch and stay on that branch. +If a conflict occurs, then you have to fix that and finish the +process manually. + +\(fn COMMITS BRANCH START-POINT &optional ARGS)" t nil) + +(autoload 'magit-cherry-spinoff "magit-sequence" "\ +Move COMMITS from the current branch onto a new BRANCH. +Remove COMMITS from the current branch and checkout BRANCH. +If a conflict occurs, then you have to fix that and finish +the process manually. + +\(fn COMMITS BRANCH START-POINT &optional ARGS)" t nil) + (autoload 'magit-revert "magit-sequence" nil t) + +(autoload 'magit-revert-and-commit "magit-sequence" "\ +Revert COMMIT by creating a new commit. +Prompt for a commit, defaulting to the commit at point. If +the region selects multiple commits, then revert all of them, +without prompting. + +\(fn COMMIT &optional ARGS)" t nil) + +(autoload 'magit-revert-no-commit "magit-sequence" "\ +Revert COMMIT by applying it in reverse to the worktree. +Prompt for a commit, defaulting to the commit at point. If +the region selects multiple commits, then revert all of them, +without prompting. + +\(fn COMMIT &optional ARGS)" t nil) + (autoload 'magit-am "magit-sequence" nil t) + +(autoload 'magit-am-apply-patches "magit-sequence" "\ +Apply the patches FILES. + +\(fn &optional FILES ARGS)" t nil) + +(autoload 'magit-am-apply-maildir "magit-sequence" "\ +Apply the patches from MAILDIR. + +\(fn &optional MAILDIR ARGS)" t nil) + +(autoload 'magit-am-continue "magit-sequence" "\ +Resume the current patch applying sequence. + +\(fn)" t nil) + +(autoload 'magit-am-skip "magit-sequence" "\ +Skip the stopped at patch during a patch applying sequence. + +\(fn)" t nil) + +(autoload 'magit-am-abort "magit-sequence" "\ +Abort the current patch applying sequence. +This discards all changes made since the sequence started. + +\(fn)" t nil) + (autoload 'magit-rebase "magit-sequence" nil t) + (autoload 'magit-rebase-onto-pushremote "magit-sequence" nil t) + (autoload 'magit-rebase-onto-upstream "magit-sequence" nil t) + +(autoload 'magit-rebase-branch "magit-sequence" "\ +Rebase the current branch onto a branch read in the minibuffer. +All commits that are reachable from `HEAD' but not from the +selected branch TARGET are being rebased. + +\(fn TARGET ARGS)" t nil) + +(autoload 'magit-rebase-subset "magit-sequence" "\ +Rebase a subset of the current branch's history onto a new base. +Rebase commits from START to `HEAD' onto NEWBASE. +START has to be selected from a list of recent commits. + +\(fn NEWBASE START ARGS)" t nil) + +(autoload 'magit-rebase-interactive "magit-sequence" "\ +Start an interactive rebase sequence. + +\(fn COMMIT ARGS)" t nil) + +(autoload 'magit-rebase-autosquash "magit-sequence" "\ +Combine squash and fixup commits with their intended targets. + +\(fn ARGS)" t nil) + +(autoload 'magit-rebase-edit-commit "magit-sequence" "\ +Edit a single older commit using rebase. + +\(fn COMMIT ARGS)" t nil) + +(autoload 'magit-rebase-reword-commit "magit-sequence" "\ +Reword a single older commit using rebase. + +\(fn COMMIT ARGS)" t nil) + +(autoload 'magit-rebase-remove-commit "magit-sequence" "\ +Remove a single older commit using rebase. + +\(fn COMMIT ARGS)" t nil) + +(autoload 'magit-rebase-continue "magit-sequence" "\ +Restart the current rebasing operation. +In some cases this pops up a commit message buffer for you do +edit. With a prefix argument the old message is reused as-is. + +\(fn &optional NOEDIT)" t nil) + +(autoload 'magit-rebase-skip "magit-sequence" "\ +Skip the current commit and restart the current rebase operation. + +\(fn)" t nil) + +(autoload 'magit-rebase-edit "magit-sequence" "\ +Edit the todo list of the current rebase operation. + +\(fn)" t nil) + +(autoload 'magit-rebase-abort "magit-sequence" "\ +Abort the current rebase operation, restoring the original branch. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-sequence" '("magit-"))) + +;;;*** + +;;;### (autoloads nil "magit-stash" "magit-stash.el" (0 0 0 0)) +;;; Generated autoloads from magit-stash.el + (autoload 'magit-stash "magit-stash" nil t) + +(autoload 'magit-stash-both "magit-stash" "\ +Create a stash of the index and working tree. +Untracked files are included according to infix arguments. +One prefix argument is equivalent to `--include-untracked' +while two prefix arguments are equivalent to `--all'. + +\(fn MESSAGE &optional INCLUDE-UNTRACKED)" t nil) + +(autoload 'magit-stash-index "magit-stash" "\ +Create a stash of the index only. +Unstaged and untracked changes are not stashed. The stashed +changes are applied in reverse to both the index and the +worktree. This command can fail when the worktree is not clean. +Applying the resulting stash has the inverse effect. + +\(fn MESSAGE)" t nil) + +(autoload 'magit-stash-worktree "magit-stash" "\ +Create a stash of unstaged changes in the working tree. +Untracked files are included according to infix arguments. +One prefix argument is equivalent to `--include-untracked' +while two prefix arguments are equivalent to `--all'. + +\(fn MESSAGE &optional INCLUDE-UNTRACKED)" t nil) + +(autoload 'magit-stash-keep-index "magit-stash" "\ +Create a stash of the index and working tree, keeping index intact. +Untracked files are included according to infix arguments. +One prefix argument is equivalent to `--include-untracked' +while two prefix arguments are equivalent to `--all'. + +\(fn MESSAGE &optional INCLUDE-UNTRACKED)" t nil) + +(autoload 'magit-snapshot-both "magit-stash" "\ +Create a snapshot of the index and working tree. +Untracked files are included according to infix arguments. +One prefix argument is equivalent to `--include-untracked' +while two prefix arguments are equivalent to `--all'. + +\(fn &optional INCLUDE-UNTRACKED)" t nil) + +(autoload 'magit-snapshot-index "magit-stash" "\ +Create a snapshot of the index only. +Unstaged and untracked changes are not stashed. + +\(fn)" t nil) + +(autoload 'magit-snapshot-worktree "magit-stash" "\ +Create a snapshot of unstaged changes in the working tree. +Untracked files are included according to infix arguments. +One prefix argument is equivalent to `--include-untracked' +while two prefix arguments are equivalent to `--all'. + +\(fn &optional INCLUDE-UNTRACKED)" t nil) + +(autoload 'magit-stash-apply "magit-stash" "\ +Apply a stash to the working tree. +Try to preserve the stash index. If that fails because there +are staged changes, apply without preserving the stash index. + +\(fn STASH)" t nil) + +(autoload 'magit-stash-drop "magit-stash" "\ +Remove a stash from the stash list. +When the region is active offer to drop all contained stashes. + +\(fn STASH)" t nil) + +(autoload 'magit-stash-clear "magit-stash" "\ +Remove all stashes saved in REF's reflog by deleting REF. + +\(fn REF)" t nil) + +(autoload 'magit-stash-branch "magit-stash" "\ +Create and checkout a new BRANCH from STASH. + +\(fn STASH BRANCH)" t nil) + +(autoload 'magit-stash-branch-here "magit-stash" "\ +Create and checkout a new BRANCH and apply STASH. +The branch is created using `magit-branch-and-checkout', using the +current branch or `HEAD' as the start-point. + +\(fn STASH BRANCH)" t nil) + +(autoload 'magit-stash-format-patch "magit-stash" "\ +Create a patch from STASH + +\(fn STASH)" t nil) + +(autoload 'magit-stash-list "magit-stash" "\ +List all stashes in a buffer. + +\(fn)" t nil) + +(autoload 'magit-stash-show "magit-stash" "\ +Show all diffs of a stash in a buffer. + +\(fn STASH &optional ARGS FILES)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-stash" '("magit-"))) + +;;;*** + +;;;### (autoloads nil "magit-status" "magit-status.el" (0 0 0 0)) +;;; Generated autoloads from magit-status.el + +(autoload 'magit-init "magit-status" "\ +Initialize a Git repository, then show its status. + +If the directory is below an existing repository, then the user +has to confirm that a new one should be created inside. If the +directory is the root of the existing repository, then the user +has to confirm that it should be reinitialized. + +Non-interactively DIRECTORY is (re-)initialized unconditionally. + +\(fn DIRECTORY)" t nil) + +(autoload 'magit-status "magit-status" "\ +Show the status of the current Git repository in a buffer. + +If the current directory isn't located within a Git repository, +then prompt for an existing repository or an arbitrary directory, +depending on option `magit-repository-directories', and show the +status of the selected repository instead. + +* If that option specifies any existing repositories, then offer + those for completion and show the status buffer for the + selected one. + +* Otherwise read an arbitrary directory using regular file-name + completion. If the selected directory is the top-level of an + existing working tree, then show the status buffer for that. + +* Otherwise offer to initialize the selected directory as a new + repository. After creating the repository show its status + buffer. + +These fallback behaviors can also be forced using one or more +prefix arguments: + +* With two prefix arguments (or more precisely a numeric prefix + value of 16 or greater) read an arbitrary directory and act on + it as described above. The same could be accomplished using + the command `magit-init'. + +* With a single prefix argument read an existing repository, or + if none can be found based on `magit-repository-directories', + then fall back to the same behavior as with two prefix + arguments. + +\(fn &optional DIRECTORY CACHE)" t nil) + +(defalias 'magit 'magit-status "\ +An alias for `magit-status' for better discoverability. + +Instead of invoking this alias for `magit-status' using +\"M-x magit RET\", you should bind a key to `magit-status' +and read the info node `(magit)Getting Started', which +also contains other useful hints.") + +(autoload 'magit-status-here "magit-status" "\ +Like `magit-status' but with non-nil `magit-status-goto-file-position'. + +\(fn)" t nil) + +(autoload 'magit-status-setup-buffer "magit-status" "\ + + +\(fn &optional DIRECTORY)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-status" '("magit-"))) + +;;;*** + +;;;### (autoloads nil "magit-submodule" "magit-submodule.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from magit-submodule.el + (autoload 'magit-submodule "magit-submodule" nil t) + (autoload 'magit-submodule-add "magit-submodule" nil t) + +(autoload 'magit-submodule-read-name-for-path "magit-submodule" "\ + + +\(fn PATH &optional PREFER-SHORT)" nil nil) + (autoload 'magit-submodule-register "magit-submodule" nil t) + (autoload 'magit-submodule-populate "magit-submodule" nil t) + (autoload 'magit-submodule-update "magit-submodule" nil t) + (autoload 'magit-submodule-synchronize "magit-submodule" nil t) + (autoload 'magit-submodule-unpopulate "magit-submodule" nil t) + +(autoload 'magit-submodule-remove "magit-submodule" "\ +Unregister MODULES and remove their working directories. + +For safety reasons, do not remove the gitdirs and if a module has +uncomitted changes, then do not remove it at all. If a module's +gitdir is located inside the working directory, then move it into +the gitdir of the superproject first. + +With the \"--force\" argument offer to remove dirty working +directories and with a prefix argument offer to delete gitdirs. +Both actions are very dangerous and have to be confirmed. There +are additional safety precautions in place, so you might be able +to recover from making a mistake here, but don't count on it. + +\(fn MODULES ARGS TRASH-GITDIRS)" t nil) + +(autoload 'magit-insert-modules "magit-submodule" "\ +Insert submodule sections. +Hook `magit-module-sections-hook' controls which module sections +are inserted, and option `magit-module-sections-nested' controls +whether they are wrapped in an additional section. + +\(fn)" nil nil) + +(autoload 'magit-insert-modules-overview "magit-submodule" "\ +Insert sections for all modules. +For each section insert the path and the output of `git describe --tags', +or, failing that, the abbreviated HEAD commit hash. + +\(fn)" nil nil) + +(autoload 'magit-insert-modules-unpulled-from-upstream "magit-submodule" "\ +Insert sections for modules that haven't been pulled from the upstream. +These sections can be expanded to show the respective commits. + +\(fn)" nil nil) + +(autoload 'magit-insert-modules-unpulled-from-pushremote "magit-submodule" "\ +Insert sections for modules that haven't been pulled from the push-remote. +These sections can be expanded to show the respective commits. + +\(fn)" nil nil) + +(autoload 'magit-insert-modules-unpushed-to-upstream "magit-submodule" "\ +Insert sections for modules that haven't been pushed to the upstream. +These sections can be expanded to show the respective commits. + +\(fn)" nil nil) + +(autoload 'magit-insert-modules-unpushed-to-pushremote "magit-submodule" "\ +Insert sections for modules that haven't been pushed to the push-remote. +These sections can be expanded to show the respective commits. + +\(fn)" nil nil) + +(autoload 'magit-list-submodules "magit-submodule" "\ +Display a list of the current repository's submodules. + +\(fn)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-submodule" '("magit-"))) + +;;;*** + +;;;### (autoloads nil "magit-subtree" "magit-subtree.el" (0 0 0 0)) +;;; Generated autoloads from magit-subtree.el + (autoload 'magit-subtree "magit-subtree" nil t) + (autoload 'magit-subtree-import "magit-subtree" nil t) + (autoload 'magit-subtree-export "magit-subtree" nil t) + +(autoload 'magit-subtree-add "magit-subtree" "\ +Add REF from REPOSITORY as a new subtree at PREFIX. + +\(fn PREFIX REPOSITORY REF ARGS)" t nil) + +(autoload 'magit-subtree-add-commit "magit-subtree" "\ +Add COMMIT as a new subtree at PREFIX. + +\(fn PREFIX COMMIT ARGS)" t nil) + +(autoload 'magit-subtree-merge "magit-subtree" "\ +Merge COMMIT into the PREFIX subtree. + +\(fn PREFIX COMMIT ARGS)" t nil) + +(autoload 'magit-subtree-pull "magit-subtree" "\ +Pull REF from REPOSITORY into the PREFIX subtree. + +\(fn PREFIX REPOSITORY REF ARGS)" t nil) + +(autoload 'magit-subtree-push "magit-subtree" "\ +Extract the history of the subtree PREFIX and push it to REF on REPOSITORY. + +\(fn PREFIX REPOSITORY REF ARGS)" t nil) + +(autoload 'magit-subtree-split "magit-subtree" "\ +Extract the history of the subtree PREFIX. + +\(fn PREFIX COMMIT ARGS)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-subtree" '("magit-"))) + +;;;*** + +;;;### (autoloads nil "magit-tag" "magit-tag.el" (0 0 0 0)) +;;; Generated autoloads from magit-tag.el + (autoload 'magit-tag "magit" nil t) + +(autoload 'magit-tag-create "magit-tag" "\ +Create a new tag with the given NAME at REV. +With a prefix argument annotate the tag. + +\(git tag [--annotate] NAME REV) + +\(fn NAME REV &optional ARGS)" t nil) + +(autoload 'magit-tag-delete "magit-tag" "\ +Delete one or more tags. +If the region marks multiple tags (and nothing else), then offer +to delete those, otherwise prompt for a single tag to be deleted, +defaulting to the tag at point. + +\(git tag -d TAGS) + +\(fn TAGS)" t nil) + +(autoload 'magit-tag-prune "magit-tag" "\ +Offer to delete tags missing locally from REMOTE, and vice versa. + +\(fn TAGS REMOTE-TAGS REMOTE)" t nil) + +(autoload 'magit-tag-release "magit-tag" "\ +Create an annotated release tag. + +Assume that release tags match `magit-release-tag-regexp'. + +First prompt for the name of the new tag using the highest +existing tag as initial input and leaving it to the user to +increment the desired part of the version string. + +Then prompt for the message of the new tag. Base the proposed +tag message on the message of the highest tag, provided that +that contains the corresponding version string and substituting +the new version string for that. Otherwise propose something +like \"Foo-Bar 1.2.3\", given, for example, a TAG \"v1.2.3\" and a +repository located at something like \"/path/to/foo-bar\". + +Then call \"git tag --annotate --sign -m MSG TAG\" to create the, +tag, regardless of whether these arguments are enabled in the +popup. Finally show the refs buffer to let the user quickly +review the result. + +\(fn TAG MSG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-tag" '("magit-"))) + +;;;*** + +;;;### (autoloads nil "magit-transient" "magit-transient.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from magit-transient.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-transient" '("magit-"))) + +;;;*** + +;;;### (autoloads nil "magit-utils" "magit-utils.el" (0 0 0 0)) +;;; Generated autoloads from magit-utils.el + +(autoload 'magit-emacs-Q-command "magit-utils" "\ +Show a shell command that runs an uncustomized Emacs with only Magit loaded. +See info node `(magit)Debugging Tools' for more information. + +\(fn)" t nil) + +(autoload 'Info-follow-nearest-node--magit-gitman "magit-utils" "\ + + +\(fn FN &optional FORK)" nil nil) + +(advice-add 'Info-follow-nearest-node :around 'Info-follow-nearest-node--magit-gitman) + +(autoload 'org-man-export--magit-gitman "magit-utils" "\ + + +\(fn FN LINK DESCRIPTION FORMAT)" nil nil) + +(advice-add 'org-man-export :around 'org-man-export--magit-gitman) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-utils" '("magit-"))) + +;;;*** + +;;;### (autoloads nil "magit-wip" "magit-wip.el" (0 0 0 0)) +;;; Generated autoloads from magit-wip.el + +(defvar magit-wip-after-save-mode nil "\ +Non-nil if Magit-Wip-After-Save mode is enabled. +See the `magit-wip-after-save-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `magit-wip-after-save-mode'.") + +(custom-autoload 'magit-wip-after-save-mode "magit-wip" nil) + +(autoload 'magit-wip-after-save-mode "magit-wip" "\ +Toggle Magit-Wip-After-Save-Local mode in all buffers. +With prefix ARG, enable Magit-Wip-After-Save mode if ARG is positive; +otherwise, disable it. If called from Lisp, enable the mode if +ARG is omitted or nil. + +Magit-Wip-After-Save-Local mode is enabled in all buffers where +`magit-wip-after-save-local-mode-turn-on' would do it. +See `magit-wip-after-save-local-mode' for more information on Magit-Wip-After-Save-Local mode. + +\(fn &optional ARG)" t nil) + +(defvar magit-wip-after-apply-mode nil "\ +Non-nil if Magit-Wip-After-Apply mode is enabled. +See the `magit-wip-after-apply-mode' command +for a description of this minor mode.") + +(custom-autoload 'magit-wip-after-apply-mode "magit-wip" nil) + +(autoload 'magit-wip-after-apply-mode "magit-wip" "\ +Commit to work-in-progress refs. + +After applying a change using any \"apply variant\" +command (apply, stage, unstage, discard, and reverse) commit the +affected files to the current wip refs. For each branch there +may be two wip refs; one contains snapshots of the files as found +in the worktree and the other contains snapshots of the entries +in the index. + +\(fn &optional ARG)" t nil) + +(defvar magit-wip-before-change-mode nil "\ +Non-nil if Magit-Wip-Before-Change mode is enabled. +See the `magit-wip-before-change-mode' command +for a description of this minor mode.") + +(custom-autoload 'magit-wip-before-change-mode "magit-wip" nil) + +(autoload 'magit-wip-before-change-mode "magit-wip" "\ +Commit to work-in-progress refs before certain destructive changes. + +Before invoking a revert command or an \"apply variant\" +command (apply, stage, unstage, discard, and reverse) commit the +affected tracked files to the current wip refs. For each branch +there may be two wip refs; one contains snapshots of the files +as found in the worktree and the other contains snapshots of the +entries in the index. + +Only changes to files which could potentially be affected by the +command which is about to be called are committed. + +\(fn &optional ARG)" t nil) + +(autoload 'magit-wip-commit-initial-backup "magit-wip" "\ +Before saving, commit current file to a worktree wip ref. + +The user has to add this function to `before-save-hook'. + +Commit the current state of the visited file before saving the +current buffer to that file. This backs up the same version of +the file as `backup-buffer' would, but stores the backup in the +worktree wip ref, which is also used by the various Magit Wip +modes, instead of in a backup file as `backup-buffer' would. + +This function ignores the variables that affect `backup-buffer' +and can be used along-side that function, which is recommended +because this function only backs up files that are tracked in +a Git repository. + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-wip" '("magit-"))) + +;;;*** + +;;;### (autoloads nil "magit-worktree" "magit-worktree.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from magit-worktree.el + (autoload 'magit-worktree "magit-worktree" nil t) + +(autoload 'magit-worktree-checkout "magit-worktree" "\ +Checkout BRANCH in a new worktree at PATH. + +\(fn PATH BRANCH)" t nil) + +(autoload 'magit-worktree-branch "magit-worktree" "\ +Create a new BRANCH and check it out in a new worktree at PATH. + +\(fn PATH BRANCH START-POINT &optional FORCE)" t nil) + +(autoload 'magit-worktree-move "magit-worktree" "\ +Move WORKTREE to PATH. + +\(fn WORKTREE PATH)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "magit-worktree" '("magit-"))) + +;;;*** + +;;;### (autoloads nil nil ("magit-core.el" "magit-pkg.el") (0 0 0 +;;;;;; 0)) + +;;;*** + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; coding: utf-8 +;; End: +;;; magit-autoloads.el ends here diff --git a/elpa/magit-20191122.2040/magit-autorevert.el b/elpa/magit-20191122.2040/magit-autorevert.el new file mode 100644 index 00000000..215864c4 --- /dev/null +++ b/elpa/magit-20191122.2040/magit-autorevert.el @@ -0,0 +1,258 @@ +;;; magit-autorevert.el --- revert buffers when files in repository change -*- lexical-binding: t -*- + +;; Copyright (C) 2010-2019 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Code: + +(require 'cl-lib) +(require 'dash) + +(require 'magit-git) + +(require 'autorevert) + +;;; Options + +(defgroup magit-auto-revert nil + "Revert buffers when files in repository change." + :link '(custom-group-link auto-revert) + :link '(info-link "(magit)Automatic Reverting of File-Visiting Buffers") + :group 'auto-revert + :group 'magit-essentials + :group 'magit-modes) + +(defcustom auto-revert-buffer-list-filter nil + "Filter that determines which buffers `auto-revert-buffers' reverts. + +This option is provided by Magit, which also advises +`auto-revert-buffers' to respect it. Magit users who do not turn +on the local mode `auto-revert-mode' themselves, are best served +by setting the value to `magit-auto-revert-repository-buffer-p'. + +However the default is nil, so as not to disturb users who do use +the local mode directly. If you experience delays when running +Magit commands, then you should consider using one of the +predicates provided by Magit - especially if you also use Tramp. + +Users who do turn on `auto-revert-mode' in buffers in which Magit +doesn't do that for them, should likely not use any filter. +Users who turn on `global-auto-revert-mode', do not have to worry +about this option, because it is disregarded if the global mode +is enabled." + :package-version '(magit . "2.4.2") + :group 'auto-revert + :group 'magit-auto-revert + :group 'magit-related + :type '(radio (const :tag "No filter" nil) + (function-item magit-auto-revert-buffer-p) + (function-item magit-auto-revert-repository-buffer-p) + function)) + +(defcustom magit-auto-revert-tracked-only t + "Whether `magit-auto-revert-mode' only reverts tracked files." + :package-version '(magit . "2.4.0") + :group 'magit-auto-revert + :type 'boolean + :set (lambda (var val) + (set var val) + (when (and (bound-and-true-p magit-auto-revert-mode) + (featurep 'magit-autorevert)) + (magit-auto-revert-mode -1) + (magit-auto-revert-mode)))) + +(defcustom magit-auto-revert-immediately t + "Whether Magit reverts buffers immediately. + +If this is non-nil and either `global-auto-revert-mode' or +`magit-auto-revert-mode' is enabled, then Magit immediately +reverts buffers by explicitly calling `auto-revert-buffers' +after running Git for side-effects. + +If `auto-revert-use-notify' is non-nil (and file notifications +are actually supported), then `magit-auto-revert-immediately' +does not have to be non-nil, because the reverts happen +immediately anyway. + +If `magit-auto-revert-immediately' and `auto-revert-use-notify' +are both nil, then reverts happen after `auto-revert-interval' +seconds of user inactivity. That is not desirable." + :package-version '(magit . "2.4.0") + :group 'magit-auto-revert + :type 'boolean) + +;;; Mode + +(defun magit-turn-on-auto-revert-mode-if-desired (&optional file) + (if file + (--when-let (find-buffer-visiting file) + (with-current-buffer it + (magit-turn-on-auto-revert-mode-if-desired))) + (when (and buffer-file-name + (file-readable-p buffer-file-name) + (magit-toplevel) + (or (not magit-auto-revert-tracked-only) + (magit-file-tracked-p buffer-file-name)) + (not auto-revert-mode) ; see #3014 + (not global-auto-revert-mode)) ; see #3460 + (auto-revert-mode 1)))) + +;;;###autoload +(define-globalized-minor-mode magit-auto-revert-mode auto-revert-mode + magit-turn-on-auto-revert-mode-if-desired + :package-version '(magit . "2.4.0") + :link '(info-link "(magit)Automatic Reverting of File-Visiting Buffers") + :group 'magit-auto-revert + :group 'magit-essentials + ;; - When `global-auto-revert-mode' is enabled, then this mode is + ;; redundant. + ;; - In all other cases enable the mode because if buffers are not + ;; automatically reverted that would make many very common tasks + ;; much more cumbersome. + :init-value (not (or global-auto-revert-mode + noninteractive))) +;; - Unfortunately `:init-value t' only sets the value of the mode +;; variable but does not cause the mode function to be called. +;; - I don't think it works like this on purpose, but since one usually +;; should not enable global modes by default, it is understandable. +;; - If the user has set the variable `magit-auto-revert-mode' to nil +;; after loading magit (instead of doing so before loading magit or +;; by using the function), then we should still respect that setting. +;; - If the user sets one of these variables after loading magit and +;; after `after-init-hook' has run, then that won't have an effect +;; and there is nothing we can do about it. +(defun magit-auto-revert-mode--init-kludge () + "This is an internal kludge to be used on `after-init-hook'. +Do not use this function elsewhere, and don't remove it from +the `after-init-hook'. For more information see the comments +and code surrounding the definition of this function." + (if magit-auto-revert-mode + (let ((start (current-time))) + (magit-message "Turning on magit-auto-revert-mode...") + (magit-auto-revert-mode 1) + (magit-message + "Turning on magit-auto-revert-mode...done%s" + (let ((elapsed (float-time (time-subtract nil start)))) + (if (> elapsed 0.2) + (format " (%.3fs, %s buffers checked)" elapsed + (length (buffer-list))) + "")))) + (magit-auto-revert-mode -1))) +(if after-init-time + ;; Since `after-init-hook' has already been + ;; run, turn the mode on or off right now. + (magit-auto-revert-mode--init-kludge) + ;; By the time the init file has been fully loaded the + ;; values of the relevant variables might have changed. + (add-hook 'after-init-hook #'magit-auto-revert-mode--init-kludge t)) + +(put 'magit-auto-revert-mode 'function-documentation + "Toggle Magit Auto Revert mode. +If called interactively, enable Magit Auto Revert mode if ARG is +positive, and disable it if ARG is zero or negative. If called +from Lisp, also enable the mode if ARG is omitted or nil, and +toggle it if ARG is `toggle'; disable the mode otherwise. + +Magit Auto Revert mode is a global minor mode that reverts +buffers associated with a file that is located inside a Git +repository when the file changes on disk. Use `auto-revert-mode' +to revert a particular buffer. Or use `global-auto-revert-mode' +to revert all file-visiting buffers, not just those that visit +a file located inside a Git repository. + +This global mode works by turning on the buffer-local mode +`auto-revert-mode' at the time a buffer is first created. The +local mode is turned on if the visited file is being tracked in +a Git repository at the time when the buffer is created. + +If `magit-auto-revert-tracked-only' is non-nil (the default), +then only tracked files are reverted. But if you stage a +previously untracked file using `magit-stage', then this mode +notices that. + +Unlike `global-auto-revert-mode', this mode never reverts any +buffers that are not visiting files. + +The behavior of this mode can be customized using the options +in the `autorevert' and `magit-autorevert' groups. + +This function calls the hook `magit-auto-revert-mode-hook'.") + +(defun magit-auto-revert-buffers () + (when (and magit-auto-revert-immediately + (or global-auto-revert-mode + (and magit-auto-revert-mode auto-revert-buffer-list))) + (let ((auto-revert-buffer-list-filter + (or auto-revert-buffer-list-filter + #'magit-auto-revert-repository-buffer-p))) + (auto-revert-buffers)))) + +(defvar magit-auto-revert-toplevel nil) + +(defvar magit-auto-revert-counter 1 + "Incremented each time `auto-revert-buffers' is called.") + +(defun magit-auto-revert-buffer-p (buffer) + "Return non-nil if BUFFER visits a file inside the current repository. +The current repository is the one containing `default-directory'. +If there is no current repository, then return t for any BUFFER." + (magit-auto-revert-repository-buffer-p buffer t)) + +(defun magit-auto-revert-repository-buffer-p (buffer &optional fallback) + "Return non-nil if BUFFER visits a file inside the current repository. +The current repository is the one containing `default-directory'. +If there is no current repository, then return FALLBACK (which +defaults to nil) for any BUFFER." + ;; Call `magit-toplevel' just once per cycle. + (unless (and magit-auto-revert-toplevel + (= (cdr magit-auto-revert-toplevel) + magit-auto-revert-counter)) + (setq magit-auto-revert-toplevel + (cons (or (magit-toplevel) 'no-repo) + magit-auto-revert-counter))) + (let ((top (car magit-auto-revert-toplevel))) + (if (eq top 'no-repo) + fallback + (let ((dir (buffer-local-value 'default-directory buffer))) + (and (equal (file-remote-p dir) + (file-remote-p top)) + ;; ^ `tramp-handle-file-in-directory-p' lacks this optimization. + (file-in-directory-p dir top)))))) + +(defun auto-revert-buffers--buffer-list-filter (fn) + (cl-incf magit-auto-revert-counter) + (if (or global-auto-revert-mode + (not auto-revert-buffer-list) + (not auto-revert-buffer-list-filter)) + (funcall fn) + (let ((auto-revert-buffer-list + (-filter auto-revert-buffer-list-filter + auto-revert-buffer-list))) + (funcall fn)) + (unless auto-revert-timer + (auto-revert-set-timer)))) + +(advice-add 'auto-revert-buffers :around + 'auto-revert-buffers--buffer-list-filter) + +;;; _ +(provide 'magit-autorevert) +;;; magit-autorevert.el ends here diff --git a/elpa/magit-20191122.2040/magit-autorevert.elc b/elpa/magit-20191122.2040/magit-autorevert.elc new file mode 100644 index 0000000000000000000000000000000000000000..6d7b889d412ff406c8155b98eabce29a923ddbd4 GIT binary patch literal 12107 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 literal 0 HcmV?d00001 diff --git a/elpa/magit-20191122.2040/magit-bisect.el b/elpa/magit-20191122.2040/magit-bisect.el new file mode 100644 index 00000000..3e54c1c2 --- /dev/null +++ b/elpa/magit-20191122.2040/magit-bisect.el @@ -0,0 +1,239 @@ +;;; magit-bisect.el --- bisect support for Magit -*- lexical-binding: t -*- + +;; Copyright (C) 2011-2019 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; Use a binary search to find the commit that introduced a bug. + +;;; Code: + +(require 'magit) + +;;; Options + +(defcustom magit-bisect-show-graph t + "Whether to use `--graph' in the log showing commits yet to be bisected." + :package-version '(magit . "2.8.0") + :group 'magit-status + :type 'boolean) + +(defface magit-bisect-good + '((t :foreground "DarkOliveGreen")) + "Face for good bisect revisions." + :group 'magit-faces) + +(defface magit-bisect-skip + '((t :foreground "DarkGoldenrod")) + "Face for skipped bisect revisions." + :group 'magit-faces) + +(defface magit-bisect-bad + '((t :foreground "IndianRed4")) + "Face for bad bisect revisions." + :group 'magit-faces) + +;;; Commands + +;;;###autoload (autoload 'magit-bisect "magit-bisect" nil t) +(define-transient-command magit-bisect () + "Narrow in on the commit that introduced a bug." + :man-page "git-bisect" + ["Actions" + :if-not magit-bisect-in-progress-p + ("B" "Start" magit-bisect-start) + ("s" "Start script" magit-bisect-run)] + ["Actions" + :if magit-bisect-in-progress-p + ("B" "Bad" magit-bisect-bad) + ("g" "Good" magit-bisect-good) + ("k" "Skip" magit-bisect-skip) + ("r" "Reset" magit-bisect-reset) + ("s" "Run script" magit-bisect-run)]) + +;;;###autoload +(defun magit-bisect-start (bad good) + "Start a bisect session. + +Bisecting a bug means to find the commit that introduced it. +This command starts such a bisect session by asking for a know +good and a bad commit. To move the session forward use the +other actions from the bisect transient command (\ +\\\\[magit-bisect])." + (interactive (if (magit-bisect-in-progress-p) + (user-error "Already bisecting") + (magit-bisect-start-read-args))) + (unless (magit-rev-ancestor-p good bad) + (user-error + "The good revision (%s) has to be an ancestor of the bad one (%s)" + good bad)) + (when (magit-anything-modified-p) + (user-error "Cannot bisect with uncommitted changes")) + (magit-git-bisect "start" (list bad good) t)) + +(defun magit-bisect-start-read-args () + (let ((b (magit-read-branch-or-commit "Start bisect with bad revision"))) + (list b (magit-read-other-branch-or-commit "Good revision" b)))) + +;;;###autoload +(defun magit-bisect-reset () + "After bisecting, cleanup bisection state and return to original `HEAD'." + (interactive) + (magit-confirm 'reset-bisect) + (magit-run-git "bisect" "reset") + (ignore-errors (delete-file (magit-git-dir "BISECT_CMD_OUTPUT")))) + +;;;###autoload +(defun magit-bisect-good () + "While bisecting, mark the current commit as good. +Use this after you have asserted that the commit does not contain +the bug in question." + (interactive) + (magit-git-bisect "good")) + +;;;###autoload +(defun magit-bisect-bad () + "While bisecting, mark the current commit as bad. +Use this after you have asserted that the commit does contain the +bug in question." + (interactive) + (magit-git-bisect "bad")) + +;;;###autoload +(defun magit-bisect-skip () + "While bisecting, skip the current commit. +Use this if for some reason the current commit is not a good one +to test. This command lets Git choose a different one." + (interactive) + (magit-git-bisect "skip")) + +;;;###autoload +(defun magit-bisect-run (cmdline &optional bad good) + "Bisect automatically by running commands after each step. + +Unlike `git bisect run' this can be used before bisecting has +begun. In that case it behaves like `git bisect start; git +bisect run'." + (interactive (let ((args (and (not (magit-bisect-in-progress-p)) + (magit-bisect-start-read-args)))) + (cons (read-shell-command "Bisect shell command: ") args))) + (when (and bad good) + (magit-bisect-start bad good)) + (magit-git-bisect "run" (list shell-file-name shell-command-switch cmdline))) + +(defun magit-git-bisect (subcommand &optional args no-assert) + (unless (or no-assert (magit-bisect-in-progress-p)) + (user-error "Not bisecting")) + (message "Bisecting...") + (magit-with-toplevel + (magit-run-git-async "bisect" subcommand args)) + (set-process-sentinel + magit-this-process + (lambda (process event) + (when (memq (process-status process) '(exit signal)) + (if (> (process-exit-status process) 0) + (magit-process-sentinel process event) + (process-put process 'inhibit-refresh t) + (magit-process-sentinel process event) + (when (buffer-live-p (process-buffer process)) + (with-current-buffer (process-buffer process) + (when-let ((section (get-text-property (point) 'magit-section)) + (output (buffer-substring-no-properties + (oref section content) + (oref section end)))) + (with-temp-file (magit-git-dir "BISECT_CMD_OUTPUT") + (insert output))))) + (magit-refresh)) + (message "Bisecting...done"))))) + +;;; Sections + +(defun magit-bisect-in-progress-p () + (file-exists-p (magit-git-dir "BISECT_LOG"))) + +(defun magit-insert-bisect-output () + "While bisecting, insert section with output from `git bisect'." + (when (magit-bisect-in-progress-p) + (let* ((lines + (or (magit-file-lines (magit-git-dir "BISECT_CMD_OUTPUT")) + (list "Bisecting: (no saved bisect output)" + "It appears you have invoked `git bisect' from a shell." + "There is nothing wrong with that, we just cannot display" + "anything useful here. Consult the shell output instead."))) + (done-re "^\\([a-z0-9]\\{40\\}\\) is the first bad commit$") + (bad-line (or (and (string-match done-re (car lines)) + (pop lines)) + (--first (string-match done-re it) lines)))) + (magit-insert-section ((eval (if bad-line 'commit 'bisect-output)) + (and bad-line (match-string 1 bad-line))) + (magit-insert-heading + (propertize (or bad-line (pop lines)) + 'font-lock-face 'magit-section-heading)) + (dolist (line lines) + (insert line "\n")))) + (insert "\n"))) + +(defun magit-insert-bisect-rest () + "While bisecting, insert section visualizing the bisect state." + (when (magit-bisect-in-progress-p) + (magit-insert-section (bisect-view) + (magit-insert-heading "Bisect Rest:") + (magit-git-wash (apply-partially 'magit-log-wash-log 'bisect-vis) + "bisect" "visualize" "git" "log" + "--format=%h%x00%D%x00%s" "--decorate=full" + (and magit-bisect-show-graph "--graph"))))) + +(defun magit-insert-bisect-log () + "While bisecting, insert section logging bisect progress." + (when (magit-bisect-in-progress-p) + (magit-insert-section (bisect-log) + (magit-insert-heading "Bisect Log:") + (magit-git-wash #'magit-wash-bisect-log "bisect" "log") + (insert ?\n)))) + +(defun magit-wash-bisect-log (_args) + (let (beg) + (while (progn (setq beg (point-marker)) + (re-search-forward "^\\(git bisect [^\n]+\n\\)" nil t)) + (magit-bind-match-strings (heading) nil + (magit-delete-match) + (save-restriction + (narrow-to-region beg (point)) + (goto-char (point-min)) + (magit-insert-section (bisect-item heading t) + (insert (propertize heading 'font-lock-face + 'magit-section-secondary-heading)) + (magit-insert-heading) + (magit-wash-sequence + (apply-partially 'magit-log-wash-rev 'bisect-log + (magit-abbrev-length))) + (insert ?\n))))) + (when (re-search-forward + "# first bad commit: \\[\\([a-z0-9]\\{40\\}\\)\\] [^\n]+\n" nil t) + (magit-bind-match-strings (hash) nil + (magit-delete-match) + (magit-insert-section (bisect-item) + (insert hash " is the first bad commit\n")))))) + +;;; _ +(provide 'magit-bisect) +;;; magit-bisect.el ends here diff --git a/elpa/magit-20191122.2040/magit-bisect.elc b/elpa/magit-20191122.2040/magit-bisect.elc new file mode 100644 index 0000000000000000000000000000000000000000..cd55c53ae067e47b43c86ddcb99b7235925f6646 GIT binary patch literal 15636 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 +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; Annotates each line in file-visiting buffer with information from +;; the revision which last modified the line. + +;;; Code: + +(eval-when-compile + (require 'subr-x)) + +(require 'magit) + +;;; Options + +(defgroup magit-blame nil + "Blame support for Magit." + :link '(info-link "(magit)Blaming") + :group 'magit-modes) + +(defcustom magit-blame-styles + '((headings + (heading-format . "%-20a %C %s\n")) + (margin + (margin-format . (" %s%f" " %C %a" " %H")) + (margin-width . 42) + (margin-face . magit-blame-margin) + (margin-body-face . (magit-blame-dimmed))) + (highlight + (highlight-face . magit-blame-highlight)) + (lines + (show-lines . t) + (show-message . t))) + "List of styles used to visualize blame information. + +Each entry has the form (IDENT (KEY . VALUE)...). IDENT has +to be a symbol uniquely identifing the style. The following +KEYs are recognized: + + `show-lines' + Whether to prefix each chunk of lines with a thin line. + This has no effect if `heading-format' is non-nil. + `show-message' + Whether to display a commit's summary line in the echo area + when crossing chunks. + `highlight-face' + Face used to highlight the first line of each chunk. + If this is nil, then those lines are not highlighted. + `heading-format' + String specifying the information to be shown above each + chunk of lines. It must end with a newline character. + `margin-format' + String specifying the information to be shown in the left + buffer margin. It must NOT end with a newline character. + This can also be a list of formats used for the lines at + the same positions within the chunk. If the chunk has + more lines than formats are specified, then the last is + repeated. + `margin-width' + Width of the margin, provided `margin-format' is non-nil. + `margin-face' + Face used in the margin, provided `margin-format' is + non-nil. This face is used in combination with the faces + that are specific to the used %-specs. If this is nil, + then `magit-blame-margin' is used. + `margin-body-face' + Face used in the margin for all but first line of a chunk. + This face is used in combination with the faces that are + specific to the used %-specs. This can also be a list of + faces (usually one face), in which case only these faces + are used and the %-spec faces are ignored. A good value + might be `(magit-blame-dimmed)'. If this is nil, then + the same face as for the first line is used. + +The following %-specs can be used in `heading-format' and +`margin-format': + + %H hash using face `magit-blame-hash' + %s summary using face `magit-blame-summary' + %a author using face `magit-blame-name' + %A author time using face `magit-blame-date' + %c committer using face `magit-blame-name' + %C committer time using face `magit-blame-date' + +Additionally if `margin-format' ends with %f, then the string +that is displayed in the margin is made at least `margin-width' +characters wide, which may be desirable if the used face sets +the background color. + +The style used in the current buffer can be cycled from the blame +popup. Blame commands (except `magit-blame-echo') use the first +style as the initial style when beginning to blame in a buffer." + :package-version '(magit . "2.13.0") + :group 'magit-blame + :type 'string) + +(defcustom magit-blame-echo-style 'lines + "The blame visualization style used by `magit-blame-echo'. +A symbol that has to be used as the identifier for one of the +styles defined in `magit-blame-styles'." + :package-version '(magit . "2.13.0") + :group 'magit-blame + :type 'symbol) + +(defcustom magit-blame-time-format "%F %H:%M" + "Format for time strings in blame headings." + :group 'magit-blame + :type 'string) + +(defcustom magit-blame-read-only t + "Whether to initially make the blamed buffer read-only." + :package-version '(magit . "2.13.0") + :group 'magit-blame + :type 'boolean) + +(defcustom magit-blame-disable-modes '(fci-mode yascroll-bar-mode) + "List of modes not compatible with Magit-Blame mode. +This modes are turned off when Magit-Blame mode is turned on, +and then turned on again when turning off the latter." + :group 'magit-blame + :type '(repeat (symbol :tag "Mode"))) + +(defcustom magit-blame-mode-lighter " Blame" + "The mode-line lighter of the Magit-Blame mode." + :group 'magit-blame + :type '(choice (const :tag "No lighter" "") string)) + +(defcustom magit-blame-goto-chunk-hook + '(magit-blame-maybe-update-revision-buffer + magit-blame-maybe-show-message) + "Hook run after point entered another chunk." + :package-version '(magit . "2.13.0") + :group 'magit-blame + :type 'hook + :get 'magit-hook-custom-get + :options '(magit-blame-maybe-update-revision-buffer + magit-blame-maybe-show-message)) + +;;; Faces + +(defface magit-blame-highlight + `((((class color) (background light)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :background "grey80" + :foreground "black") + (((class color) (background dark)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :background "grey25" + :foreground "white")) + "Face used for highlighting when blaming. +Also see option `magit-blame-styles'." + :group 'magit-faces) + +(defface magit-blame-margin + '((t :inherit magit-blame-highlight + :weight normal + :slant normal)) + "Face used for the blame margin by default when blaming. +Also see option `magit-blame-styles'." + :group 'magit-faces) + +(defface magit-blame-dimmed + '((t :inherit magit-dimmed + :weight normal + :slant normal)) + "Face used for the blame margin in some cases when blaming. +Also see option `magit-blame-styles'." + :group 'magit-faces) + +(defface magit-blame-heading + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :inherit magit-blame-highlight + :weight normal + :slant normal)) + "Face used for blame headings by default when blaming. +Also see option `magit-blame-styles'." + :group 'magit-faces) + +(defface magit-blame-summary nil + "Face used for commit summaries when blaming." + :group 'magit-faces) + +(defface magit-blame-hash nil + "Face used for commit hashes when blaming." + :group 'magit-faces) + +(defface magit-blame-name nil + "Face used for author and committer names when blaming." + :group 'magit-faces) + +(defface magit-blame-date nil + "Face used for dates when blaming." + :group 'magit-faces) + +;;; Chunks + +(defclass magit-blame-chunk () + (;; + (orig-rev :initarg :orig-rev) + (orig-line :initarg :orig-line) + (final-line :initarg :final-line) + (num-lines :initarg :num-lines) + ;; previous + (prev-rev :initform nil) + (prev-file :initform nil) + ;; filename + (orig-file))) + +(defun magit-current-blame-chunk (&optional type) + (or (and (not (and type (not (eq type magit-blame-type)))) + (magit-blame-chunk-at (point))) + (and type + (let ((rev (or magit-buffer-refname magit-buffer-revision)) + (file (magit-file-relative-name nil (not magit-buffer-file-name))) + (line (format "%i,+1" (line-number-at-pos)))) + (unless file + (error "Buffer does not visit a tracked file")) + (with-temp-buffer + (magit-with-toplevel + (magit-git-insert + "blame" "--porcelain" + (if (memq magit-blame-type '(final removal)) + (cons "--reverse" (magit-blame-arguments)) + (magit-blame-arguments)) + "-L" line rev "--" file) + (goto-char (point-min)) + (car (magit-blame--parse-chunk type)))))))) + +(defun magit-blame-chunk-at (pos) + (--some (overlay-get it 'magit-blame-chunk) + (overlays-at pos))) + +(defun magit-blame--overlay-at (&optional pos key) + (unless pos + (setq pos (point))) + (--first (overlay-get it (or key 'magit-blame-chunk)) + (nconc (overlays-at pos) + (overlays-in pos pos)))) + +;;; Keymaps + +(defvar magit-blame-mode-map + (let ((map (make-sparse-keymap))) + (define-key map (kbd "C-c C-q") 'magit-blame-quit) + map) + "Keymap for `magit-blame-mode'. +Note that most blaming key bindings are defined +in `magit-blame-read-only-mode-map' instead.") + +(defvar magit-blame-read-only-mode-map + (let ((map (make-sparse-keymap))) + (cond ((featurep 'jkl) + (define-key map [return] 'magit-show-commit) + (define-key map (kbd "i") 'magit-blame-previous-chunk) + (define-key map (kbd "I") 'magit-blame-previous-chunk-same-commit) + (define-key map (kbd "k") 'magit-blame-next-chunk) + (define-key map (kbd "K") 'magit-blame-next-chunk-same-commit) + (define-key map (kbd "j") 'magit-blame-addition) + (define-key map (kbd "l") 'magit-blame-removal) + (define-key map (kbd "f") 'magit-blame-reverse) + (define-key map (kbd "b") 'magit-blame)) + (t + (define-key map (kbd "C-m") 'magit-show-commit) + (define-key map (kbd "p") 'magit-blame-previous-chunk) + (define-key map (kbd "P") 'magit-blame-previous-chunk-same-commit) + (define-key map (kbd "n") 'magit-blame-next-chunk) + (define-key map (kbd "N") 'magit-blame-next-chunk-same-commit) + (define-key map (kbd "b") 'magit-blame-addition) + (define-key map (kbd "r") 'magit-blame-removal) + (define-key map (kbd "f") 'magit-blame-reverse) + (define-key map (kbd "B") 'magit-blame))) + (define-key map (kbd "c") 'magit-blame-cycle-style) + (define-key map (kbd "q") 'magit-blame-quit) + (define-key map (kbd "M-w") 'magit-blame-copy-hash) + (define-key map (kbd "SPC") 'magit-diff-show-or-scroll-up) + (define-key map (kbd "DEL") 'magit-diff-show-or-scroll-down) + map) + "Keymap for `magit-blame-read-only-mode'.") + +;;; Modes +;;;; Variables + +(defvar-local magit-blame-buffer-read-only nil) +(defvar-local magit-blame-cache nil) +(defvar-local magit-blame-disabled-modes nil) +(defvar-local magit-blame-process nil) +(defvar-local magit-blame-recursive-p nil) +(defvar-local magit-blame-type nil) +(defvar-local magit-blame-separator nil) +(defvar-local magit-blame-previous-chunk nil) + +(defvar-local magit-blame--style nil) + +(defsubst magit-blame--style-get (key) + (cdr (assoc key (cdr magit-blame--style)))) + +;;;; Base Mode + +(define-minor-mode magit-blame-mode + "Display blame information inline." + :lighter magit-blame-mode-lighter + (cond (magit-blame-mode + (when (called-interactively-p 'any) + (setq magit-blame-mode nil) + (user-error + (concat "Don't call `magit-blame-mode' directly; " + "instead use `magit-blame'"))) + (add-hook 'after-save-hook 'magit-blame--refresh t t) + (add-hook 'post-command-hook 'magit-blame-goto-chunk-hook t t) + (add-hook 'before-revert-hook 'magit-blame--remove-overlays t t) + (add-hook 'after-revert-hook 'magit-blame--refresh t t) + (add-hook 'read-only-mode-hook 'magit-blame-toggle-read-only t t) + (setq magit-blame-buffer-read-only buffer-read-only) + (when (or magit-blame-read-only magit-buffer-file-name) + (read-only-mode 1)) + (dolist (mode magit-blame-disable-modes) + (when (and (boundp mode) (symbol-value mode)) + (funcall mode -1) + (push mode magit-blame-disabled-modes))) + (setq magit-blame-separator (magit-blame--format-separator)) + (unless magit-blame--style + (setq magit-blame--style (car magit-blame-styles))) + (magit-blame--update-margin)) + (t + (when (process-live-p magit-blame-process) + (kill-process magit-blame-process) + (while magit-blame-process + (sit-for 0.01))) ; avoid racing the sentinel + (remove-hook 'after-save-hook 'magit-blame--refresh t) + (remove-hook 'post-command-hook 'magit-blame-goto-chunk-hook t) + (remove-hook 'before-revert-hook 'magit-blame--remove-overlays t) + (remove-hook 'after-revert-hook 'magit-blame--refresh t) + (remove-hook 'read-only-mode-hook 'magit-blame-toggle-read-only t) + (unless magit-blame-buffer-read-only + (read-only-mode -1)) + (magit-blame-read-only-mode -1) + (dolist (mode magit-blame-disabled-modes) + (funcall mode 1)) + (kill-local-variable 'magit-blame-disabled-modes) + (kill-local-variable 'magit-blame-type) + (kill-local-variable 'magit-blame--style) + (magit-blame--update-margin) + (magit-blame--remove-overlays)))) + +(defun magit-blame--refresh () + (magit-blame--run (magit-blame-arguments))) + +(defun magit-blame-goto-chunk-hook () + (let ((chunk (magit-blame-chunk-at (point)))) + (when (cl-typep chunk 'magit-blame-chunk) + (unless (eq chunk magit-blame-previous-chunk) + (run-hooks 'magit-blame-goto-chunk-hook)) + (setq magit-blame-previous-chunk chunk)))) + +(defun magit-blame-toggle-read-only () + (magit-blame-read-only-mode (if buffer-read-only 1 -1))) + +;;;; Read-Only Mode + +(define-minor-mode magit-blame-read-only-mode + "Provide keybindings for Magit-Blame mode. + +This minor-mode provides the key bindings for Magit-Blame mode, +but only when Read-Only mode is also enabled because these key +bindings would otherwise conflict badly with regular bindings. + +When both Magit-Blame mode and Read-Only mode are enabled, then +this mode gets automatically enabled too and when one of these +modes is toggled, then this mode also gets toggled automatically. + +\\{magit-blame-read-only-mode-map}") + +;;;; Kludges + +(defun magit-blame-put-keymap-before-view-mode () + "Put `magit-blame-read-only-mode' ahead of `view-mode' in `minor-mode-map-alist'." + (--when-let (assq 'magit-blame-read-only-mode + (cl-member 'view-mode minor-mode-map-alist :key #'car)) + (setq minor-mode-map-alist + (cons it (delq it minor-mode-map-alist)))) + (remove-hook 'view-mode-hook #'magit-blame-put-keymap-before-view-mode)) + +(add-hook 'view-mode-hook #'magit-blame-put-keymap-before-view-mode) + +;;; Process + +(defun magit-blame--run (args) + (magit-with-toplevel + (unless magit-blame-mode + (magit-blame-mode 1)) + (message "Blaming...") + (magit-blame-run-process + (or magit-buffer-refname magit-buffer-revision) + (magit-file-relative-name nil (not magit-buffer-file-name)) + (if (memq magit-blame-type '(final removal)) + (cons "--reverse" args) + args) + (list (line-number-at-pos (window-start)) + (line-number-at-pos (1- (window-end nil t))))) + (set-process-sentinel magit-this-process + 'magit-blame-process-quickstart-sentinel))) + +(defun magit-blame-run-process (revision file args &optional lines) + (let ((process (magit-parse-git-async + "blame" "--incremental" args + (and lines (list "-L" (apply #'format "%s,%s" lines))) + revision "--" file))) + (set-process-filter process 'magit-blame-process-filter) + (set-process-sentinel process 'magit-blame-process-sentinel) + (process-put process 'arguments (list revision file args)) + (setq magit-blame-cache (make-hash-table :test 'equal)) + (setq magit-blame-process process))) + +(defun magit-blame-process-quickstart-sentinel (process event) + (when (memq (process-status process) '(exit signal)) + (magit-blame-process-sentinel process event t) + (magit-blame-assert-buffer process) + (with-current-buffer (process-get process 'command-buf) + (when magit-blame-mode + (let ((default-directory (magit-toplevel))) + (apply #'magit-blame-run-process + (process-get process 'arguments))))))) + +(defun magit-blame-process-sentinel (process _event &optional quiet) + (let ((status (process-status process))) + (when (memq status '(exit signal)) + (kill-buffer (process-buffer process)) + (if (and (eq status 'exit) + (zerop (process-exit-status process))) + (unless quiet + (message "Blaming...done")) + (magit-blame-assert-buffer process) + (with-current-buffer (process-get process 'command-buf) + (if magit-blame-mode + (progn (magit-blame-mode -1) + (message "Blaming...failed")) + (message "Blaming...aborted")))) + (kill-local-variable 'magit-blame-process)))) + +(defun magit-blame-process-filter (process string) + (internal-default-process-filter process string) + (let ((buf (process-get process 'command-buf)) + (pos (process-get process 'parsed)) + (mark (process-mark process)) + type cache) + (with-current-buffer buf + (setq type magit-blame-type) + (setq cache magit-blame-cache)) + (with-current-buffer (process-buffer process) + (goto-char pos) + (while (and (< (point) mark) + (save-excursion (re-search-forward "^filename .+\n" nil t))) + (pcase-let* ((`(,chunk ,revinfo) + (magit-blame--parse-chunk type)) + (rev (oref chunk orig-rev))) + (if revinfo + (puthash rev revinfo cache) + (setq revinfo + (or (gethash rev cache) + (puthash rev (magit-blame--commit-alist rev) cache)))) + (magit-blame--make-overlays buf chunk revinfo)) + (process-put process 'parsed (point)))))) + +(defun magit-blame--parse-chunk (type) + (let (chunk revinfo) + (looking-at "^\\(.\\{40\\}\\) \\([0-9]+\\) \\([0-9]+\\) \\([0-9]+\\)") + (with-slots (orig-rev orig-file prev-rev prev-file) + (setq chunk (magit-blame-chunk + :orig-rev (match-string 1) + :orig-line (string-to-number (match-string 2)) + :final-line (string-to-number (match-string 3)) + :num-lines (string-to-number (match-string 4)))) + (forward-line) + (let (done) + (while (not done) + (cond ((looking-at "^filename \\(.+\\)") + (setq done t) + (setf orig-file (match-string 1))) + ((looking-at "^previous \\(.\\{40\\}\\) \\(.+\\)") + (setf prev-rev (match-string 1)) + (setf prev-file (match-string 2))) + ((looking-at "^\\([^ ]+\\) \\(.+\\)") + (push (cons (match-string 1) + (match-string 2)) revinfo))) + (forward-line))) + (when (and (eq type 'removal) prev-rev) + (cl-rotatef orig-rev prev-rev) + (cl-rotatef orig-file prev-file) + (setq revinfo nil))) + (list chunk revinfo))) + +(defun magit-blame--commit-alist (rev) + (cl-mapcar 'cons + '("summary" + "author" "author-time" "author-tz" + "committer" "committer-time" "committer-tz") + (split-string (magit-rev-format "%s\v%an\v%ad\v%cn\v%cd" rev + "--date=format:%s\v%z") + "\v"))) + +(defun magit-blame-assert-buffer (process) + (unless (buffer-live-p (process-get process 'command-buf)) + (kill-process process) + (user-error "Buffer being blamed has been killed"))) + +;;; Display + +(defun magit-blame--make-overlays (buf chunk revinfo) + (with-current-buffer buf + (save-excursion + (save-restriction + (widen) + (goto-char (point-min)) + (forward-line (1- (oref chunk final-line))) + (let ((beg (point)) + (end (save-excursion + (forward-line (oref chunk num-lines)) + (point)))) + (magit-blame--remove-overlays beg end) + (magit-blame--make-margin-overlays chunk revinfo beg end) + (magit-blame--make-heading-overlay chunk revinfo beg end) + (magit-blame--make-highlight-overlay chunk beg)))))) + +(defun magit-blame--make-margin-overlays (chunk revinfo _beg end) + (save-excursion + (let ((line 0)) + (while (< (point) end) + (magit-blame--make-margin-overlay chunk revinfo line) + (forward-line) + (cl-incf line))))) + +(defun magit-blame--make-margin-overlay (chunk revinfo line) + (let* ((end (line-end-position)) + ;; If possible avoid putting this on the first character + ;; of the line to avoid a conflict with the line overlay. + (beg (min (1+ (line-beginning-position)) end)) + (ov (make-overlay beg end))) + (overlay-put ov 'magit-blame-chunk chunk) + (overlay-put ov 'magit-blame-revinfo revinfo) + (overlay-put ov 'magit-blame-margin line) + (magit-blame--update-margin-overlay ov))) + +(defun magit-blame--make-heading-overlay (chunk revinfo beg end) + (let ((ov (make-overlay beg end))) + (overlay-put ov 'magit-blame-chunk chunk) + (overlay-put ov 'magit-blame-revinfo revinfo) + (overlay-put ov 'magit-blame-heading t) + (magit-blame--update-heading-overlay ov))) + +(defun magit-blame--make-highlight-overlay (chunk beg) + (let ((ov (make-overlay beg (1+ (line-end-position))))) + (overlay-put ov 'magit-blame-chunk chunk) + (overlay-put ov 'magit-blame-highlight t) + (magit-blame--update-highlight-overlay ov))) + +(defun magit-blame--update-margin () + (setq left-margin-width (or (magit-blame--style-get 'margin-width) 0)) + (set-window-buffer (selected-window) (current-buffer))) + +(defun magit-blame--update-overlays () + (save-restriction + (widen) + (dolist (ov (overlays-in (point-min) (point-max))) + (cond ((overlay-get ov 'magit-blame-heading) + (magit-blame--update-heading-overlay ov)) + ((overlay-get ov 'magit-blame-margin) + (magit-blame--update-margin-overlay ov)) + ((overlay-get ov 'magit-blame-highlight) + (magit-blame--update-highlight-overlay ov)))))) + +(defun magit-blame--update-margin-overlay (ov) + (overlay-put + ov 'before-string + (and (magit-blame--style-get 'margin-width) + (propertize + "o" 'display + (list (list 'margin 'left-margin) + (let ((line (overlay-get ov 'magit-blame-margin)) + (format (magit-blame--style-get 'margin-format)) + (face (magit-blame--style-get 'margin-face))) + (magit-blame--format-string + ov + (or (and (atom format) + format) + (nth line format) + (car (last format))) + (or (and (not (zerop line)) + (magit-blame--style-get 'margin-body-face)) + face + 'magit-blame-margin)))))))) + +(defun magit-blame--update-heading-overlay (ov) + (overlay-put + ov 'before-string + (--if-let (magit-blame--style-get 'heading-format) + (magit-blame--format-string ov it 'magit-blame-heading) + (and (magit-blame--style-get 'show-lines) + (or (not (magit-blame--style-get 'margin-format)) + (save-excursion + (goto-char (overlay-start ov)) + ;; Special case of the special case described in + ;; `magit-blame--make-margin-overlay'. For empty + ;; lines it is not possible to show both overlays + ;; without the line being to high. + (not (= (point) (line-end-position))))) + magit-blame-separator)))) + +(defun magit-blame--update-highlight-overlay (ov) + (overlay-put ov 'font-lock-face (magit-blame--style-get 'highlight-face))) + +(defun magit-blame--format-string (ov format face) + (let* ((chunk (overlay-get ov 'magit-blame-chunk)) + (revinfo (overlay-get ov 'magit-blame-revinfo)) + (key (list format face)) + (string (cdr (assoc key revinfo)))) + (unless string + (setq string + (and format + (magit-blame--format-string-1 (oref chunk orig-rev) + revinfo format face))) + (nconc revinfo (list (cons key string)))) + string)) + +(defun magit-blame--format-string-1 (rev revinfo format face) + (let ((str + (if (equal rev "0000000000000000000000000000000000000000") + (propertize (concat (if (string-prefix-p "\s" format) "\s" "") + "Not Yet Committed" + (if (string-suffix-p "\n" format) "\n" "")) + 'font-lock-face face) + (magit--format-spec + (propertize format 'font-lock-face face) + (cl-flet* ((p0 (s f) + (propertize s 'font-lock-face + (if face + (if (listp face) + face + (list f face)) + f))) + (p1 (k f) + (p0 (cdr (assoc k revinfo)) f)) + (p2 (k1 k2 f) + (p0 (magit-blame--format-time-string + (cdr (assoc k1 revinfo)) + (cdr (assoc k2 revinfo))) + f))) + `((?H . ,(p0 rev 'magit-blame-hash)) + (?s . ,(p1 "summary" 'magit-blame-summary)) + (?a . ,(p1 "author" 'magit-blame-name)) + (?c . ,(p1 "committer" 'magit-blame-name)) + (?A . ,(p2 "author-time" "author-tz" 'magit-blame-date)) + (?C . ,(p2 "committer-time" "committer-tz" 'magit-blame-date)) + (?f . ""))))))) + (if-let ((width (and (string-suffix-p "%f" format) + (magit-blame--style-get 'margin-width)))) + (concat str + (propertize (make-string (max 0 (- width (length str))) ?\s) + 'font-lock-face face)) + str))) + +(defun magit-blame--format-separator () + (propertize + (concat (propertize "\s" 'display '(space :height (2))) + (propertize "\n" 'line-height t)) + 'font-lock-face (list :background + (face-attribute 'magit-blame-heading + :background nil t)))) + +(defun magit-blame--format-time-string (time tz) + (let* ((time-format (or (magit-blame--style-get 'time-format) + magit-blame-time-format)) + (tz-in-second (and (string-match "%z" time-format) + (car (last (parse-time-string tz)))))) + (format-time-string time-format + (seconds-to-time (string-to-number time)) + tz-in-second))) + +(defun magit-blame--remove-overlays (&optional beg end) + (save-restriction + (widen) + (dolist (ov (overlays-in (or beg (point-min)) + (or end (point-max)))) + (when (overlay-get ov 'magit-blame-chunk) + (delete-overlay ov))))) + +(defun magit-blame-maybe-show-message () + (when (magit-blame--style-get 'show-message) + (let ((message-log-max 0)) + (if-let ((msg (cdr (assoc "summary" + (gethash (oref (magit-current-blame-chunk) + orig-rev) + magit-blame-cache))))) + (progn (set-text-properties 0 (length msg) nil msg) + (message msg)) + (message "Commit data not available yet. Still blaming."))))) + +;;; Commands + +;;;###autoload (autoload 'magit-blame-echo "magit-blame" nil t) +(define-suffix-command magit-blame-echo (args) + "For each line show the revision in which it was added. +Show the information about the chunk at point in the echo area +when moving between chunks. Unlike other blaming commands, do +not turn on `read-only-mode'." + :if (lambda () + (and buffer-file-name + (or (not magit-blame-mode) + buffer-read-only))) + (interactive (list (magit-blame-arguments))) + (when magit-buffer-file-name + (user-error "Blob buffers aren't supported")) + (setq-local magit-blame--style + (assq magit-blame-echo-style magit-blame-styles)) + (setq-local magit-blame-disable-modes + (cons 'eldoc-mode magit-blame-disable-modes)) + (if (not magit-blame-mode) + (let ((magit-blame-read-only nil)) + (magit-blame--pre-blame-assert 'addition) + (magit-blame--pre-blame-setup 'addition) + (magit-blame--run args)) + (read-only-mode -1) + (magit-blame--update-overlays))) + +;;;###autoload (autoload 'magit-blame-addition "magit-blame" nil t) +(define-suffix-command magit-blame-addition (args) + "For each line show the revision in which it was added." + (interactive (list (magit-blame-arguments))) + (magit-blame--pre-blame-assert 'addition) + (magit-blame--pre-blame-setup 'addition) + (magit-blame--run args)) + +;;;###autoload (autoload 'magit-blame-removal "magit-blame" nil t) +(define-suffix-command magit-blame-removal (args) + "For each line show the revision in which it was removed." + :if-nil 'buffer-file-name + (interactive (list (magit-blame-arguments))) + (unless magit-buffer-file-name + (user-error "Only blob buffers can be blamed in reverse")) + (magit-blame--pre-blame-assert 'removal) + (magit-blame--pre-blame-setup 'removal) + (magit-blame--run args)) + +;;;###autoload (autoload 'magit-blame-reverse "magit-blame" nil t) +(define-suffix-command magit-blame-reverse (args) + "For each line show the last revision in which it still exists." + :if-nil 'buffer-file-name + (interactive (list (magit-blame-arguments))) + (unless magit-buffer-file-name + (user-error "Only blob buffers can be blamed in reverse")) + (magit-blame--pre-blame-assert 'final) + (magit-blame--pre-blame-setup 'final) + (magit-blame--run args)) + +(defun magit-blame--pre-blame-assert (type) + (unless (magit-toplevel) + (magit--not-inside-repository-error)) + (if (and magit-blame-mode + (eq type magit-blame-type)) + (if-let ((chunk (magit-current-blame-chunk))) + (unless (oref chunk prev-rev) + (user-error "Chunk has no further history")) + (user-error "Commit data not available yet. Still blaming.")) + (unless (magit-file-relative-name nil (not magit-buffer-file-name)) + (if buffer-file-name + (user-error "Buffer isn't visiting a tracked file") + (user-error "Buffer isn't visiting a file"))))) + +(defun magit-blame--pre-blame-setup (type) + (when magit-blame-mode + (if (eq type magit-blame-type) + (let ((style magit-blame--style)) + (magit-blame-visit-other-file) + (setq-local magit-blame--style style) + (setq-local magit-blame-recursive-p t) + ;; Set window-start for the benefit of quickstart. + (redisplay)) + (magit-blame--remove-overlays))) + (setq magit-blame-type type)) + +(defun magit-blame-visit-other-file () + "Visit another blob related to the current chunk." + (interactive) + (with-slots (prev-rev prev-file orig-line) + (magit-current-blame-chunk) + (unless prev-rev + (user-error "Chunk has no further history")) + (magit-with-toplevel + (magit-find-file prev-rev prev-file)) + ;; TODO Adjust line like magit-diff-visit-file. + (goto-char (point-min)) + (forward-line (1- orig-line)))) + +(defun magit-blame-visit-file () + "Visit the blob related to the current chunk." + (interactive) + (with-slots (orig-rev orig-file orig-line) + (magit-current-blame-chunk) + (magit-with-toplevel + (magit-find-file orig-rev orig-file)) + (goto-char (point-min)) + (forward-line (1- orig-line)))) + +(define-suffix-command magit-blame-quit () + "Turn off Magit-Blame mode. +If the buffer was created during a recursive blame, +then also kill the buffer." + :if-non-nil 'magit-blame-mode + (interactive) + (magit-blame-mode -1) + (when magit-blame-recursive-p + (kill-buffer))) + +(defun magit-blame-next-chunk () + "Move to the next chunk." + (interactive) + (--if-let (next-single-char-property-change (point) 'magit-blame-chunk) + (goto-char it) + (user-error "No more chunks"))) + +(defun magit-blame-previous-chunk () + "Move to the previous chunk." + (interactive) + (--if-let (previous-single-char-property-change (point) 'magit-blame-chunk) + (goto-char it) + (user-error "No more chunks"))) + +(defun magit-blame-next-chunk-same-commit (&optional previous) + "Move to the next chunk from the same commit.\n\n(fn)" + (interactive) + (if-let ((rev (oref (magit-current-blame-chunk) orig-rev))) + (let ((pos (point)) ov) + (save-excursion + (while (and (not ov) + (not (= pos (if previous (point-min) (point-max)))) + (setq pos (funcall + (if previous + 'previous-single-char-property-change + 'next-single-char-property-change) + pos 'magit-blame-chunk))) + (--when-let (magit-blame--overlay-at pos) + (when (equal (oref (magit-blame-chunk-at pos) orig-rev) rev) + (setq ov it))))) + (if ov + (goto-char (overlay-start ov)) + (user-error "No more chunks from same commit"))) + (user-error "This chunk hasn't been blamed yet"))) + +(defun magit-blame-previous-chunk-same-commit () + "Move to the previous chunk from the same commit." + (interactive) + (magit-blame-next-chunk-same-commit 'previous-single-char-property-change)) + +(defun magit-blame-cycle-style () + "Change how blame information is visualized. +Cycle through the elements of option `magit-blame-styles'." + (interactive) + (setq magit-blame--style + (or (cadr (cl-member (car magit-blame--style) + magit-blame-styles :key #'car)) + (car magit-blame-styles))) + (magit-blame--update-margin) + (magit-blame--update-overlays)) + +(defun magit-blame-copy-hash () + "Save hash of the current chunk's commit to the kill ring. + +When the region is active, then save the region's content +instead of the hash, like `kill-ring-save' would." + (interactive) + (if (use-region-p) + (call-interactively #'copy-region-as-kill) + (kill-new (message "%s" (oref (magit-current-blame-chunk) orig-rev))))) + +;;; Popup + +;;;###autoload (autoload 'magit-blame "magit-blame" nil t) +(define-transient-command magit-blame () + "Show the commits that added or removed lines in the visited file." + :man-page "git-blame" + :value '("-w") + ["Arguments" + ("-w" "Ignore whitespace" "-w") + ("-r" "Do not treat root commits as boundaries" "--root") + (magit-blame:-M) + (magit-blame:-C)] + ["Actions" + ("b" "Show commits adding lines" magit-blame-addition) + ("r" "Show commits removing lines" magit-blame-removal) + ("f" "Show last commits that still have lines" magit-blame-reverse) + ("m" "Blame echo" magit-blame-echo) + ("q" "Quit blaming" magit-blame-quit)] + ["Refresh" + :if-non-nil magit-blame-mode + ("c" "Cycle style" magit-blame-cycle-style)]) + +(defun magit-blame-arguments () + (transient-args 'magit-blame)) + +(define-infix-argument magit-blame:-M () + :description "Detect lines moved or copied within a file" + :class 'transient-option + :argument "-M" + :reader 'transient-read-number-N+) + +(define-infix-argument magit-blame:-C () + :description "Detect lines moved or copied between files" + :class 'transient-option + :argument "-C" + :reader 'transient-read-number-N+) + +;;; Utilities + +(defun magit-blame-maybe-update-revision-buffer () + (when-let ((chunk (magit-current-blame-chunk)) + (commit (oref chunk orig-rev)) + (buffer (magit-get-mode-buffer 'magit-revision-mode nil t))) + (if magit--update-revision-buffer + (setq magit--update-revision-buffer (list commit buffer)) + (setq magit--update-revision-buffer (list commit buffer)) + (run-with-idle-timer + magit-update-other-window-delay nil + (lambda () + (pcase-let ((`(,rev ,buf) magit--update-revision-buffer)) + (setq magit--update-revision-buffer nil) + (when (buffer-live-p buf) + (let ((magit-display-buffer-noselect t)) + (apply #'magit-show-commit rev + (magit-diff-arguments 'magit-revision-mode)))))))))) + +;;; _ +(provide 'magit-blame) +;;; magit-blame.el ends here diff --git a/elpa/magit-20191122.2040/magit-blame.elc b/elpa/magit-20191122.2040/magit-blame.elc new file mode 100644 index 0000000000000000000000000000000000000000..c419d5a992f1277ccb8f7ace965e08a01bdf79a2 GIT binary patch literal 37852 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 literal 0 HcmV?d00001 diff --git a/elpa/magit-20191122.2040/magit-bookmark.el b/elpa/magit-20191122.2040/magit-bookmark.el new file mode 100644 index 00000000..49ba9c70 --- /dev/null +++ b/elpa/magit-20191122.2040/magit-bookmark.el @@ -0,0 +1,203 @@ +;;; magit-bookmark.el --- bookmark support for Magit -*- lexical-binding: t -*- + +;; Copyright (C) 2010-2019 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; Inspired by an earlier implementation by Yuri Khan. + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; Support for bookmarks for most Magit buffers. + +;;; Code: + +(eval-when-compile + (require 'subr-x)) + +(require 'magit) +(require 'bookmark) + +;;; Core + +(defun magit--make-bookmark () + "Create a bookmark for the current Magit buffer. +Input values are the major-mode's `magit-bookmark-name' method, +and the buffer-local values of the variables referenced in its +`magit-bookmark-variables' property." + (if (plist-member (symbol-plist major-mode) 'magit-bookmark-variables) + (let ((bookmark (bookmark-make-record-default 'no-file))) + (bookmark-prop-set bookmark 'handler 'magit--handle-bookmark) + (bookmark-prop-set bookmark 'mode major-mode) + (bookmark-prop-set bookmark 'filename (magit-toplevel)) + (bookmark-prop-set bookmark 'defaults (list (magit-bookmark-name))) + (dolist (var (get major-mode 'magit-bookmark-variables)) + (bookmark-prop-set bookmark var (symbol-value var))) + (bookmark-prop-set + bookmark 'magit-hidden-sections + (--keep (and (oref it hidden) + (cons (oref it type) + (if (derived-mode-p 'magit-stash-mode) + (replace-regexp-in-string + (regexp-quote magit-buffer-revision) + magit-buffer-revision-hash + (oref it value)) + (oref it value)))) + (oref magit-root-section children))) + bookmark) + (user-error "Bookmarking is not implemented for %s buffers" major-mode))) + +;;;###autoload +(defun magit--handle-bookmark (bookmark) + "Open a bookmark created by `magit--make-bookmark'. +Call the `magit-*-setup-buffer' function of the the major-mode +with the variables' values as arguments, which were recorded by +`magit--make-bookmark'. Ignore `magit-display-buffer-function'." + (let ((buffer (let ((default-directory (bookmark-get-filename bookmark)) + (mode (bookmark-prop-get bookmark 'mode)) + (magit-display-buffer-function #'identity) + (magit-display-buffer-noselect t)) + (apply (intern (format "%s-setup-buffer" + (substring (symbol-name mode) 0 -5))) + (--map (bookmark-prop-get bookmark it) + (get mode 'magit-bookmark-variables)))))) + (set-buffer buffer) ; That is the interface we have to adhere to. + (when-let ((hidden (bookmark-prop-get bookmark 'magit-hidden-sections))) + (with-current-buffer buffer + (dolist (child (oref magit-root-section children)) + (if (member (cons (oref child type) + (oref child value)) + hidden) + (magit-section-hide child) + (magit-section-show child))))) + nil)) + +(cl-defgeneric magit-bookmark-name () + "Return name for bookmark to current buffer." + (format "%s%s" + (substring (symbol-name major-mode) 0 -5) + (if-let ((vars (get major-mode 'magit-bookmark-variables))) + (cl-mapcan (lambda (var) + (let ((val (symbol-value var))) + (if (and val (atom val)) + (list val) + val))) + vars) + ""))) + +;;; Diff +;;;; Diff + +(put 'magit-diff-mode 'magit-bookmark-variables + '(magit-buffer-range-hashed + magit-buffer-typearg + magit-buffer-diff-args + magit-buffer-diff-files)) + +(cl-defmethod magit-bookmark-name (&context (major-mode magit-diff-mode)) + (format "magit-diff(%s%s)" + (pcase (magit-diff-type) + (`staged "staged") + (`unstaged "unstaged") + (`committed magit-buffer-range) + (`undefined + (delq nil (list magit-buffer-typearg magit-buffer-range-hashed)))) + (if magit-buffer-diff-files + (concat " -- " (mapconcat #'identity magit-buffer-diff-files " ")) + ""))) + +;;;; Revision + +(put 'magit-revision-mode 'magit-bookmark-variables + '(magit-buffer-revision-hash + magit-buffer-diff-args + magit-buffer-diff-files)) + +(cl-defmethod magit-bookmark-name (&context (major-mode magit-revision-mode)) + (format "magit-revision(%s %s)" + (magit-rev-abbrev magit-buffer-revision) + (if magit-buffer-diff-files + (mapconcat #'identity magit-buffer-diff-files " ") + (magit-rev-format "%s" magit-buffer-revision)))) + +;;;; Stash + +(put 'magit-stash-mode 'magit-bookmark-variables + '(magit-buffer-revision-hash + magit-buffer-diff-args + magit-buffer-diff-files)) + +(cl-defmethod magit-bookmark-name (&context (major-mode magit-stash-mode)) + (format "magit-stash(%s %s)" + (magit-rev-abbrev magit-buffer-revision) + (if magit-buffer-diff-files + (mapconcat #'identity magit-buffer-diff-files " ") + (magit-rev-format "%s" magit-buffer-revision)))) + +;;; Log +;;;; Log + +(put 'magit-log-mode 'magit-bookmark-variables + '(magit-buffer-revisions + magit-buffer-log-args + magit-buffer-log-files)) + +(cl-defmethod magit-bookmark-name (&context (major-mode magit-log-mode)) + (format "magit-log(%s%s)" + (mapconcat #'identity magit-buffer-revisions " ") + (if magit-buffer-log-files + (concat " -- " (mapconcat #'identity magit-buffer-log-files " ")) + ""))) + +;;;; Cherry + +(put 'magit-cherry-mode 'magit-bookmark-variables + '(magit-buffer-refname + magit-buffer-upstream)) + +(cl-defmethod magit-bookmark-name (&context (major-mode magit-cherry-mode)) + (format "magit-cherry(%s > %s)" + magit-buffer-refname + magit-buffer-upstream)) + +;;;; Reflog + +(put 'magit-reflog-mode 'magit-bookmark-variables + '(magit-buffer-refname)) + +(cl-defmethod magit-bookmark-name (&context (major-mode magit-reflog-mode)) + (format "magit-reflog(%s)" magit-buffer-refname)) + +;;; Misc + +(put 'magit-status-mode 'magit-bookmark-variables nil) + +(put 'magit-refs-mode 'magit-bookmark-variables + '(magit-buffer-upstream + magit-buffer-arguments)) + +(put 'magit-stashes-mode 'magit-bookmark-variables nil) + +(cl-defmethod magit-bookmark-name (&context (major-mode magit-stashes-mode)) + (format "magit-states(%s)" magit-buffer-refname)) + +;;; _ +(provide 'magit-bookmark) +;;; magit-bookmark.el ends here diff --git a/elpa/magit-20191122.2040/magit-bookmark.elc b/elpa/magit-20191122.2040/magit-bookmark.elc new file mode 100644 index 0000000000000000000000000000000000000000..da2deb49f0fa7aaf3db33168c702f1ba904f5634 GIT binary patch literal 5676 zcmc&&ZExeo5wo{lJojx4W5m}hl>$(wrVd=5$Gy!_|Y^|c7s zK^cTKTztmngDetNF2W!a3nh{~=om3use}s3Bvz%U*O(}MZ5JW6tGJu4Az%2H*u_*O67ESIXh=v`;UrWSWWvO&}XXr`%Y@IziYDcm`$#P@8= zv9=r>t~wK`s@Hk+tVhA8B@5Q)BzYJlR$ad2p}U}rgGB=UrGibBg*pl1y6WvKZ|0tf zqRb0b*4vBU_s%1=43apg#F=)+NrShlaY+o`xE!|;LNz{lir>kskBIp*DZL}SPG`R7 zLhgCT_>s8$fex>hj7~bQV@#NcjtCm0E3Q~}LI%FWdXH>;c|=cNk@Alo(c|BE((%ig zoJ=r5()Afl!b!3@=|LHskp2_=jNqy-$H&@VcY1UTUDAi6Qtx7Xi!Erul;---<5POL zeu5DnntXqjJ^h$wJ;n<(!Ub0ryzY^fTv~sBVt*gweIg%|kL>hodOc>RB?PYgE2f#T zne?YTtRtfLjez)wlRr7(P*Za5(njZ}Q|5W?R4OF0Fd~yDrMiomVN7!A?6Fd39aL*k zBym+csY(|>ZM97odE&6lsxsN{G)dDWz0QwPg?Sk{lsucH27@?EQcWgPhQYmBfDxhu zMoe<)*IjxM5SZU6_06O@FA{a95@EDg`%bmyu4C|CW&;6oixZ(@73WS4M1arYBmyji zEA&iJZwm#*WqhY1hM`j!^;M0?un1r(k|0!0saER8!iiyk*%kvVxZUI+0!B9Ra_OkD z1QqlzP1r!p0=!L38>iSz3UUB2i7rkngXgM07v5N$5B?x7#ArGl&Y5S%&&5pvhg&QY zGVerUv9*NJ#pu~Z?~3XNamDvK&Yw~2H-)29;!G?zna&i$8(k*qaS0+>bKGZ^Xg~}> zx!TYUP;1_;<8UqBfoTv5$^h(Yv9(mQ@0JkPs|@F0y^7)raorlP9P1SP@0~9*ad~s| z&9^UKeKS17O8bd3cq7MC%}mF{N@HM=smU$o0p8gEK-ggl6|3v5|924wsHTkf8&_&-;!4F5}u^IDy z&<8Px9a~#k^NET8bz&Z$$OHy2KLRI=iGk+CKvV3F=nduqypLS{-lf1xrof?gWkl4e zIRk~v*$aA>S1JK*n55quwMSy1ht)XeIxn|oeus7%w69dn_-9}?Qsw{*2?lu#oYrx@ z73fupBH5x>L7$NkDAJ%7{nM(GvwcfTtkV_F7#_F*bkRWaw?{b3fQ3_?4!S@i;Ta0|SD;?A zPT-@xg6cG_m>gOGM8FGRr?rAWL@T5`utFLevTZ{e8}g71LLJ!v@^<_1jSc^h4HRm< zqHTlfD0$@{vVqdeD@JV_fDf;5Z5u-Y91(|LVAK&3p+LBsxjP4cM9=VOWY1v)HDfeN z8kFHB-1tMBPT z)u;BdY3yhNlvzGEciiUPbi1(MfOm8jX?V#`Ai&0{tHD_tuCZ-x3(%+4K@<}!S>Ia? z20UeiXK+n}ni@XNW{}}8nKSF1*U$i z1uQj@+jDO?Yz~Q!1*b3(2Hn#yuxbAnbP!w{qz(j*g$F*R0q%~Q0iOqE{i72KTq7Q_ zm^yinpfY(f%l^V7N>iv((kXvT#!zHXH3{{&JnD$$;2)&x3ImdW(W*MO7p2H`qjNB1 z<$EK%i&~RdyD*)fR;N`%-8_{k7_Hn2N7dK&zSv||VxItvJWb=8+OkciQ5K=L3rh4@u9(aSf_;#JiZtshvjtI@$wE-Hg zdZg8p|E~hOGx`6HDtq!@4{4IGH2ED4=pJd&?E6$k(*J~BqrMC8aE*_H&wedW1e~MI%}icEiKK5>d?p;LCR`)pyswGe$d8f3#!^} S4BtR^yWZb+J##S`_Wlhnoz=Sl literal 0 HcmV?d00001 diff --git a/elpa/magit-20191122.2040/magit-branch.el b/elpa/magit-20191122.2040/magit-branch.el new file mode 100644 index 00000000..9d7dc251 --- /dev/null +++ b/elpa/magit-20191122.2040/magit-branch.el @@ -0,0 +1,887 @@ +;;; magit-branch.el --- branch support -*- lexical-binding: t -*- + +;; Copyright (C) 2010-2019 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; This library implements support for branches. It defines commands +;; for creating, checking out, manipulating, and configuring branches. +;; Commands defined here are mainly concerned with branches as +;; pointers, commands that deal with what a branch points at, are +;; defined elsewhere. + +;;; Code: + +(eval-when-compile + (require 'subr-x)) + +(require 'magit) +(require 'magit-reset) + +;;; Options + +(defcustom magit-branch-read-upstream-first t + "Whether to read upstream before name of new branch when creating a branch. + +`nil' Read the branch name first. +`t' Read the upstream first. +`fallback' Read the upstream first, but if it turns out that the chosen + value is not a valid upstream (because it cannot be resolved + as an existing revision), then treat it as the name of the + new branch and continue by reading the upstream next." + :package-version '(magit . "2.2.0") + :group 'magit-commands + :type '(choice (const :tag "read branch name first" nil) + (const :tag "read upstream first" t) + (const :tag "read upstream first, with fallback" fallback))) + +(defcustom magit-branch-prefer-remote-upstream nil + "Whether to favor remote upstreams when creating new branches. + +When a new branch is created, then the branch, commit, or stash +at point is suggested as the default starting point of the new +branch, or if there is no such revision at point the current +branch. In either case the user may choose another starting +point. + +If the chosen starting point is a branch, then it may also be set +as the upstream of the new branch, depending on the value of the +Git variable `branch.autoSetupMerge'. By default this is done +for remote branches, but not for local branches. + +You might prefer to always use some remote branch as upstream. +If the chosen starting point is (1) a local branch, (2) whose +name matches a member of the value of this option, (3) the +upstream of that local branch is a remote branch with the same +name, and (4) that remote branch can be fast-forwarded to the +local branch, then the chosen branch is used as starting point, +but its own upstream is used as the upstream of the new branch. + +Members of this option's value are treated as branch names that +have to match exactly unless they contain a character that makes +them invalid as a branch name. Recommended characters to use +to trigger interpretation as a regexp are \"*\" and \"^\". Some +other characters which you might expect to be invalid, actually +are not, e.g. \".+$\" are all perfectly valid. More precisely, +if `git check-ref-format --branch STRING' exits with a non-zero +status, then treat STRING as a regexp. + +Assuming the chosen branch matches these conditions you would end +up with with e.g.: + + feature --upstream--> origin/master + +instead of + + feature --upstream--> master --upstream--> origin/master + +Which you prefer is a matter of personal preference. If you do +prefer the former, then you should add branches such as \"master\", +\"next\", and \"maint\" to the value of this options." + :package-version '(magit . "2.4.0") + :group 'magit-commands + :type '(repeat string)) + +(defcustom magit-branch-adjust-remote-upstream-alist nil + "Alist of upstreams to be used when branching from remote branches. + +When creating a local branch from an ephemeral branch located +on a remote, e.g. a feature or hotfix branch, then that remote +branch should usually not be used as the upstream branch, since +the push-remote already allows accessing it and having both the +upstream and the push-remote reference the same related branch +would be wasteful. Instead a branch like \"maint\" or \"master\" +should be used as the upstream. + +This option allows specifying the branch that should be used as +the upstream when branching certain remote branches. The value +is an alist of the form ((UPSTREAM . RULE)...). The first +matching element is used, the following elements are ignored. + +UPSTREAM is the branch to be used as the upstream for branches +specified by RULE. It can be a local or a remote branch. + +RULE can either be a regular expression, matching branches whose +upstream should be the one specified by UPSTREAM. Or it can be +a list of the only branches that should *not* use UPSTREAM; all +other branches will. Matching is done after stripping the remote +part of the name of the branch that is being branched from. + +If you use a finite set of non-ephemeral branches across all your +repositories, then you might use something like: + + ((\"origin/master\" \"master\" \"next\" \"maint\")) + +Or if the names of all your ephemeral branches contain a slash, +at least in some repositories, then a good value could be: + + ((\"origin/master\" . \"/\")) + +Of course you can also fine-tune: + + ((\"origin/maint\" . \"\\\\\\=`hotfix/\") + (\"origin/master\" . \"\\\\\\=`feature/\")) + +If you use remote branches as UPSTREAM, then you might also want +to set `magit-branch-prefer-remote-upstream' to a non-nil value. +However, I recommend that you use local branches as UPSTREAM." + :package-version '(magit . "2.9.0") + :group 'magit-commands + :type '(repeat (cons (string :tag "Use upstream") + (choice :tag "for branches" + (regexp :tag "matching") + (repeat :tag "except" + (string :tag "branch")))))) + +(defcustom magit-branch-rename-push-target t + "Whether the push-remote setup is preserved when renaming a branch. + +The command `magit-branch-rename' renames a branch named OLD to +NEW. This option controls how much of the push-remote setup is +preserved when doing so. + +When nil, then preserve nothing and unset `branch.OLD.pushRemote'. + +When `local-only', then first set `branch.NEW.pushRemote' to the + same value as `branch.OLD.pushRemote', provided the latter is + actually set and unless the former already has another value. + +When t, then rename the branch named OLD on the remote specified + by `branch.OLD.pushRemote' to NEW, provided OLD exists on that + remote and unless NEW already exists on the remote. + +When `forge-only' and the `forge' package is available, then + behave like `t' if the remote points to a repository on a forge + (currently Github or Gitlab), otherwise like `local-only'. + +Another supported but obsolete value is `github-only'. It is a + misnomer because it now treated as an alias for `forge-only'." + :package-version '(magit . "2.90.0") + :group 'magit-commands + :type '(choice + (const :tag "Don't preserve push-remote setup" nil) + (const :tag "Preserve push-remote setup" local-only) + (const :tag "... and rename corresponding branch on remote" t) + (const :tag "... but only if remote is on a forge" forge-only))) + +(defcustom magit-branch-direct-configure t + "Whether the command `magit-branch' shows Git variables. +When set to nil, no variables are displayed by this transient +command, instead the sub-transient `magit-branch-configure' +has to be used to view and change branch related variables." + :package-version '(magit . "2.7.0") + :group 'magit-commands + :type 'boolean) + +(defcustom magit-published-branches '("origin/master") + "List of branches that are considered to be published." + :package-version '(magit . "2.13.0") + :group 'magit-commands + :type '(repeat string)) + +;;; Commands + +;;;###autoload (autoload 'magit-branch "magit" nil t) +(define-transient-command magit-branch (branch) + "Add, configure or remove a branch." + :man-page "git-branch" + ["Variables" + :if (lambda () + (and magit-branch-direct-configure + (oref transient--prefix scope))) + ("d" magit-branch..description) + ("u" magit-branch..merge/remote) + ("r" magit-branch..rebase) + ("p" magit-branch..pushRemote)] + [["Checkout" + ("b" "branch/revision" magit-checkout) + ("l" "local branch" magit-branch-checkout) + (6 "o" "new orphan" magit-branch-orphan)] + ["" + ("c" "new branch" magit-branch-and-checkout) + ("s" "new spin-off" magit-branch-spinoff) + (5 "w" "new worktree" magit-worktree-checkout)] + ["Create" + ("n" "new branch" magit-branch-create) + ("S" "new spin-out" magit-branch-spinout) + (5 "W" "new worktree" magit-worktree-branch)] + ["Do" + ("C" "configure..." magit-branch-configure) + ("m" "rename" magit-branch-rename) + ("x" "reset" magit-branch-reset) + ("k" "delete" magit-branch-delete)] + ["" + (7 "h" "shelve" magit-branch-shelve) + (7 "H" "unshelve" magit-branch-unshelve)]] + (interactive (list (magit-get-current-branch))) + (transient-setup 'magit-branch nil nil :scope branch)) + +;;;###autoload +(defun magit-checkout (revision) + "Checkout REVISION, updating the index and the working tree. +If REVISION is a local branch, then that becomes the current +branch. If it is something else, then `HEAD' becomes detached. +Checkout fails if the working tree or the staging area contain +changes. +\n(git checkout REVISION)." + (interactive (list (magit-read-other-branch-or-commit "Checkout"))) + (when (string-match "\\`heads/\\(.+\\)" revision) + (setq revision (match-string 1 revision))) + (magit-run-git "checkout" revision)) + +;;;###autoload +(defun magit-branch-create (branch start-point) + "Create BRANCH at branch or revision START-POINT." + (interactive (magit-branch-read-args "Create branch")) + (magit-call-git "branch" branch start-point) + (magit-branch-maybe-adjust-upstream branch start-point) + (magit-refresh)) + +;;;###autoload +(defun magit-branch-and-checkout (branch start-point) + "Create and checkout BRANCH at branch or revision START-POINT." + (interactive (magit-branch-read-args "Create and checkout branch")) + (if (string-match-p "^stash@{[0-9]+}$" start-point) + (magit-run-git "stash" "branch" branch start-point) + (magit-call-git "checkout" "-b" branch start-point) + (magit-branch-maybe-adjust-upstream branch start-point) + (magit-refresh))) + +;;;###autoload +(defun magit-branch-or-checkout (arg &optional start-point) + "Hybrid between `magit-checkout' and `magit-branch-and-checkout'. + +Ask the user for an existing branch or revision. If the user +input actually can be resolved as a branch or revision, then +check that out, just like `magit-checkout' would. + +Otherwise create and checkout a new branch using the input as +its name. Before doing so read the starting-point for the new +branch. This is similar to what `magit-branch-and-checkout' +does." + (interactive + (let ((arg (magit-read-other-branch-or-commit "Checkout"))) + (list arg + (and (not (magit-commit-p arg)) + (magit-read-starting-point "Create and checkout branch" arg))))) + (when (string-match "\\`heads/\\(.+\\)" arg) + (setq arg (match-string 1 arg))) + (if start-point + (magit-branch-and-checkout arg start-point) + (magit-checkout arg))) + +;;;###autoload +(defun magit-branch-checkout (branch &optional start-point) + "Checkout an existing or new local branch. + +Read a branch name from the user offering all local branches and +a subset of remote branches as candidates. Omit remote branches +for which a local branch by the same name exists from the list +of candidates. The user can also enter a completely new branch +name. + +- If the user selects an existing local branch, then check that + out. + +- If the user selects a remote branch, then create and checkout + a new local branch with the same name. Configure the selected + remote branch as push target. + +- If the user enters a new branch name, then create and check + that out, after also reading the starting-point from the user. + +In the latter two cases the upstream is also set. Whether it is +set to the chosen START-POINT or something else depends on the +value of `magit-branch-adjust-remote-upstream-alist', just like +when using `magit-branch-and-checkout'." + (interactive + (let* ((current (magit-get-current-branch)) + (local (magit-list-local-branch-names)) + (remote (--filter (and (string-match "[^/]+/" it) + (not (member (substring it (match-end 0)) + (cons "HEAD" local)))) + (magit-list-remote-branch-names))) + (choices (nconc (delete current local) remote)) + (atpoint (magit-branch-at-point)) + (choice (magit-completing-read + "Checkout branch" choices + nil nil nil 'magit-revision-history + (or (car (member atpoint choices)) + (and atpoint + (car (member (and (string-match "[^/]+/" atpoint) + (substring atpoint (match-end 0))) + choices))))))) + (cond ((member choice remote) + (list (and (string-match "[^/]+/" choice) + (substring choice (match-end 0))) + choice)) + ((member choice local) + (list choice)) + (t + (list choice (magit-read-starting-point "Create" choice)))))) + (if (not start-point) + (magit-checkout branch) + (when (magit-anything-modified-p) + (user-error "Cannot checkout when there are uncommitted changes")) + (magit-branch-and-checkout branch start-point) + (when (magit-remote-branch-p start-point) + (pcase-let ((`(,remote . ,remote-branch) + (magit-split-branch-name start-point))) + (when (and (equal branch remote-branch) + (not (equal remote (magit-get "remote.pushDefault")))) + (magit-set remote "branch" branch "pushRemote")))))) + +(defun magit-branch-maybe-adjust-upstream (branch start-point) + (--when-let + (or (and (magit-get-upstream-branch branch) + (magit-get-indirect-upstream-branch start-point)) + (and (magit-remote-branch-p start-point) + (let ((name (cdr (magit-split-branch-name start-point)))) + (car (--first (if (listp (cdr it)) + (not (member name (cdr it))) + (string-match-p (cdr it) name)) + magit-branch-adjust-remote-upstream-alist))))) + (magit-call-git "branch" (concat "--set-upstream-to=" it) branch))) + +;;;###autoload +(defun magit-branch-orphan (branch start-point) + "Create and checkout an orphan BRANCH with contents from revision START-POINT." + (interactive (magit-branch-read-args "Create and checkout orphan branch")) + (magit-run-git "checkout" "--orphan" branch start-point)) + +(defun magit-branch-read-args (prompt &optional default-start) + (if magit-branch-read-upstream-first + (let ((choice (magit-read-starting-point prompt nil default-start))) + (if (magit-rev-verify choice) + (list (magit-read-string-ns + (if magit-completing-read--silent-default + (format "%s (starting at `%s')" prompt choice) + "Name for new branch") + (let ((def (mapconcat #'identity + (cdr (split-string choice "/")) + "/"))) + (and (member choice (magit-list-remote-branch-names)) + (not (member def (magit-list-local-branch-names))) + def))) + choice) + (if (eq magit-branch-read-upstream-first 'fallback) + (list choice + (magit-read-starting-point prompt choice default-start)) + (user-error "Not a valid starting-point: %s" choice)))) + (let ((branch (magit-read-string-ns (concat prompt " named")))) + (list branch (magit-read-starting-point prompt branch default-start))))) + +;;;###autoload +(defun magit-branch-spinout (branch &optional from) + "Create new branch from the unpushed commits. +Like `magit-branch-spinoff' but remain on the current branch. +If there are any uncommitted changes, then behave exactly like +`magit-branch-spinoff'." + (interactive (list (magit-read-string-ns "Spin out branch") + (car (last (magit-region-values 'commit))))) + (magit--branch-spinoff branch from nil)) + +;;;###autoload +(defun magit-branch-spinoff (branch &optional from) + "Create new branch from the unpushed commits. + +Create and checkout a new branch starting at and tracking the +current branch. That branch in turn is reset to the last commit +it shares with its upstream. If the current branch has no +upstream or no unpushed commits, then the new branch is created +anyway and the previously current branch is not touched. + +This is useful to create a feature branch after work has already +began on the old branch (likely but not necessarily \"master\"). + +If the current branch is a member of the value of option +`magit-branch-prefer-remote-upstream' (which see), then the +current branch will be used as the starting point as usual, but +the upstream of the starting-point may be used as the upstream +of the new branch, instead of the starting-point itself. + +If optional FROM is non-nil, then the source branch is reset +to `FROM~', instead of to the last commit it shares with its +upstream. Interactively, FROM is only ever non-nil, if the +region selects some commits, and among those commits, FROM is +the commit that is the fewest commits ahead of the source +branch. + +The commit at the other end of the selection actually does not +matter, all commits between FROM and `HEAD' are moved to the new +branch. If FROM is not reachable from `HEAD' or is reachable +from the source branch's upstream, then an error is raised." + (interactive (list (magit-read-string-ns "Spin off branch") + (car (last (magit-region-values 'commit))))) + (magit--branch-spinoff branch from t)) + +(defun magit--branch-spinoff (branch from checkout) + (when (magit-branch-p branch) + (user-error "Cannot spin off %s. It already exists" branch)) + (when (and (not checkout) + (magit-anything-modified-p)) + (message "Staying on HEAD due to uncommitted changes") + (setq checkout t)) + (if-let ((current (magit-get-current-branch))) + (let ((tracked (magit-get-upstream-branch current)) + base) + (when from + (unless (magit-rev-ancestor-p from current) + (user-error "Cannot spin off %s. %s is not reachable from %s" + branch from current)) + (when (and tracked + (magit-rev-ancestor-p from tracked)) + (user-error "Cannot spin off %s. %s is ancestor of upstream %s" + branch from tracked))) + (let ((magit-process-raise-error t)) + (if checkout + (magit-call-git "checkout" "-b" branch current) + (magit-call-git "branch" branch current))) + (--when-let (magit-get-indirect-upstream-branch current) + (magit-call-git "branch" "--set-upstream-to" it branch)) + (when (and tracked + (setq base + (if from + (concat from "^") + (magit-git-string "merge-base" current tracked))) + (not (magit-rev-eq base current))) + (if checkout + (magit-call-git "update-ref" "-m" + (format "reset: moving to %s" base) + (concat "refs/heads/" current) base) + (magit-call-git "reset" "--hard" base)))) + (if checkout + (magit-call-git "checkout" "-b" branch) + (magit-call-git "branch" branch))) + (magit-refresh)) + +;;;###autoload +(defun magit-branch-reset (branch to &optional set-upstream) + "Reset a branch to the tip of another branch or any other commit. + +When the branch being reset is the current branch, then do a +hard reset. If there are any uncommitted changes, then the user +has to confirm the reset because those changes would be lost. + +This is useful when you have started work on a feature branch but +realize it's all crap and want to start over. + +When resetting to another branch and a prefix argument is used, +then also set the target branch as the upstream of the branch +that is being reset." + (interactive + (let* ((atpoint (magit-local-branch-at-point)) + (branch (magit-read-local-branch "Reset branch" atpoint))) + (list branch + (magit-completing-read (format "Reset %s to" branch) + (delete branch (magit-list-branch-names)) + nil nil nil 'magit-revision-history + (or (and (not (equal branch atpoint)) atpoint) + (magit-get-upstream-branch branch))) + current-prefix-arg))) + (let ((inhibit-magit-refresh t)) + (if (equal branch (magit-get-current-branch)) + (if (and (magit-anything-modified-p) + (not (yes-or-no-p + "Uncommitted changes will be lost. Proceed? "))) + (user-error "Abort") + (magit-reset-hard to)) + (magit-call-git "update-ref" + "-m" (format "reset: moving to %s" to) + (magit-git-string "rev-parse" "--symbolic-full-name" + branch) + to)) + (when (and set-upstream (magit-branch-p to)) + (magit-set-upstream-branch branch to) + (magit-branch-maybe-adjust-upstream branch to))) + (magit-refresh)) + +;;;###autoload +(defun magit-branch-delete (branches &optional force) + "Delete one or multiple branches. +If the region marks multiple branches, then offer to delete +those, otherwise prompt for a single branch to be deleted, +defaulting to the branch at point." + ;; One would expect this to be a command as simple as, for example, + ;; `magit-branch-rename'; but it turns out everyone wants to squeeze + ;; a bit of extra functionality into this one, including myself. + (interactive + (let ((branches (magit-region-values 'branch t)) + (force current-prefix-arg)) + (if (> (length branches) 1) + (magit-confirm t nil "Delete %i branches" nil branches) + (setq branches + (list (magit-read-branch-prefer-other + (if force "Force delete branch" "Delete branch"))))) + (unless force + (when-let ((unmerged (-remove #'magit-branch-merged-p branches))) + (if (magit-confirm 'delete-unmerged-branch + "Delete unmerged branch %s" + "Delete %i unmerged branches" + 'noabort unmerged) + (setq force branches) + (or (setq branches (-difference branches unmerged)) + (user-error "Abort"))))) + (list branches force))) + (let* ((refs (mapcar #'magit-ref-fullname branches)) + (ambiguous (--remove it refs))) + (when ambiguous + (user-error + "%s ambiguous. Please cleanup using git directly." + (let ((len (length ambiguous))) + (cond + ((= len 1) + (format "%s is" (-first #'magit-ref-ambiguous-p branches))) + ((= len (length refs)) + (format "These %s names are" len)) + (t + (format "%s of these names are" len)))))) + (cond + ((string-match "^refs/remotes/\\([^/]+\\)" (car refs)) + (let* ((remote (match-string 1 (car refs))) + (offset (1+ (length remote)))) + ;; Assume the branches actually still exists on the remote. + (magit-run-git-async + "push" remote (--map (concat ":" (substring it offset)) branches)) + ;; If that is not the case, then this deletes the tracking branches. + (set-process-sentinel + magit-this-process + (apply-partially 'magit-delete-remote-branch-sentinel remote refs)))) + ((> (length branches) 1) + (setq branches (delete (magit-get-current-branch) branches)) + (mapc 'magit-branch-maybe-delete-pr-remote branches) + (mapc 'magit-branch-unset-pushRemote branches) + (magit-run-git "branch" (if force "-D" "-d") branches)) + (t ; And now for something completely different. + (let* ((branch (car branches)) + (prompt (format "Branch %s is checked out. " branch))) + (when (equal branch (magit-get-current-branch)) + (pcase (if (or (equal branch "master") + (not (magit-rev-verify "master"))) + (magit-read-char-case prompt nil + (?d "[d]etach HEAD & delete" 'detach) + (?a "[a]bort" 'abort)) + (magit-read-char-case prompt nil + (?d "[d]etach HEAD & delete" 'detach) + (?c "[c]heckout master & delete" 'master) + (?a "[a]bort" 'abort))) + (`detach (unless (or (equal force '(4)) + (member branch force) + (magit-branch-merged-p branch t)) + (magit-confirm 'delete-unmerged-branch + "Delete unmerged branch %s" "" + nil (list branch))) + (magit-call-git "checkout" "--detach")) + (`master (unless (or (equal force '(4)) + (member branch force) + (magit-branch-merged-p branch "master")) + (magit-confirm 'delete-unmerged-branch + "Delete unmerged branch %s" "" + nil (list branch))) + (magit-call-git "checkout" "master")) + (`abort (user-error "Abort"))) + (setq force t)) + (magit-branch-maybe-delete-pr-remote branch) + (magit-branch-unset-pushRemote branch) + (magit-run-git "branch" (if force "-D" "-d") branch)))))) + +(put 'magit-branch-delete 'interactive-only t) + +(defun magit-branch-maybe-delete-pr-remote (branch) + (when-let ((remote (magit-get "branch" branch "pullRequestRemote"))) + (let* ((variable (format "remote.%s.fetch" remote)) + (refspecs (magit-get-all variable))) + (unless (member (format "+refs/heads/*:refs/remotes/%s/*" remote) + refspecs) + (let ((refspec + (if (equal (magit-get "branch" branch "pushRemote") remote) + (format "+refs/heads/%s:refs/remotes/%s/%s" + branch remote branch) + (let ((merge (magit-get "branch" branch "merge"))) + (and merge + (string-prefix-p "refs/heads/" merge) + (setq merge (substring merge 11)) + (format "+refs/heads/%s:refs/remotes/%s/%s" + merge remote merge)))))) + (when (member refspec refspecs) + (if (and (= (length refspecs) 1) + (magit-confirm 'delete-pr-remote + (format "Also delete remote %s (%s)" remote + "no pull-request branch remains") + nil t)) + (magit-call-git "remote" "rm" remote) + (magit-call-git "config" "--unset-all" variable + (format "^%s$" (regexp-quote refspec)))))))))) + +(defun magit-branch-unset-pushRemote (branch) + (magit-set nil "branch" branch "pushRemote")) + +(defun magit-delete-remote-branch-sentinel (remote refs process event) + (when (memq (process-status process) '(exit signal)) + (if (= (process-exit-status process) 1) + (if-let ((on-remote (--map (concat "refs/remotes/" remote "/" it) + (magit-remote-list-branches remote))) + (rest (--filter (and (not (member it on-remote)) + (magit-ref-exists-p it)) + refs))) + (progn + (process-put process 'inhibit-refresh t) + (magit-process-sentinel process event) + (setq magit-this-error nil) + (message "Some remote branches no longer exist. %s" + "Deleting just the local tracking refs instead...") + (dolist (ref rest) + (magit-call-git "update-ref" "-d" ref)) + (magit-refresh) + (message "Deleting local remote-tracking refs...done")) + (magit-process-sentinel process event)) + (magit-process-sentinel process event)))) + +;;;###autoload +(defun magit-branch-rename (old new &optional force) + "Rename the branch named OLD to NEW. + +With a prefix argument FORCE, rename even if a branch named NEW +already exists. + +If `branch.OLD.pushRemote' is set, then unset it. Depending on +the value of `magit-branch-rename-push-target' (which see) maybe +set `branch.NEW.pushRemote' and maybe rename the push-target on +the remote." + (interactive + (let ((branch (magit-read-local-branch "Rename branch"))) + (list branch + (magit-read-string-ns (format "Rename branch '%s' to" branch) + nil 'magit-revision-history) + current-prefix-arg))) + (when (string-match "\\`heads/\\(.+\\)" old) + (setq old (match-string 1 old))) + (when (equal old new) + (user-error "Old and new branch names are the same")) + (magit-call-git "branch" (if force "-M" "-m") old new) + (when magit-branch-rename-push-target + (let ((remote (magit-get-push-remote old)) + (old-specific (magit-get "branch" old "pushRemote")) + (new-specific (magit-get "branch" new "pushRemote"))) + (when (and old-specific (or force (not new-specific))) + ;; Keep the target setting branch specific, even if that is + ;; redundant. But if a branch by the same name existed before + ;; and the rename isn't forced, then do not change a leftover + ;; setting. Such a leftover setting may or may not conform to + ;; what we expect here... + (magit-set old-specific "branch" new "pushRemote")) + (when (and (equal (magit-get-push-remote new) remote) + ;; ...and if it does not, then we must abort. + (not (eq magit-branch-rename-push-target 'local-only)) + (or (not (memq magit-branch-rename-push-target + '(forge-only github-only))) + (and (require (quote forge) nil t) + (fboundp 'forge--forge-remote-p) + (forge--forge-remote-p remote)))) + (let ((old-target (magit-get-push-branch old t)) + (new-target (magit-get-push-branch new t)) + (remote (magit-get-push-remote new))) + (when (and old-target + (not new-target) + (magit-y-or-n-p (format "Also rename %S to %S on \"%s\"" + old new remote))) + ;; Rename on (i.e. within) the remote, but only if the + ;; destination ref doesn't exist yet. If that ref already + ;; exists, then it probably is of some value and we better + ;; not touch it. Ignore what the local ref points at, + ;; i.e. if the local and the remote ref didn't point at + ;; the same commit before the rename then keep it that way. + (magit-call-git "push" "-v" remote + (format "%s:refs/heads/%s" old-target new) + (format ":refs/heads/%s" old))))))) + (magit-branch-unset-pushRemote old) + (magit-refresh)) + +;;;###autoload +(defun magit-branch-shelve (branch) + "Shelve a BRANCH. +Rename \"refs/heads/BRANCH\" to \"refs/shelved/BRANCH\", +and also rename the respective reflog file." + (interactive (list (magit-read-other-local-branch "Shelve branch"))) + (let ((old (concat "refs/heads/" branch)) + (new (concat "refs/shelved/" branch))) + (magit-git "update-ref" new old "") + (magit--rename-reflog-file old new) + (magit-branch-unset-pushRemote branch) + (magit-run-git "branch" "-D" branch))) + +;;;###autoload +(defun magit-branch-unshelve (branch) + "Unshelve a BRANCH +Rename \"refs/shelved/BRANCH\" to \"refs/heads/BRANCH\", +and also rename the respective reflog file." + (interactive + (list (magit-completing-read + "Unshelve branch" + (--map (substring it 8) + (magit-list-refnames "refs/shelved")) + nil t))) + (let ((old (concat "refs/shelved/" branch)) + (new (concat "refs/heads/" branch))) + (magit-git "update-ref" new old "") + (magit--rename-reflog-file old new) + (magit-run-git "update-ref" "-d" old))) + +(defun magit--rename-reflog-file (old new) + (let ((old (magit-git-dir (concat "logs/" old))) + (new (magit-git-dir (concat "logs/" new)))) + (when (file-exists-p old) + (make-directory (file-name-directory new) t) + (rename-file old new t)))) + +;;; Configure + +;;;###autoload (autoload 'magit-branch-configure "magit-branch" nil t) +(define-transient-command magit-branch-configure (branch) + "Configure a branch." + :man-page "git-branch" + [:description + (lambda () + (concat + (propertize "Configure " 'face 'transient-heading) + (propertize (oref transient--prefix scope) 'face 'magit-branch-local))) + ("d" magit-branch..description) + ("u" magit-branch..merge/remote) + ("r" magit-branch..rebase) + ("p" magit-branch..pushRemote)] + ["Configure repository defaults" + ("R" magit-pull.rebase) + ("P" magit-remote.pushDefault)] + ["Configure branch creation" + ("a m" magit-branch.autoSetupMerge) + ("a r" magit-branch.autoSetupRebase)] + (interactive + (list (or (and (not current-prefix-arg) + (not (and magit-branch-direct-configure + (eq current-transient-command 'magit-branch))) + (magit-get-current-branch)) + (magit--read-branch-scope)))) + (transient-setup 'magit-branch-configure nil nil :scope branch)) + +(defun magit--read-branch-scope (&optional obj) + (magit-read-local-branch + (if obj + (format "Set %s for branch" + (format (oref obj variable) "")) + "Configure branch"))) + +(define-suffix-command magit-branch..description (branch) + "Edit the description of BRANCH." + :class 'magit--git-variable + :transient nil + :variable "branch.%s.description" + (interactive (list (oref current-transient-prefix scope))) + (magit-run-git-with-editor "branch" "--edit-description" branch)) + +(add-hook 'find-file-hook 'magit-branch-description-check-buffers) + +(defun magit-branch-description-check-buffers () + (and buffer-file-name + (string-match-p "/\\(BRANCH\\|EDIT\\)_DESCRIPTION\\'" buffer-file-name))) + +(defclass magit--git-branch:upstream (magit--git-variable) + ((format :initform " %k %m %M\n %r %R"))) + +(define-infix-command magit-branch..merge/remote () + :class 'magit--git-branch:upstream) + +(cl-defmethod transient-init-value ((obj magit--git-branch:upstream)) + (when-let ((branch (oref transient--prefix scope)) + (remote (magit-get "branch" branch "remote")) + (merge (magit-get "branch" branch "merge"))) + (oset obj value (list remote merge)))) + +(cl-defmethod transient-infix-read ((obj magit--git-branch:upstream)) + (if (oref obj value) + (oset obj value nil) + (magit-read-upstream-branch (oref transient--prefix scope) "Upstream"))) + +(cl-defmethod transient-infix-set ((obj magit--git-branch:upstream) refname) + (magit-set-upstream-branch (oref transient--prefix scope) refname) + (oset obj value + (let ((branch (oref transient--prefix scope))) + (when-let ((r (magit-get "branch" branch "remote")) + (m (magit-get "branch" branch "merge"))) + (list r m)))) + (magit-refresh)) + +(cl-defmethod transient-format ((obj magit--git-branch:upstream)) + (let ((branch (oref transient--prefix scope))) + (format-spec + (oref obj format) + `((?k . ,(transient-format-key obj)) + (?r . ,(format "branch.%s.remote" branch)) + (?m . ,(format "branch.%s.merge" branch)) + (?R . ,(transient-format-value obj #'car)) + (?M . ,(transient-format-value obj #'cadr)))))) + +(cl-defmethod transient-format-value ((obj magit--git-branch:upstream) key) + (if-let ((value (funcall key (oref obj value)))) + (propertize value 'face 'transient-argument) + (propertize "unset" 'face 'transient-inactive-argument))) + +(define-infix-command magit-branch..rebase () + :class 'magit--git-variable:choices + :scope 'magit--read-branch-scope + :variable "branch.%s.rebase" + :fallback "pull.rebase" + :choices '("true" "false") + :default "false") + +(define-infix-command magit-branch..pushRemote () + :class 'magit--git-variable:choices + :scope 'magit--read-branch-scope + :variable "branch.%s.pushRemote" + :fallback "remote.pushDefault" + :choices 'magit-list-remotes) + +(define-infix-command magit-pull.rebase () + :class 'magit--git-variable:choices + :variable "pull.rebase" + :choices '("true" "false") + :default "false") + +(define-infix-command magit-remote.pushDefault () + :class 'magit--git-variable:choices + :variable "remote.pushDefault" + :choices 'magit-list-remotes) + +(define-infix-command magit-branch.autoSetupMerge () + :class 'magit--git-variable:choices + :variable "branch.autoSetupMerge" + :choices '("always" "true" "false") + :default "true") + +(define-infix-command magit-branch.autoSetupRebase () + :class 'magit--git-variable:choices + :variable "branch.autoSetupRebase" + :choices '("always" "local" "remote" "never") + :default "never") + +;;; _ +(provide 'magit-branch) +;;; magit-branch.el ends here diff --git a/elpa/magit-20191122.2040/magit-branch.elc b/elpa/magit-20191122.2040/magit-branch.elc new file mode 100644 index 0000000000000000000000000000000000000000..2fb16ccebc328fd08a9d82107e61338dd1b46851 GIT binary patch literal 37160 zcmeHw3wK*bk{+oC<>8#{BRM-WNj4{~s|QJ&pn!{)DBH87DcV-XvJ{dYpFM^gfxsn+ z5eQ�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 +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; This library implements clone commands. + +;;; Code: + +(require 'magit) + +;;; Options + +(defcustom magit-clone-set-remote-head nil + "Whether cloning creates the symbolic-ref `/HEAD'." + :package-version '(magit . "2.4.2") + :group 'magit-commands + :type 'boolean) + +(defcustom magit-clone-set-remote.pushDefault 'ask + "Whether to set the value of `remote.pushDefault' after cloning. + +If t, then set without asking. If nil, then don't set. If +`ask', then ask." + :package-version '(magit . "2.4.0") + :group 'magit-commands + :type '(choice (const :tag "set" t) + (const :tag "ask" ask) + (const :tag "don't set" nil))) + +(defcustom magit-clone-default-directory nil + "Default directory to use when `magit-clone' reads destination. +If nil (the default), then use the value of `default-directory'. +If a directory, then use that. If a function, then call that +with the remote url as only argument and use the returned value." + :package-version '(magit . "2.90.0") + :group 'magit-commands + :type '(choice (const :tag "value of default-directory") + (directory :tag "constant directory") + (function :tag "function's value"))) + +(defcustom magit-clone-always-transient nil + "Whether `magit-clone' always acts as a transient prefix command. +If nil, then a prefix argument has to be used to show the transient +popup instead of invoking the default suffix `magit-clone-regular' +directly." + :package-version '(magit . "2.91.0") + :group 'magit-commands + :type 'boolean) + +(defcustom magit-clone-name-alist + '(("\\`\\(?:github:\\|gh:\\)?\\([^:]+\\)\\'" "github.com" "github.user") + ("\\`\\(?:gitlab:\\|gl:\\)\\([^:]+\\)\\'" "gitlab.com" "gitlab.user")) + "Alist mapping repository names to repository urls. + +Each element has the form (REGEXP HOSTNAME USER). When the user +enters a name when a cloning command asks for a name or url, then +that is looked up in this list. The first element whose REGEXP +matches is used. + +The format specified by option `magit-clone-url-format' is used +to turn the name into an url, using HOSTNAME and the repository +name. If the provided name contains a slash, then that is used. +Otherwise if the name omits the owner of the repository, then the +default user specified in the matched entry is used. + +If USER contains a dot, then it is treated as a Git variable and +the value of that is used as the username. Otherwise it is used +as the username itself." + :package-version '(magit . "2.91.0") + :group 'magit-commands + :type '(repeat (list regexp + (string :tag "hostname") + (string :tag "user name or git variable")))) + +(defcustom magit-clone-url-format "git@%h:%n.git" + "Format used when turning repository names into urls. +%h is the hostname and %n is the repository name, including +the name of the owner. Also see `magit-clone-name-alist'." + :package-version '(magit . "2.91.0") + :group 'magit-commands + :type 'regexp) + +;;; Commands + +;;;###autoload (autoload 'magit-clone "magit-clone" nil t) +(define-transient-command magit-clone (&optional transient) + "Clone a repository." + :man-page "git-clone" + ["Fetch arguments" + ("-B" "Clone a single branch" "--single-branch") + ("-n" "Do not clone tags" "--no-tags") + ("-S" "Clones submodules" "--recurse-submodules" :level 6) + ("-l" "Do not optimize" "--no-local" :level 7)] + ["Setup arguments" + ("-o" "Set name of remote" ("-o" "--origin=")) + ("-b" "Set HEAD branch" ("-b" "--branch=")) + ("-g" "Separate git directory" "--separate-git-dir=" + transient-read-directory :level 7) + ("-t" "Use template directory" "--template=" + transient-read-existing-directory :level 6)] + ["Local sharing arguments" + ("-s" "Share objects" ("-s" "--shared" :level 7)) + ("-h" "Do not use hardlinks" "--no-hardlinks")] + ["Clone" + ("C" "regular" magit-clone-regular) + ("s" "shallow" magit-clone-shallow) + ("d" "shallow since date" magit-clone-shallow-since :level 7) + ("e" "shallow excluding" magit-clone-shallow-exclude :level 7) + ("b" "bare" magit-clone-bare) + ("m" "mirror" magit-clone-mirror)] + (interactive (list (or magit-clone-always-transient current-prefix-arg))) + (if transient + (transient-setup #'magit-clone) + (call-interactively #'magit-clone-regular))) + +;;;###autoload +(defun magit-clone-regular (repository directory args) + "Create a clone of REPOSITORY in DIRECTORY. +Then show the status buffer for the new repository." + (interactive (magit-clone-read-args)) + (magit-clone-internal repository directory args)) + +;;;###autoload +(defun magit-clone-shallow (repository directory args depth) + "Create a shallow clone of REPOSITORY in DIRECTORY. +Then show the status buffer for the new repository. +With a prefix argument read the DEPTH of the clone; +otherwise use 1." + (interactive (append (magit-clone-read-args) + (list (if current-prefix-arg + (read-number "Depth: " 1) + 1)))) + (magit-clone-internal repository directory + (cons (format "--depth=%s" depth) args))) + +;;;###autoload +(defun magit-clone-shallow-since (repository directory args date) + "Create a shallow clone of REPOSITORY in DIRECTORY. +Then show the status buffer for the new repository. +Exclude commits before DATE, which is read from the +user." + (interactive (append (magit-clone-read-args) + (list (transient-read-date "Exclude commits before: " + nil nil)))) + (magit-clone-internal repository directory + (cons (format "--shallow-since=%s" date) args))) + +;;;###autoload +(defun magit-clone-shallow-exclude (repository directory args exclude) + "Create a shallow clone of REPOSITORY in DIRECTORY. +Then show the status buffer for the new repository. +Exclude commits reachable from EXCLUDE, which is a +branch or tag read from the user." + (interactive (append (magit-clone-read-args) + (list (read-string "Exclude commits reachable from: ")))) + (magit-clone-internal repository directory + (cons (format "--shallow-exclude=%s" exclude) args))) + +;;;###autoload +(defun magit-clone-bare (repository directory args) + "Create a bare clone of REPOSITORY in DIRECTORY. +Then show the status buffer for the new repository." + (interactive (magit-clone-read-args)) + (magit-clone-internal repository directory (cons "--bare" args))) + +;;;###autoload +(defun magit-clone-mirror (repository directory args) + "Create a mirror of REPOSITORY in DIRECTORY. +Then show the status buffer for the new repository." + (interactive (magit-clone-read-args)) + (magit-clone-internal repository directory (cons "--mirror" args))) + +(defun magit-clone-internal (repository directory args) + (run-hooks 'magit-credential-hook) + (setq directory (file-name-as-directory (expand-file-name directory))) + (magit-run-git-async "clone" args "--" repository + (magit-convert-filename-for-git directory)) + ;; Don't refresh the buffer we're calling from. + (process-put magit-this-process 'inhibit-refresh t) + (set-process-sentinel + magit-this-process + (lambda (process event) + (when (memq (process-status process) '(exit signal)) + (let ((magit-process-raise-error t)) + (magit-process-sentinel process event))) + (when (and (eq (process-status process) 'exit) + (= (process-exit-status process) 0)) + (unless (memq (car args) '("--bare" "--mirror")) + (let ((default-directory directory)) + (when (or (eq magit-clone-set-remote.pushDefault t) + (and magit-clone-set-remote.pushDefault + (y-or-n-p "Set `remote.pushDefault' to \"origin\"? "))) + (setf (magit-get "remote.pushDefault") "origin")) + (unless magit-clone-set-remote-head + (magit-remote-unset-head "origin")))) + (with-current-buffer (process-get process 'command-buf) + (magit-status-setup-buffer directory)))))) + +(defun magit-clone-read-args () + (let ((repo (magit-clone-read-repository))) + (list repo + (read-directory-name + "Clone to: " + (if (functionp magit-clone-default-directory) + (funcall magit-clone-default-directory repo) + magit-clone-default-directory) + nil nil + (and (string-match "\\([^/:]+?\\)\\(/?\\.git\\)?$" repo) + (match-string 1 repo))) + (transient-args 'magit-clone)))) + +(defun magit-clone-read-repository () + (magit-read-char-case "Clone from " nil + (?u "[u]rl or name" + (let ((str (magit-read-string-ns "Clone from url or name"))) + (if (string-match-p "\\(://\\|@\\)" str) + str + (magit-clone--name-to-url str)))) + (?p "[p]ath" + (read-directory-name "Clone repository: ")) + (?l "or [l]ocal url" + (concat "file://" (read-directory-name "Clone repository: file://"))))) + +(defun magit-clone--name-to-url (name) + (or (-some + (pcase-lambda (`(,re ,host ,user)) + (and (string-match re name) + (let ((repo (match-string 1 name))) + (format-spec + magit-clone-url-format + `((?h . ,host) + (?n . ,(if (string-match-p "/" repo) + repo + (if (string-match-p "\\." user) + (if-let ((user (magit-get user))) + (concat user "/" repo) + (user-error + "Set %S or specify owner explicitly" user)) + (concat user "/" repo))))))))) + magit-clone-name-alist) + (user-error "Not an url and no matching entry in `%s'" + 'magit-clone-name-alist))) + +;;; _ +(provide 'magit-clone) +;;; magit-clone.el ends here diff --git a/elpa/magit-20191122.2040/magit-clone.elc b/elpa/magit-20191122.2040/magit-clone.elc new file mode 100644 index 0000000000000000000000000000000000000000..b4383bedb9447c9e912e8b1851190335c597361d GIT binary patch literal 11156 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 NpXk+yLbtfK_Aik*;8g$s literal 0 HcmV?d00001 diff --git a/elpa/magit-20191122.2040/magit-commit.el b/elpa/magit-20191122.2040/magit-commit.el new file mode 100644 index 00000000..6a560560 --- /dev/null +++ b/elpa/magit-20191122.2040/magit-commit.el @@ -0,0 +1,570 @@ +;;; magit-commit.el --- create Git commits -*- lexical-binding: t -*- + +;; Copyright (C) 2008-2019 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; This library implements commands for creating Git commits. These +;; commands just initiate the commit, support for writing the commit +;; messages is implemented in `git-commit.el'. + +;;; Code: + +(require 'magit) +(require 'magit-sequence) + +(eval-when-compile (require 'epa)) ; for `epa-protocol' +(eval-when-compile (require 'epg)) +(eval-when-compile (require 'subr-x)) + +;;; Options + +(defcustom magit-commit-ask-to-stage 'verbose + "Whether to ask to stage all unstaged changes when committing and nothing is staged." + :package-version '(magit . "2.3.0") + :group 'magit-commands + :type '(choice (const :tag "Ask" t) + (const :tag "Ask showing diff" verbose) + (const :tag "Stage without confirmation" stage) + (const :tag "Don't ask" nil))) + +(defcustom magit-commit-show-diff t + "Whether the relevant diff is automatically shown when committing." + :package-version '(magit . "2.3.0") + :group 'magit-commands + :type 'boolean) + +(defcustom magit-commit-extend-override-date t + "Whether using `magit-commit-extend' changes the committer date." + :package-version '(magit . "2.3.0") + :group 'magit-commands + :type 'boolean) + +(defcustom magit-commit-reword-override-date t + "Whether using `magit-commit-reword' changes the committer date." + :package-version '(magit . "2.3.0") + :group 'magit-commands + :type 'boolean) + +(defcustom magit-commit-squash-confirm t + "Whether the commit targeted by squash and fixup has to be confirmed. +When non-nil then the commit at point (if any) is used as default +choice, otherwise it has to be confirmed. This option only +affects `magit-commit-squash' and `magit-commit-fixup'. The +\"instant\" variants always require confirmation because making +an error while using those is harder to recover from." + :package-version '(magit . "2.1.0") + :group 'magit-commands + :type 'boolean) + +(defcustom magit-post-commit-hook nil + "Hook run after creating a commit without the user editing a message. + +This hook is run by `magit-refresh' if `this-command' is a member +of `magit-post-stage-hook-commands'. This only includes commands +named `magit-commit-*' that do *not* require that the user edits +the commit message in a buffer and then finishes by pressing +\\\\[with-editor-finish]. + +Also see `git-commit-post-finish-hook'." + :package-version '(magit . "2.90.0") + :group 'magit-commands + :type 'hook) + +(defvar magit-post-commit-hook-commands + '(magit-commit-extend + magit-commit-fixup + magit-commit-augment + magit-commit-instant-fixup + magit-commit-instant-squash)) + +;;; Popup + +;;;###autoload (autoload 'magit-commit "magit-commit" nil t) +(define-transient-command magit-commit () + "Create a new commit or replace an existing commit." + :info-manual "(magit)Initiating a Commit" + :man-page "git-commit" + ["Arguments" + ("-a" "Stage all modified and deleted files" ("-a" "--all")) + ("-e" "Allow empty commit" "--allow-empty") + ("-v" "Show diff of changes to be committed" ("-v" "--verbose")) + ("-n" "Disable hooks" ("-n" "--no-verify")) + ("-R" "Claim authorship and reset author date" "--reset-author") + (magit:--author :description "Override the author") + (7 "-D" "Override the author date" "--date=" transient-read-date) + ("-s" "Add Signed-off-by line" ("-s" "--signoff")) + (5 magit:--gpg-sign) + (magit-commit:--reuse-message)] + [["Create" + ("c" "Commit" magit-commit-create)] + ["Edit HEAD" + ("e" "Extend" magit-commit-extend) + ("w" "Reword" magit-commit-reword) + ("a" "Amend" magit-commit-amend) + (6 "n" "Reshelve" magit-commit-reshelve)] + ["Edit" + ("f" "Fixup" magit-commit-fixup) + ("s" "Squash" magit-commit-squash) + ("A" "Augment" magit-commit-augment) + (6 "x" "Absorb changes" magit-commit-absorb)] + ["" + ("F" "Instant fixup" magit-commit-instant-fixup) + ("S" "Instant squash" magit-commit-instant-squash)]] + (interactive) + (if-let ((buffer (magit-commit-message-buffer))) + (switch-to-buffer buffer) + (transient-setup 'magit-commit))) + +(defun magit-commit-arguments nil + (transient-args 'magit-commit)) + +(define-infix-argument magit:--gpg-sign () + :description "Sign using gpg" + :class 'transient-option + :shortarg "-S" + :argument "--gpg-sign=" + :allow-empty t + :reader 'magit-read-gpg-secret-key) + +(defvar magit-gpg-secret-key-hist nil) + +(defun magit-read-gpg-secret-key (prompt &optional initial-input history) + (require 'epa) + (let* ((keys (mapcar + (lambda (obj) + (let ((key (epg-sub-key-id (car (epg-key-sub-key-list obj)))) + (author + (when-let ((id-obj (car (epg-key-user-id-list obj)))) + (let ((id-str (epg-user-id-string id-obj))) + (if (stringp id-str) + id-str + (epg-decode-dn id-obj)))))) + (propertize key 'display (concat key " " author)))) + (epg-list-keys (epg-make-context epa-protocol) nil t))) + (choice (completing-read prompt keys nil nil nil + history nil initial-input))) + (set-text-properties 0 (length choice) nil choice) + choice)) + +(define-infix-argument magit-commit:--reuse-message () + :description "Reuse commit message" + :class 'transient-option + :shortarg "-C" + :argument "--reuse-message=" + :reader 'magit-read-reuse-message + :history-key 'magit-revision-history) + +(defun magit-read-reuse-message (prompt &optional default history) + (magit-completing-read prompt (magit-list-refnames) + nil nil nil history + (or default + (and (magit-rev-verify "ORIG_HEAD") + "ORIG_HEAD")))) + +;;; Commands + +;;;###autoload +(defun magit-commit-create (&optional args) + "Create a new commit on `HEAD'. +With a prefix argument, amend to the commit at `HEAD' instead. +\n(git commit [--amend] ARGS)" + (interactive (if current-prefix-arg + (list (cons "--amend" (magit-commit-arguments))) + (list (magit-commit-arguments)))) + (when (member "--all" args) + (setq this-command 'magit-commit-all)) + (when (setq args (magit-commit-assert args)) + (let ((default-directory (magit-toplevel))) + (magit-run-git-with-editor "commit" args)))) + +;;;###autoload +(defun magit-commit-amend (&optional args) + "Amend the last commit. +\n(git commit --amend ARGS)" + (interactive (list (magit-commit-arguments))) + (magit-commit-amend-assert) + (magit-run-git-with-editor "commit" "--amend" args)) + +;;;###autoload +(defun magit-commit-extend (&optional args override-date) + "Amend the last commit, without editing the message. + +With a prefix argument keep the committer date, otherwise change +it. The option `magit-commit-extend-override-date' can be used +to inverse the meaning of the prefix argument. \n(git commit +--amend --no-edit)" + (interactive (list (magit-commit-arguments) + (if current-prefix-arg + (not magit-commit-extend-override-date) + magit-commit-extend-override-date))) + (when (setq args (magit-commit-assert args (not override-date))) + (magit-commit-amend-assert) + (let ((process-environment process-environment)) + (unless override-date + (push (magit-rev-format "GIT_COMMITTER_DATE=%cD") process-environment)) + (magit-run-git-with-editor "commit" "--amend" "--no-edit" args)))) + +;;;###autoload +(defun magit-commit-reword (&optional args override-date) + "Reword the last commit, ignoring staged changes. + +With a prefix argument keep the committer date, otherwise change +it. The option `magit-commit-reword-override-date' can be used +to inverse the meaning of the prefix argument. + +Non-interactively respect the optional OVERRIDE-DATE argument +and ignore the option. +\n(git commit --amend --only)" + (interactive (list (magit-commit-arguments) + (if current-prefix-arg + (not magit-commit-reword-override-date) + magit-commit-reword-override-date))) + (magit-commit-amend-assert) + (let ((process-environment process-environment)) + (unless override-date + (push (magit-rev-format "GIT_COMMITTER_DATE=%cD") process-environment)) + (cl-pushnew "--allow-empty" args :test #'equal) + (magit-run-git-with-editor "commit" "--amend" "--only" args))) + +;;;###autoload +(defun magit-commit-fixup (&optional commit args) + "Create a fixup commit. + +With a prefix argument the target COMMIT has to be confirmed. +Otherwise the commit at point may be used without confirmation +depending on the value of option `magit-commit-squash-confirm'." + (interactive (list (magit-commit-at-point) + (magit-commit-arguments))) + (magit-commit-squash-internal "--fixup" commit args)) + +;;;###autoload +(defun magit-commit-squash (&optional commit args) + "Create a squash commit, without editing the squash message. + +With a prefix argument the target COMMIT has to be confirmed. +Otherwise the commit at point may be used without confirmation +depending on the value of option `magit-commit-squash-confirm'." + (interactive (list (magit-commit-at-point) + (magit-commit-arguments))) + (magit-commit-squash-internal "--squash" commit args)) + +;;;###autoload +(defun magit-commit-augment (&optional commit args) + "Create a squash commit, editing the squash message. + +With a prefix argument the target COMMIT has to be confirmed. +Otherwise the commit at point may be used without confirmation +depending on the value of option `magit-commit-squash-confirm'." + (interactive (list (magit-commit-at-point) + (magit-commit-arguments))) + (magit-commit-squash-internal "--squash" commit args nil t)) + +;;;###autoload +(defun magit-commit-instant-fixup (&optional commit args) + "Create a fixup commit targeting COMMIT and instantly rebase." + (interactive (list (magit-commit-at-point) + (magit-commit-arguments))) + (magit-commit-squash-internal "--fixup" commit args t)) + +;;;###autoload +(defun magit-commit-instant-squash (&optional commit args) + "Create a squash commit targeting COMMIT and instantly rebase." + (interactive (list (magit-commit-at-point) + (magit-commit-arguments))) + (magit-commit-squash-internal "--squash" commit args t)) + +(defun magit-commit-squash-internal + (option commit &optional args rebase edit confirmed) + (when-let ((args (magit-commit-assert args t))) + (when commit + (when (and rebase (not (magit-rev-ancestor-p commit "HEAD"))) + (magit-read-char-case + (format "%s isn't an ancestor of HEAD. " commit) nil + (?c "[c]reate without rebasing" (setq rebase nil)) + (?s "[s]elect other" (setq commit nil)) + (?a "[a]bort" (user-error "Quit"))))) + (when commit + (setq commit (magit-rebase-interactive-assert commit t))) + (if (and commit + (or confirmed + (not (or rebase + current-prefix-arg + magit-commit-squash-confirm)))) + (let ((magit-commit-show-diff nil)) + (push (concat option "=" commit) args) + (unless edit + (push "--no-edit" args)) + (if rebase + (magit-with-editor + (magit-call-git + "commit" "--no-gpg-sign" + (-remove-first + (apply-partially #'string-match-p "\\`--gpg-sign=") + args))) + (magit-run-git-with-editor "commit" args)) + t) ; The commit was created; used by below lambda. + (magit-log-select + (lambda (commit) + (when (and (magit-commit-squash-internal option commit args + rebase edit t) + rebase) + (magit-commit-amend-assert commit) + (magit-rebase-interactive-1 commit + (list "--autosquash" "--autostash" "--keep-empty") + "" "true" nil t))) + (format "Type %%p on a commit to %s into it," + (substring option 2)) + nil nil nil commit) + (when magit-commit-show-diff + (let ((magit-display-buffer-noselect t)) + (apply #'magit-diff-staged nil (magit-diff-arguments))))))) + +(defun magit-commit-amend-assert (&optional commit) + (--when-let (magit-list-publishing-branches commit) + (let ((m1 "This commit has already been published to ") + (m2 ".\nDo you really want to modify it")) + (magit-confirm 'amend-published + (concat m1 "%s" m2) + (concat m1 "%i public branches" m2) + nil it)))) + +(defun magit-commit-assert (args &optional strict) + (cond + ((or (magit-anything-staged-p) + (and (magit-anything-unstaged-p) + ;; ^ Everything of nothing is still nothing. + (member "--all" args)) + (and (not strict) + ;; ^ For amend variants that don't make sense otherwise. + (or (member "--amend" args) + (member "--allow-empty" args)))) + (or args (list "--"))) + ((and (magit-rebase-in-progress-p) + (not (magit-anything-unstaged-p)) + (y-or-n-p "Nothing staged. Continue in-progress rebase? ")) + (setq this-command 'magit-rebase-continue) + (magit-run-git-sequencer "rebase" "--continue") + nil) + ((and (file-exists-p (magit-git-dir "MERGE_MSG")) + (not (magit-anything-unstaged-p))) + (or args (list "--"))) + ((not (magit-anything-unstaged-p)) + (user-error "Nothing staged (or unstaged)")) + (magit-commit-ask-to-stage + (when (eq magit-commit-ask-to-stage 'verbose) + (magit-diff-unstaged)) + (prog1 (when (or (eq magit-commit-ask-to-stage 'stage) + (y-or-n-p "Nothing staged. Stage and commit all unstaged changes? ")) + (magit-run-git "add" "-u" ".") + (or args (list "--"))) + (when (and (eq magit-commit-ask-to-stage 'verbose) + (derived-mode-p 'magit-diff-mode)) + (magit-mode-bury-buffer)))) + (t + (user-error "Nothing staged")))) + +(defvar magit--reshelve-history nil) + +;;;###autoload +(defun magit-commit-reshelve (date) + "Change the committer date and possibly the author date of `HEAD'. + +If you are the author of `HEAD', then both dates are changed, +otherwise only the committer date. The current time is used +as the initial minibuffer input and the original author (if +that is you) or committer date is available as the previous +history element." + (interactive + (let ((author-p (magit-rev-author-p "HEAD"))) + (push (magit-rev-format (if author-p "%ad" "%cd") "HEAD" + (concat "--date=format:%F %T %z")) + magit--reshelve-history) + (list (read-string (if author-p + "Change author and committer dates to: " + "Change committer date to: ") + (cons (format-time-string "%F %T %z") 17) + 'magit--reshelve-history)))) + (let ((process-environment process-environment)) + (push (concat "GIT_COMMITTER_DATE=" date) process-environment) + (magit-run-git "commit" "--amend" "--no-edit" + (and (magit-rev-author-p "HEAD") + (concat "--date=" date))))) + +;;;###autoload (autoload 'magit-commit-absorb "magit-commit" nil t) +(define-transient-command magit-commit-absorb (phase commit args) + "Spread unstaged changes across recent commits. +With a prefix argument use a transient command to select infix +arguments. This command requires the git-autofixup script, which +is available from https://github.com/torbiak/git-autofixup." + ["Arguments" + (magit-autofixup:--context) + (magit-autofixup:--strict)] + ["Actions" + ("x" "Absorb" magit-commit-absorb)] + (interactive (if current-prefix-arg + (list 'transient nil nil) + (list 'select + (magit-get-upstream-branch) + (transient-args 'magit-commit-absorb)))) + (if (eq phase 'transient) + (transient-setup 'magit-commit-absorb) + (unless (executable-find "git-autofixup") + (user-error "This command requires the git-autofixup script, which %s" + "is available from https://github.com/torbiak/git-autofixup")) + (when (magit-anything-staged-p) + (user-error "Cannot absorb when there are staged changes")) + (unless (magit-anything-unstaged-p) + (user-error "There are no unstaged changes that could be absorbed")) + (when commit + (setq commit (magit-rebase-interactive-assert commit t))) + (if (and commit (eq phase 'run)) + (progn (magit-run-git-async "autofixup" "-vv" args commit) t) + (magit-log-select + (lambda (commit) + (with-no-warnings ; about non-interactive use + (magit-commit-absorb 'run commit args))) + nil nil nil nil commit)))) + +(define-infix-argument magit-autofixup:--context () + :description "Diff context lines" + :class 'transient-option + :shortarg "-c" + :argument "--context=" + :reader 'transient-read-number-N0) + +(define-infix-argument magit-autofixup:--strict () + :description "Strictness" + :class 'transient-option + :shortarg "-s" + :argument "--strict=" + :reader 'transient-read-number-N0) + +;;; Pending Diff + +(defun magit-commit-diff () + (when (and git-commit-mode magit-commit-show-diff) + (when-let ((diff-buffer (magit-get-mode-buffer 'magit-diff-mode))) + ;; This window just started displaying the commit message + ;; buffer. Without this that buffer would immediately be + ;; replaced with the diff buffer. See #2632. + (unrecord-window-buffer nil diff-buffer)) + (condition-case nil + (let ((args (car (magit-diff-arguments))) + (magit-inhibit-save-previous-winconf 'unset) + (magit-display-buffer-noselect t) + (inhibit-quit nil)) + (message "Diffing changes to be committed (C-g to abort diffing)") + (cl-case last-command + (magit-commit + (magit-diff-staged nil args)) + (magit-commit-all + (magit-diff-working-tree nil args)) + ((magit-commit-amend + magit-commit-reword + magit-rebase-reword-commit) + (magit-diff-while-amending args)) + (t (if (magit-anything-staged-p) + (magit-diff-staged nil args) + (magit-diff-while-amending args))))) + (quit)))) + +;; Mention `magit-diff-while-committing' because that's +;; always what I search for when I try to find this line. +(add-hook 'server-switch-hook 'magit-commit-diff) + +(add-to-list 'with-editor-server-window-alist + (cons git-commit-filename-regexp 'switch-to-buffer)) + +;;; Message Utilities + +(defun magit-commit-message-buffer () + (let* ((find-file-visit-truename t) ; git uses truename of COMMIT_EDITMSG + (topdir (magit-toplevel))) + (--first (equal topdir (with-current-buffer it + (and git-commit-mode (magit-toplevel)))) + (append (buffer-list (selected-frame)) + (buffer-list))))) + +(defvar magit-commit-add-log-insert-function 'magit-commit-add-log-insert + "Used by `magit-commit-add-log' to insert a single entry.") + +(defun magit-commit-add-log () + "Add a stub for the current change into the commit message buffer. +If no commit is in progress, then initiate it. Use the function +specified by variable `magit-commit-add-log-insert-function' to +actually insert the entry." + (interactive) + (pcase-let* ((hunk (and (magit-section-match 'hunk) + (magit-current-section))) + (log (magit-commit-message-buffer)) + (`(,buf ,pos) (magit-diff-visit-file--noselect))) + (unless log + (unless (magit-commit-assert nil) + (user-error "Abort")) + (magit-commit-create) + (while (not (setq log (magit-commit-message-buffer))) + (sit-for 0.01))) + (magit--with-temp-position buf pos + (funcall magit-commit-add-log-insert-function log + (magit-file-relative-name) + (and hunk (add-log-current-defun)))))) + +(defun magit-commit-add-log-insert (buffer file defun) + (with-current-buffer buffer + (undo-boundary) + (goto-char (point-max)) + (while (re-search-backward (concat "^" comment-start) nil t)) + (save-restriction + (narrow-to-region (point-min) (point)) + (cond ((re-search-backward (format "* %s\\(?: (\\([^)]+\\))\\)?: " file) + nil t) + (when (equal (match-string 1) defun) + (setq defun nil)) + (re-search-forward ": ")) + (t + (when (re-search-backward "^[\\*(].+\n" nil t) + (goto-char (match-end 0))) + (while (re-search-forward "^[^\\*\n].*\n" nil t)) + (if defun + (progn (insert (format "* %s (%s): \n" file defun)) + (setq defun nil)) + (insert (format "* %s: \n" file))) + (backward-char) + (unless (looking-at "\n[\n\\']") + (insert ?\n) + (backward-char)))) + (when defun + (forward-line) + (let ((limit (save-excursion + (and (re-search-forward "^\\*" nil t) + (point))))) + (unless (or (looking-back (format "(%s): " defun) + (line-beginning-position)) + (re-search-forward (format "^(%s): " defun) limit t)) + (while (re-search-forward "^[^\\*\n].*\n" limit t)) + (insert (format "(%s): \n" defun)) + (backward-char))))))) + +;;; _ +(provide 'magit-commit) +;;; magit-commit.el ends here diff --git a/elpa/magit-20191122.2040/magit-commit.elc b/elpa/magit-20191122.2040/magit-commit.elc new file mode 100644 index 0000000000000000000000000000000000000000..2b75604e8358d63f62e915bf39e06ec225ca31ce GIT binary patch literal 22559 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 +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; This library requires several other libraries, so that yet other +;; libraries can just require this one, instead of having to require +;; all the other ones. In other words this separates the low-level +;; stuff from the rest. It also defines some Custom groups. + +;;; Code: + +(require 'magit-utils) +(require 'magit-section) +(require 'magit-git) +(require 'magit-mode) +(require 'magit-margin) +(require 'magit-process) +(require 'magit-transient) +(require 'magit-autorevert) + +(when (magit--libgit-available-p) + (condition-case err + (require 'magit-libgit) + (error + (setq magit-inhibit-libgit 'error) + (message "Error while loading `magit-libgit': %S" err) + (message "That is not fatal. The `libegit2' module just won't be used.")))) + +(defgroup magit nil + "Controlling Git from Emacs." + :link '(url-link "https://magit.vc") + :link '(info-link "(magit)FAQ") + :link '(info-link "(magit)") + :group 'tools) + +(defgroup magit-essentials nil + "Options that every Magit user should briefly think about. + +Each of these options falls into one or more of these categories: + +* Options that affect Magit's behavior in fundamental ways. +* Options that affect safety. +* Options that affect performance. +* Options that are of a personal nature." + :link '(info-link "(magit)Essential Settings") + :group 'magit) + +(defgroup magit-miscellaneous nil + "Miscellaneous Magit options." + :group 'magit) + +(defgroup magit-commands nil + "Options controlling behavior of certain commands." + :group 'magit) + +(defgroup magit-modes nil + "Modes used or provided by Magit." + :group 'magit) + +(defgroup magit-buffers nil + "Options concerning Magit buffers." + :link '(info-link "(magit)Modes and Buffers") + :group 'magit) + +(defgroup magit-refresh nil + "Options controlling how Magit buffers are refreshed." + :link '(info-link "(magit)Automatic Refreshing of Magit Buffers") + :group 'magit + :group 'magit-buffers) + +(defgroup magit-faces nil + "Faces used by Magit." + :group 'magit + :group 'faces) + +(defgroup magit-extensions nil + "Extensions to Magit." + :group 'magit) + +(custom-add-to-group 'magit-modes 'git-commit 'custom-group) +(custom-add-to-group 'magit-faces 'git-commit-faces 'custom-group) +(custom-add-to-group 'magit-modes 'git-rebase 'custom-group) +(custom-add-to-group 'magit-faces 'git-rebase-faces 'custom-group) +(custom-add-to-group 'magit-process 'with-editor 'custom-group) + +(defgroup magit-related nil + "Options that are relevant to Magit but that are defined elsewhere." + :link '(custom-group-link vc) + :link '(custom-group-link smerge) + :link '(custom-group-link ediff) + :link '(custom-group-link auto-revert) + :group 'magit + :group 'magit-extensions + :group 'magit-essentials) + +(custom-add-to-group 'magit-related 'auto-revert-check-vc-info 'custom-variable) +(custom-add-to-group 'magit-auto-revert 'auto-revert-check-vc-info 'custom-variable) + +(custom-add-to-group 'magit-related 'ediff-window-setup-function 'custom-variable) +(custom-add-to-group 'magit-related 'smerge-refine-ignore-whitespace 'custom-variable) +(custom-add-to-group 'magit-related 'vc-follow-symlinks 'custom-variable) + +;;; _ +(provide 'magit-core) +;;; magit-core.el ends here diff --git a/elpa/magit-20191122.2040/magit-core.elc b/elpa/magit-20191122.2040/magit-core.elc new file mode 100644 index 0000000000000000000000000000000000000000..177de0ebcbfc2a79dcc5694e0a7e5ca830348b33 GIT binary patch literal 2968 zcmbtWTaVjB6kd2iEHCiH>uFH;g6cG}b7^-$V!KLFB`O5lH-glOJ&uRkGht?&5Pm)1 z@i>Xo4Nr|UvCsW7=i=MhFZbV`ot>TE-rmx^saC3#Spz6dvr43n*3vpZpguhiM^Mbf z5i4&*yTsP35lcTJvQd^~H*rQV^Vs-^0|3{U?SN~%w-dNWql+&O-i%v=X z8nZ>#xwqK*Jch9mR7_xOGW;&+WhCpJ@aZBOPN+FTHk^p;2swa?35@QMd}Wh1trLzA z#AzGhloQ1;$HLE#V*!rylq47596V%gQ`nu3J8n-;AsbHEJmLg09t?j%&7DBsbt-{vB21gZCizWJg z#w@fcc#iTA!{DU%!Gj=hc|%VhdenPY2v3-}JR@`AMcF5MS4esfHi>ZJOF}3$)cjRr z=x&U@^gJ0coU?w9QXowgWil;=mC@3gdKDZatxD?MW9(W}mTdoLBqz6~3TpwvH$Z=& ztJ;IUu5+qm&AbP)I z;b7J9*!IME-qKsXZw|+jD@5X>b-6rO&&V22V%G;`Hz>FI9#~B+2I|< z+bBldZAatlD)OdnXmkj^C#njK(vm})9q>^w!U!uD0{wA#ZE5_~7s*Uv!nFlpWr^m< z4q0p3G9;&zYk{%2bBq=>0Pb2QXEIkBg0ggSQ^-)RUC+Y6Sf`jDkI}A@b}3Ji;9j1e zr0`@$Xgr#)sRKl5A=3}hI>pM!@!c5a;aXV5)4C0`!%vNgXrpvyHj$IQUPb8iutb7q rFvH+}BrLKCJM literal 0 HcmV?d00001 diff --git a/elpa/magit-20191122.2040/magit-diff.el b/elpa/magit-20191122.2040/magit-diff.el new file mode 100644 index 00000000..77f2bdac --- /dev/null +++ b/elpa/magit-20191122.2040/magit-diff.el @@ -0,0 +1,3162 @@ +;;; magit-diff.el --- inspect Git diffs -*- lexical-binding: t -*- + +;; Copyright (C) 2010-2019 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; This library implements support for looking at Git diffs and +;; commits. + +;;; Code: + +(eval-when-compile + (require 'ansi-color) + (require 'subr-x)) + +(require 'git-commit) +(require 'magit-core) + +;; For `magit-diff-popup' +(declare-function magit-stash-show "magit-stash" (stash &optional args files)) +;; For `magit-diff-visit-file' +(declare-function dired-jump "dired-x" (&optional other-window file-name)) +(declare-function magit-find-file-noselect "magit-files" (rev file)) +(declare-function magit-status-setup-buffer "magit-status" (directory)) +;; For `magit-diff-while-committing' +(declare-function magit-commit-message-buffer "magit-commit" ()) +;; For `magit-insert-revision-gravatar' +(defvar gravatar-size) +;; For `magit-show-commit' and `magit-diff-show-or-scroll' +(declare-function magit-current-blame-chunk "magit-blame" ()) +(declare-function magit-blame-mode "magit-blame" (&optional arg)) +(defvar magit-blame-mode) +;; For `magit-diff-show-or-scroll' +(declare-function git-rebase-current-line "git-rebase" ()) +;; For `magit-diff-unmerged' +(declare-function magit-merge-in-progress-p "magit-merge" ()) +(declare-function magit--merge-range "magit-merge" (&optional head)) +;; For `magit-diff--dwim' +(declare-function forge--pullreq-ref "forge-pullreq" (pullreq)) +;; For `magit-diff-wash-diff' +(declare-function ansi-color-apply-on-region "ansi-color" (begin end)) + +(eval-when-compile + (cl-pushnew 'base-ref eieio--known-slot-names) + (cl-pushnew 'orig-rev eieio--known-slot-names) + (cl-pushnew 'action-type eieio--known-slot-names) + (cl-pushnew 'target eieio--known-slot-names)) + +(require 'diff-mode) +(require 'smerge-mode) + +;;; Options +;;;; Diff Mode + +(defgroup magit-diff nil + "Inspect and manipulate Git diffs." + :link '(info-link "(magit)Diffing") + :group 'magit-modes) + +(defcustom magit-diff-mode-hook nil + "Hook run after entering Magit-Diff mode." + :group 'magit-diff + :type 'hook) + +(defcustom magit-diff-sections-hook + '(magit-insert-diff + magit-insert-xref-buttons) + "Hook run to insert sections into a `magit-diff-mode' buffer." + :package-version '(magit . "2.3.0") + :group 'magit-diff + :type 'hook) + +(defcustom magit-diff-expansion-threshold 60 + "After how many seconds not to expand anymore diffs. + +Except in status buffers, diffs are usually start out fully +expanded. Because that can take a long time, all diffs that +haven't been fontified during a refresh before the threshold +defined here are instead displayed with their bodies collapsed. + +Note that this can cause sections that were previously expanded +to be collapsed. So you should not pick a very low value here. + +The hook function `magit-diff-expansion-threshold' has to be a +member of `magit-section-set-visibility-hook' for this option +to have any effect." + :package-version '(magit . "2.9.0") + :group 'magit-diff + :type 'float) + +(defcustom magit-diff-highlight-hunk-body t + "Whether to highlight bodies of selected hunk sections. +This only has an effect if `magit-diff-highlight' is a +member of `magit-section-highlight-hook', which see." + :package-version '(magit . "2.1.0") + :group 'magit-diff + :type 'boolean) + +(defcustom magit-diff-highlight-hunk-region-functions + '(magit-diff-highlight-hunk-region-dim-outside + magit-diff-highlight-hunk-region-using-overlays) + "The functions used to highlight the hunk-internal region. + +`magit-diff-highlight-hunk-region-dim-outside' overlays the outside +of the hunk internal selection with a face that causes the added and +removed lines to have the same background color as context lines. +This function should not be removed from the value of this option. + +`magit-diff-highlight-hunk-region-using-overlays' and +`magit-diff-highlight-hunk-region-using-underline' emphasize the +region by placing delimiting horizontal lines before and after it. +The underline variant was implemented because Eli said that is +how we should do it. However the overlay variant actually works +better. Also see https://github.com/magit/magit/issues/2758. + +Instead of, or in addition to, using delimiting horizontal lines, +to emphasize the boundaries, you may which to emphasize the text +itself, using `magit-diff-highlight-hunk-region-using-face'. + +In terminal frames it's not possible to draw lines as the overlay +and underline variants normally do, so there they fall back to +calling the face function instead." + :package-version '(magit . "2.9.0") + :set-after '(magit-diff-show-lines-boundaries) + :group 'magit-diff + :type 'hook + :options '(magit-diff-highlight-hunk-region-dim-outside + magit-diff-highlight-hunk-region-using-underline + magit-diff-highlight-hunk-region-using-overlays + magit-diff-highlight-hunk-region-using-face)) + +(defcustom magit-diff-unmarked-lines-keep-foreground t + "Whether `magit-diff-highlight-hunk-region-dim-outside' preserves foreground. +When this is set to nil, then that function only adjusts the +foreground color but added and removed lines outside the region +keep their distinct foreground colors." + :package-version '(magit . "2.9.0") + :group 'magit-diff + :type 'boolean) + +(defcustom magit-diff-refine-hunk nil + "Whether to show word-granularity differences within diff hunks. + +nil Never show fine differences. +t Show fine differences for the current diff hunk only. +`all' Show fine differences for all displayed diff hunks." + :group 'magit-diff + :safe (lambda (val) (memq val '(nil t all))) + :type '(choice (const :tag "Never" nil) + (const :tag "Current" t) + (const :tag "All" all))) + +(defcustom magit-diff-refine-ignore-whitespace smerge-refine-ignore-whitespace + "Whether to ignore whitespace changes in word-granularity differences." + :package-version '(magit . "2.91.0") + :set-after '(smerge-refine-ignore-whitespace) + :group 'magit-diff + :safe 'booleanp + :type 'boolean) + +(put 'magit-diff-refine-hunk 'permanent-local t) + +(defcustom magit-diff-adjust-tab-width nil + "Whether to adjust the width of tabs in diffs. + +Determining the correct width can be expensive if it requires +opening large and/or many files, so the widths are cached in +the variable `magit-diff--tab-width-cache'. Set that to nil +to invalidate the cache. + +nil Never adjust tab width. Use `tab-width's value from + the Magit buffer itself instead. + +t If the corresponding file-visiting buffer exits, then + use `tab-width's value from that buffer. Doing this is + cheap, so this value is used even if a corresponding + cache entry exists. + +`always' If there is no such buffer, then temporarily visit the + file to determine the value. + +NUMBER Like `always', but don't visit files larger than NUMBER + bytes." + :package-version '(magit . "2.12.0") + :group 'magit-diff + :type '(choice (const :tag "Never" nil) + (const :tag "If file-visiting buffer exists" t) + (integer :tag "If file isn't larger than N bytes") + (const :tag "Always" always))) + +(defcustom magit-diff-paint-whitespace t + "Specify where to highlight whitespace errors. + +nil Never highlight whitespace errors. +t Highlight whitespace errors everywhere. +`uncommitted' Only highlight whitespace errors in diffs + showing uncommitted changes. + +For backward compatibility `status' is treated as a synonym +for `uncommitted'. + +The option `magit-diff-paint-whitespace-lines' controls for +what lines (added/remove/context) errors are highlighted. + +The options `magit-diff-highlight-trailing' and +`magit-diff-highlight-indentation' control what kind of +whitespace errors are highlighted." + :group 'magit-diff + :safe (lambda (val) (memq val '(t nil uncommitted status))) + :type '(choice (const :tag "In all diffs" t) + (const :tag "Only in uncommitted changes" uncommitted) + (const :tag "Never" nil))) + +(defcustom magit-diff-paint-whitespace-lines t + "Specify in what kind of lines to highlight whitespace errors. + +t Highlight only in added lines. +`both' Highlight in added and removed lines. +`all' Highlight in added, removed and context lines." + :package-version '(magit . "2.91.0") + :group 'magit-diff + :safe (lambda (val) (memq val '(t both all))) + :type '(choice (const :tag "in added lines" t) + (const :tag "in added and removed lines" both) + (const :tag "in added, removed and context lines" all))) + +(defcustom magit-diff-highlight-trailing t + "Whether to highlight whitespace at the end of a line in diffs. +Used only when `magit-diff-paint-whitespace' is non-nil." + :group 'magit-diff + :safe 'booleanp + :type 'boolean) + +(defcustom magit-diff-highlight-indentation nil + "Highlight the \"wrong\" indentation style. +Used only when `magit-diff-paint-whitespace' is non-nil. + +The value is an alist of the form ((REGEXP . INDENT)...). The +path to the current repository is matched against each element +in reverse order. Therefore if a REGEXP matches, then earlier +elements are not tried. + +If the used INDENT is `tabs', highlight indentation with tabs. +If INDENT is an integer, highlight indentation with at least +that many spaces. Otherwise, highlight neither." + :group 'magit-diff + :type `(repeat (cons (string :tag "Directory regexp") + (choice (const :tag "Tabs" tabs) + (integer :tag "Spaces" :value ,tab-width) + (const :tag "Neither" nil))))) + +(defcustom magit-diff-hide-trailing-cr-characters + (and (memq system-type '(ms-dos windows-nt)) t) + "Whether to hide ^M characters at the end of a line in diffs." + :package-version '(magit . "2.6.0") + :group 'magit-diff + :type 'boolean) + +(defcustom magit-diff-highlight-keywords t + "Whether to highlight bracketed keywords in commit messages." + :package-version '(magit . "2.12.0") + :group 'magit-diff + :type 'boolean) + +;;;; File Diff + +(defcustom magit-diff-buffer-file-locked t + "Whether `magit-diff-buffer-file' uses a dedicated buffer." + :package-version '(magit . "2.7.0") + :group 'magit-commands + :group 'magit-diff + :type 'boolean) + +;;;; Revision Mode + +(defgroup magit-revision nil + "Inspect and manipulate Git commits." + :link '(info-link "(magit)Revision Buffer") + :group 'magit-modes) + +(defcustom magit-revision-mode-hook '(bug-reference-mode) + "Hook run after entering Magit-Revision mode." + :group 'magit-revision + :type 'hook + :options '(bug-reference-mode)) + +(defcustom magit-revision-sections-hook + '(magit-insert-revision-tag + magit-insert-revision-headers + magit-insert-revision-message + magit-insert-revision-notes + magit-insert-revision-diff + magit-insert-xref-buttons) + "Hook run to insert sections into a `magit-revision-mode' buffer." + :package-version '(magit . "2.3.0") + :group 'magit-revision + :type 'hook) + +(defcustom magit-revision-headers-format "\ +Author: %aN <%aE> +AuthorDate: %ad +Commit: %cN <%cE> +CommitDate: %cd +" + "Format string used to insert headers in revision buffers. + +All headers in revision buffers are inserted by the section +inserter `magit-insert-revision-headers'. Some of the headers +are created by calling `git show --format=FORMAT' where FORMAT +is the format specified here. Other headers are hard coded or +subject to option `magit-revision-insert-related-refs'." + :package-version '(magit . "2.3.0") + :group 'magit-revision + :type 'string) + +(defcustom magit-revision-insert-related-refs t + "Whether to show related branches in revision buffers + +`nil' Don't show any related branches. +`t' Show related local branches. +`all' Show related local and remote branches. +`mixed' Show all containing branches and local merged branches." + :package-version '(magit . "2.1.0") + :group 'magit-revision + :type '(choice (const :tag "don't" nil) + (const :tag "local only" t) + (const :tag "all related" all) + (const :tag "all containing, local merged" mixed))) + +(defcustom magit-revision-use-hash-sections 'quicker + "Whether to turn hashes inside the commit message into sections. + +If non-nil, then hashes inside the commit message are turned into +`commit' sections. There is a trade off to be made between +performance and reliability: + +- `slow' calls git for every word to be absolutely sure. +- `quick' skips words less than seven characters long. +- `quicker' additionally skips words that don't contain a number. +- `quickest' uses all words that are at least seven characters + long and which contain at least one number as well as at least + one letter. + +If nil, then no hashes are turned into sections, but you can +still visit the commit at point using \"RET\"." + :package-version '(magit . "2.12.0") + :group 'magit-revision + :type '(choice (const :tag "Use sections, quickest" quickest) + (const :tag "Use sections, quicker" quicker) + (const :tag "Use sections, quick" quick) + (const :tag "Use sections, slow" slow) + (const :tag "Don't use sections" nil))) + +(defcustom magit-revision-show-gravatars nil + "Whether to show gravatar images in revision buffers. + +If nil, then don't insert any gravatar images. If t, then insert +both images. If `author' or `committer', then insert only the +respective image. + +If you have customized the option `magit-revision-header-format' +and want to insert the images then you might also have to specify +where to do so. In that case the value has to be a cons-cell of +two regular expressions. The car specifies where to insert the +author's image. The top half of the image is inserted right +after the matched text, the bottom half on the next line in the +same column. The cdr specifies where to insert the committer's +image, accordingly. Either the car or the cdr may be nil." + :package-version '(magit . "2.3.0") + :group 'magit-revision + :type '(choice (const :tag "Don't show gravatars" nil) + (const :tag "Show gravatars" t) + (const :tag "Show author gravatar" author) + (const :tag "Show committer gravatar" committer) + (cons :tag "Show gravatars using custom pattern." + (regexp :tag "Author regexp" "^Author: ") + (regexp :tag "Committer regexp" "^Commit: ")))) + +(defcustom magit-revision-use-gravatar-kludge nil + "Whether to work around a bug which affects display of gravatars. + +Gravatar images are spliced into two halves which are then +displayed on separate lines. On OS X the splicing has a bug in +some Emacs builds, which causes the top and bottom halves to be +interchanged. Enabling this option works around this issue by +interchanging the halves once more, which cancels out the effect +of the bug. + +See https://github.com/magit/magit/issues/2265 +and https://debbugs.gnu.org/cgi/bugreport.cgi?bug=7847. + +Starting with Emacs 26.1 this kludge should not be required for +any build." + :package-version '(magit . "2.3.0") + :group 'magit-revision + :type 'boolean) + +(defcustom magit-revision-fill-summary-line nil + "Whether to fill excessively long summary lines. + +If this is an integer, then the summary line is filled if it is +longer than either the limit specified here or `window-width'. + +You may want to only set this locally in \".dir-locals-2.el\" for +repositories known to contain bad commit messages. + +The body of the message is left alone because (a) most people who +write excessively long summary lines usually don't add a body and +(b) even people who have the decency to wrap their lines may have +a good reason to include a long line in the body sometimes." + :package-version '(magit . "2.90.0") + :group 'magit-revision + :type '(choice (const :tag "Don't fill" nil) + (integer :tag "Fill if longer than"))) + +(defcustom magit-revision-filter-files-on-follow nil + "Whether to honor file filter if log arguments include --follow. + +When a commit is displayed from a log buffer, the resulting +revision buffer usually shares the log's file arguments, +restricting the diff to those files. However, there's a +complication when the log arguments include --follow: if the log +follows a file across a rename event, keeping the file +restriction would mean showing an empty diff in revision buffers +for commits before the rename event. + +When this option is nil, the revision buffer ignores the log's +filter if the log arguments include --follow. If non-nil, the +log's file filter is always honored." + :package-version '(magit . "2.91.0") + :group 'magit-revision + :type 'boolean) + +;;;; Visit Commands + +(defcustom magit-diff-visit-previous-blob t + "Whether `magit-diff-visit-file' may visit the previous blob. + +When this is t and point is on a removed line in a diff for a +committed change, then `magit-diff-visit-file' visits the blob +from the last revision which still had that line. + +Currently this is only supported for committed changes, for +staged and unstaged changes `magit-diff-visit-file' always +visits the file in the working tree." + :package-version '(magit . "2.9.0") + :group 'magit-diff + :type 'boolean) + +(defcustom magit-diff-visit-avoid-head-blob nil + "Whether `magit-diff-visit-file' avoids visiting a blob from `HEAD'. + +By default `magit-diff-visit-file' always visits the blob that +added the current line, while `magit-diff-visit-worktree-file' +visits the respective file in the working tree. For the `HEAD' +commit, the former command used to visit the worktree file too, +but that made it impossible to visit a blob from `HEAD'. + +When point is on a removed line and that change has not been +committed yet, then `magit-diff-visit-file' now visits the last +blob that still had that line, which is a blob from `HEAD'. +Previously this function used to visit the worktree file not +only for added lines but also for such removed lines. + +If you prefer the old behaviors, then set this to t." + :package-version '(magit . "2.91.0") + :group 'magit-diff + :type 'boolean) + +;;; Faces + +(defface magit-diff-file-heading + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :weight bold)) + "Face for diff file headings." + :group 'magit-faces) + +(defface magit-diff-file-heading-highlight + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :inherit magit-section-highlight)) + "Face for current diff file headings." + :group 'magit-faces) + +(defface magit-diff-file-heading-selection + `((((class color) (background light)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :inherit magit-diff-file-heading-highlight + :foreground "salmon4") + (((class color) (background dark)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :inherit magit-diff-file-heading-highlight + :foreground "LightSalmon3")) + "Face for selected diff file headings." + :group 'magit-faces) + +(defface magit-diff-hunk-heading + `((((class color) (background light)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :background "grey80" + :foreground "grey30") + (((class color) (background dark)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :background "grey25" + :foreground "grey70")) + "Face for diff hunk headings." + :group 'magit-faces) + +(defface magit-diff-hunk-heading-highlight + `((((class color) (background light)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :background "grey75" + :foreground "grey30") + (((class color) (background dark)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :background "grey35" + :foreground "grey70")) + "Face for current diff hunk headings." + :group 'magit-faces) + +(defface magit-diff-hunk-heading-selection + `((((class color) (background light)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :inherit magit-diff-hunk-heading-highlight + :foreground "salmon4") + (((class color) (background dark)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :inherit magit-diff-hunk-heading-highlight + :foreground "LightSalmon3")) + "Face for selected diff hunk headings." + :group 'magit-faces) + +(defface magit-diff-hunk-region + `((t :inherit bold + ,@(and (>= emacs-major-version 27) + (list :extend (ignore-errors (face-attribute 'region :extend)))))) + "Face used by `magit-diff-highlight-hunk-region-using-face'. + +This face is overlaid over text that uses other hunk faces, +and those normally set the foreground and background colors. +The `:foreground' and especially the `:background' properties +should be avoided here. Setting the latter would cause the +loss of information. Good properties to set here are `:weight' +and `:slant'." + :group 'magit-faces) + +(defface magit-diff-revision-summary + '((t :inherit magit-diff-hunk-heading)) + "Face for commit message summaries." + :group 'magit-faces) + +(defface magit-diff-revision-summary-highlight + '((t :inherit magit-diff-hunk-heading-highlight)) + "Face for highlighted commit message summaries." + :group 'magit-faces) + +(defface magit-diff-lines-heading + `((((class color) (background light)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :inherit magit-diff-hunk-heading-highlight + :background "LightSalmon3") + (((class color) (background dark)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :inherit magit-diff-hunk-heading-highlight + :foreground "grey80" + :background "salmon4")) + "Face for diff hunk heading when lines are marked." + :group 'magit-faces) + +(defface magit-diff-lines-boundary + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) ; !important + :inherit magit-diff-lines-heading)) + "Face for boundary of marked lines in diff hunk." + :group 'magit-faces) + +(defface magit-diff-conflict-heading + '((t :inherit magit-diff-hunk-heading)) + "Face for conflict markers." + :group 'magit-faces) + +(defface magit-diff-added + `((((class color) (background light)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :background "#ddffdd" + :foreground "#22aa22") + (((class color) (background dark)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :background "#335533" + :foreground "#ddffdd")) + "Face for lines in a diff that have been added." + :group 'magit-faces) + +(defface magit-diff-removed + `((((class color) (background light)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :background "#ffdddd" + :foreground "#aa2222") + (((class color) (background dark)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :background "#553333" + :foreground "#ffdddd")) + "Face for lines in a diff that have been removed." + :group 'magit-faces) + +(defface magit-diff-our + '((t :inherit magit-diff-removed)) + "Face for lines in a diff for our side in a conflict." + :group 'magit-faces) + +(defface magit-diff-base + `((((class color) (background light)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :background "#ffffcc" + :foreground "#aaaa11") + (((class color) (background dark)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :background "#555522" + :foreground "#ffffcc")) + "Face for lines in a diff for the base side in a conflict." + :group 'magit-faces) + +(defface magit-diff-their + '((t :inherit magit-diff-added)) + "Face for lines in a diff for their side in a conflict." + :group 'magit-faces) + +(defface magit-diff-context + `((((class color) (background light)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "grey50") + (((class color) (background dark)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "grey70")) + "Face for lines in a diff that are unchanged." + :group 'magit-faces) + +(defface magit-diff-added-highlight + `((((class color) (background light)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :background "#cceecc" + :foreground "#22aa22") + (((class color) (background dark)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :background "#336633" + :foreground "#cceecc")) + "Face for lines in a diff that have been added." + :group 'magit-faces) + +(defface magit-diff-removed-highlight + `((((class color) (background light)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :background "#eecccc" + :foreground "#aa2222") + (((class color) (background dark)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :background "#663333" + :foreground "#eecccc")) + "Face for lines in a diff that have been removed." + :group 'magit-faces) + +(defface magit-diff-our-highlight + '((t :inherit magit-diff-removed-highlight)) + "Face for lines in a diff for our side in a conflict." + :group 'magit-faces) + +(defface magit-diff-base-highlight + `((((class color) (background light)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :background "#eeeebb" + :foreground "#aaaa11") + (((class color) (background dark)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :background "#666622" + :foreground "#eeeebb")) + "Face for lines in a diff for the base side in a conflict." + :group 'magit-faces) + +(defface magit-diff-their-highlight + '((t :inherit magit-diff-added-highlight)) + "Face for lines in a diff for their side in a conflict." + :group 'magit-faces) + +(defface magit-diff-context-highlight + `((((class color) (background light)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :background "grey95" + :foreground "grey50") + (((class color) (background dark)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :background "grey20" + :foreground "grey70")) + "Face for lines in the current context in a diff." + :group 'magit-faces) + +(defface magit-diff-whitespace-warning + '((t :inherit trailing-whitespace)) + "Face for highlighting whitespace errors added lines." + :group 'magit-faces) + +(defface magit-diffstat-added + '((((class color) (background light)) :foreground "#22aa22") + (((class color) (background dark)) :foreground "#448844")) + "Face for plus sign in diffstat." + :group 'magit-faces) + +(defface magit-diffstat-removed + '((((class color) (background light)) :foreground "#aa2222") + (((class color) (background dark)) :foreground "#aa4444")) + "Face for minus sign in diffstat." + :group 'magit-faces) + +;;; Arguments +;;;; Prefix Classes + +(defclass magit-diff-prefix (transient-prefix) + ((history-key :initform 'magit-diff) + (major-mode :initform 'magit-diff-mode))) + +(defclass magit-diff-refresh-prefix (magit-diff-prefix) + ((history-key :initform 'magit-diff) + (major-mode :initform nil))) + +;;;; Prefix Methods + +(cl-defmethod transient-init-value ((obj magit-diff-prefix)) + (pcase-let ((`(,args ,files) + (magit-diff--get-value 'magit-diff-mode + magit-prefix-use-buffer-arguments))) + (unless (eq current-transient-command 'magit-dispatch) + (when-let ((file (magit-file-relative-name))) + (setq files (list file)))) + (oset obj value (if files `(("--" ,@files) ,args) args)))) + +(cl-defmethod transient-init-value ((obj magit-diff-refresh-prefix)) + (oset obj value (if magit-buffer-diff-files + `(("--" ,@magit-buffer-diff-files) + ,magit-buffer-diff-args) + magit-buffer-diff-args))) + +(cl-defmethod transient-set-value ((obj magit-diff-prefix)) + (magit-diff--set-value obj)) + +(cl-defmethod transient-save-value ((obj magit-diff-prefix)) + (magit-diff--set-value obj 'save)) + +;;;; Argument Access + +(defun magit-diff-arguments (&optional mode) + "Return the current diff arguments." + (if (memq current-transient-command '(magit-diff magit-diff-refresh)) + (pcase-let ((`(,args ,alist) + (-separate #'atom (transient-get-value)))) + (list args (cdr (assoc "--" alist)))) + (magit-diff--get-value (or mode 'magit-diff-mode)))) + +(defun magit-diff--get-value (mode &optional use-buffer-args) + (unless use-buffer-args + (setq use-buffer-args magit-direct-use-buffer-arguments)) + (let (args files) + (cond + ((and (memq use-buffer-args '(always selected current)) + (eq major-mode mode)) + (setq args magit-buffer-diff-args) + (setq files magit-buffer-diff-files)) + ((and (memq use-buffer-args '(always selected)) + (when-let ((buffer (magit-get-mode-buffer + mode nil + (or (eq use-buffer-args 'selected) 'all)))) + (setq args (buffer-local-value 'magit-buffer-diff-args buffer)) + (setq files (buffer-local-value 'magit-buffer-diff-files buffer)) + t))) + ((plist-member (symbol-plist mode) 'magit-diff-current-arguments) + (setq args (get mode 'magit-diff-current-arguments))) + ((when-let ((elt (assq (intern (format "magit-diff:%s" mode)) + transient-values))) + (setq args (cdr elt)) + t)) + (t + (setq args (get mode 'magit-diff-default-arguments)))) + (list args files))) + +(defun magit-diff--set-value (obj &optional save) + (pcase-let* ((obj (oref obj prototype)) + (mode (or (oref obj major-mode) major-mode)) + (key (intern (format "magit-diff:%s" mode))) + (`(,args ,alist) + (-separate #'atom (transient-get-value))) + (files (cdr (assoc "--" alist)))) + (put mode 'magit-diff-current-arguments args) + (when save + (setf (alist-get key transient-values) args) + (transient-save-values)) + (transient--history-push obj) + (setq magit-buffer-diff-args args) + (setq magit-buffer-diff-files files) + (magit-refresh))) + +;;; Commands +;;;; Prefix Commands + +;;;###autoload (autoload 'magit-diff "magit-diff" nil t) +(define-transient-command magit-diff () + "Show changes between different versions." + :man-page "git-diff" + :class 'magit-diff-prefix + ["Limit arguments" + (magit:--) + (magit-diff:--ignore-submodules) + ("-b" "Ignore whitespace changes" ("-b" "--ignore-space-change")) + ("-w" "Ignore all whitespace" ("-w" "--ignore-all-space"))] + ["Context arguments" + (magit-diff:-U) + ("-W" "Show surrounding functions" ("-W" "--function-context"))] + ["Tune arguments" + (magit-diff:--diff-algorithm) + (magit-diff:-M) + (magit-diff:-C) + ("-x" "Disallow external diff drivers" "--no-ext-diff") + ("-s" "Show stats" "--stat") + ("=g" "Show signature" "--show-signature") + (5 magit-diff:--color-moved) + (5 magit-diff:--color-moved-ws)] + ["Actions" + [("d" "Dwim" magit-diff-dwim) + ("r" "Diff range" magit-diff-range) + ("p" "Diff paths" magit-diff-paths)] + [("u" "Diff unstaged" magit-diff-unstaged) + ("s" "Diff staged" magit-diff-staged) + ("w" "Diff worktree" magit-diff-working-tree)] + [("c" "Show commit" magit-show-commit) + ("t" "Show stash" magit-stash-show)]]) + +;;;###autoload (autoload 'magit-diff-refresh "magit-diff" nil t) +(define-transient-command magit-diff-refresh () + "Change the arguments used for the diff(s) in the current buffer." + :man-page "git-diff" + :class 'magit-diff-refresh-prefix + ["Limit arguments" + (magit:--) + (magit-diff:--ignore-submodules) + ("-b" "Ignore whitespace changes" ("-b" "--ignore-space-change")) + ("-w" "Ignore all whitespace" ("-w" "--ignore-all-space"))] + ["Context arguments" + (magit-diff:-U) + ("-W" "Show surrounding functions" ("-W" "--function-context"))] + ["Tune arguments" + (magit-diff:--diff-algorithm) + (magit-diff:-M) + (magit-diff:-C) + ("-x" "Disallow external diff drivers" "--no-ext-diff") + ("-s" "Show stats" "--stat" + :if-derived magit-diff-mode) + ("=g" "Show signature" "--show-signature" + :if-derived magit-diff-mode) + (5 magit-diff:--color-moved) + (5 magit-diff:--color-moved-ws)] + [["Refresh" + ("g" "buffer" magit-diff-refresh) + ("s" "buffer and set defaults" transient-set :transient nil) + ("w" "buffer and save defaults" transient-save :transient nil)] + ["Toggle" + ("t" "hunk refinement" magit-diff-toggle-refine-hunk) + ("F" "file filter" magit-diff-toggle-file-filter) + ("b" "buffer lock" magit-toggle-buffer-lock + :if-mode (magit-diff-mode magit-revision-mode magit-stash-mode))] + [:if-mode magit-diff-mode + :description "Do" + ("r" "switch range type" magit-diff-switch-range-type) + ("f" "flip revisions" magit-diff-flip-revs)]] + (interactive) + (if (not (eq current-transient-command 'magit-diff-refresh)) + (transient-setup 'magit-diff-refresh) + (pcase-let ((`(,args ,files) (magit-diff-arguments))) + (setq magit-buffer-diff-args args) + (setq magit-buffer-diff-files files)) + (magit-refresh))) + +;;;; Infix Commands + +(define-infix-argument magit:-- () + :description "Limit to files" + :class 'transient-files + :key "--" + :argument "--" + :prompt "Limit to file(s): " + :reader 'magit-read-files + :multi-value t) + +(defun magit-read-files (prompt initial-input history) + (magit-completing-read-multiple* prompt + (magit-list-files) + nil nil initial-input history)) + +(define-infix-argument magit-diff:-U () + :description "Context lines" + :class 'transient-option + :argument "-U" + :reader 'transient-read-number-N+) + +(define-infix-argument magit-diff:-M () + :description "Detect renames" + :class 'transient-option + :argument "-M" + :reader 'transient-read-number-N+) + +(define-infix-argument magit-diff:-C () + :description "Detect copies" + :class 'transient-option + :argument "-C" + :reader 'transient-read-number-N+) + +(define-infix-argument magit-diff:--diff-algorithm () + :description "Diff algorithm" + :class 'transient-option + :key "-A" + :argument "--diff-algorithm=" + :reader 'magit-diff-select-algorithm) + +(defun magit-diff-select-algorithm (&rest _ignore) + (magit-read-char-case nil t + (?d "[d]efault" "default") + (?m "[m]inimal" "minimal") + (?p "[p]atience" "patience") + (?h "[h]istogram" "histogram"))) + +(define-infix-argument magit-diff:--ignore-submodules () + :description "Ignore submodules" + :class 'transient-option + :key "-i" + :argument "--ignore-submodules=" + :reader 'magit-diff-select-ignore-submodules) + +(defun magit-diff-select-ignore-submodules (&rest _ignored) + (magit-read-char-case "Ignore submodules " t + (?u "[u]ntracked" "untracked") + (?d "[d]irty" "dirty") + (?a "[a]ll" "all"))) + +(define-infix-argument magit-diff:--color-moved () + :description "Color moved lines" + :class 'transient-option + :key "-m" + :argument "--color-moved=" + :reader 'magit-diff-select-color-moved-mode) + +(defun magit-diff-select-color-moved-mode (&rest _ignore) + (magit-read-char-case "Color moved " t + (?d "[d]efault" "default") + (?p "[p]lain" "plain") + (?b "[b]locks" "blocks") + (?z "[z]ebra" "zebra") + (?Z "[Z] dimmed-zebra" "dimmed-zebra"))) + +(define-infix-argument magit-diff:--color-moved-ws () + :description "Whitespace treatment for --color-moved" + :class 'transient-option + :key "=w" + :argument "--color-moved-ws=" + :reader 'magit-diff-select-color-moved-ws-mode) + +(defun magit-diff-select-color-moved-ws-mode (&rest _ignore) + (magit-read-char-case "Ignore whitespace " t + (?i "[i]ndentation" "allow-indentation-change") + (?e "[e]nd of line" "ignore-space-at-eol") + (?s "[s]pace change" "ignore-space-change") + (?a "[a]ll space" "ignore-all-space") + (?n "[n]o" "no"))) + +;;;; Setup Commands + +;;;###autoload +(defun magit-diff-dwim (&optional args files) + "Show changes for the thing at point." + (interactive (magit-diff-arguments)) + (pcase (magit-diff--dwim) + (`unmerged (magit-diff-unmerged args files)) + (`unstaged (magit-diff-unstaged args files)) + (`staged + (let ((file (magit-file-at-point))) + (if (and file (equal (cddr (car (magit-file-status file))) '(?D ?U))) + ;; File was deleted by us and modified by them. Show the latter. + (magit-diff-unmerged args (list file)) + (magit-diff-staged nil args files)))) + (`(commit . ,value) + (magit-diff-range (format "%s^..%s" value value) args files)) + (`(stash . ,value) (magit-stash-show value args)) + ((and range (pred stringp)) + (magit-diff-range range args files)) + (_ + (call-interactively #'magit-diff-range)))) + +(defun magit-diff--dwim () + "Return information for performing DWIM diff. + +The information can be in three forms: +1. TYPE + A symbol describing a type of diff where no additional information + is needed to generate the diff. Currently, this includes `staged', + `unstaged' and `unmerged'. +2. (TYPE . VALUE) + Like #1 but the diff requires additional information, which is + given by VALUE. Currently, this includes `commit' and `stash', + where VALUE is the given commit or stash, respectively. +3. RANGE + A string indicating a diff range. + +If no DWIM context is found, nil is returned." + (cond + ((--when-let (magit-region-values '(commit branch) t) + (deactivate-mark) + (concat (car (last it)) ".." (car it)))) + (magit-buffer-refname + (cons 'commit magit-buffer-refname)) + ((derived-mode-p 'magit-stash-mode) + (cons 'commit + (magit-section-case + (commit (oref it value)) + (file (-> it + (oref parent) + (oref value))) + (hunk (-> it + (oref parent) + (oref parent) + (oref value)))))) + ((derived-mode-p 'magit-revision-mode) + (cons 'commit magit-buffer-revision)) + ((derived-mode-p 'magit-diff-mode) + magit-buffer-range) + (t + (magit-section-case + ([* unstaged] 'unstaged) + ([* staged] 'staged) + (unmerged 'unmerged) + (unpushed (oref it value)) + (unpulled (oref it value)) + (branch (let ((current (magit-get-current-branch)) + (atpoint (oref it value))) + (if (equal atpoint current) + (--if-let (magit-get-upstream-branch) + (format "%s...%s" it current) + (if (magit-anything-modified-p) + current + (cons 'commit current))) + (format "%s...%s" + (or current "HEAD") + atpoint)))) + (commit (cons 'commit (oref it value))) + (stash (cons 'stash (oref it value))) + (pullreq (let ((pullreq (oref it value))) + (format "%s...%s" + (oref pullreq base-ref) + (forge--pullreq-ref pullreq)))))))) + +(defun magit-diff-read-range-or-commit (prompt &optional secondary-default mbase) + "Read range or revision with special diff range treatment. +If MBASE is non-nil, prompt for which rev to place at the end of +a \"revA...revB\" range. Otherwise, always construct +\"revA..revB\" range." + (--if-let (magit-region-values '(commit branch) t) + (let ((revA (car (last it))) + (revB (car it))) + (deactivate-mark) + (if mbase + (let ((base (magit-git-string "merge-base" revA revB))) + (cond + ((string= (magit-rev-parse revA) base) + (format "%s..%s" revA revB)) + ((string= (magit-rev-parse revB) base) + (format "%s..%s" revB revA)) + (t + (let ((main (magit-completing-read "View changes along" + (list revA revB) + nil t nil nil revB))) + (format "%s...%s" + (if (string= main revB) revA revB) main))))) + (format "%s..%s" revA revB))) + (magit-read-range prompt + (or (pcase (magit-diff--dwim) + (`(commit . ,value) + (format "%s^..%s" value value)) + ((and range (pred stringp)) + range)) + secondary-default + (magit-get-current-branch))))) + +;;;###autoload +(defun magit-diff-range (rev-or-range &optional args files) + "Show differences between two commits. + +REV-OR-RANGE should be a range or a single revision. If it is a +revision, then show changes in the working tree relative to that +revision. If it is a range, but one side is omitted, then show +changes relative to `HEAD'. + +If the region is active, use the revisions on the first and last +line of the region as the two sides of the range. With a prefix +argument, instead of diffing the revisions, choose a revision to +view changes along, starting at the common ancestor of both +revisions (i.e., use a \"...\" range)." + (interactive (cons (magit-diff-read-range-or-commit "Diff for range" + nil current-prefix-arg) + (magit-diff-arguments))) + (magit-diff-setup-buffer rev-or-range nil args files)) + +;;;###autoload +(defun magit-diff-working-tree (&optional rev args files) + "Show changes between the current working tree and the `HEAD' commit. +With a prefix argument show changes between the working tree and +a commit read from the minibuffer." + (interactive + (cons (and current-prefix-arg + (magit-read-branch-or-commit "Diff working tree and commit")) + (magit-diff-arguments))) + (magit-diff-setup-buffer (or rev "HEAD") nil args files)) + +;;;###autoload +(defun magit-diff-staged (&optional rev args files) + "Show changes between the index and the `HEAD' commit. +With a prefix argument show changes between the index and +a commit read from the minibuffer." + (interactive + (cons (and current-prefix-arg + (magit-read-branch-or-commit "Diff index and commit")) + (magit-diff-arguments))) + (magit-diff-setup-buffer rev "--cached" args files)) + +;;;###autoload +(defun magit-diff-unstaged (&optional args files) + "Show changes between the working tree and the index." + (interactive (magit-diff-arguments)) + (magit-diff-setup-buffer nil nil args files)) + +;;;###autoload +(defun magit-diff-unmerged (&optional args files) + "Show changes that are being merged." + (interactive (magit-diff-arguments)) + (unless (magit-merge-in-progress-p) + (user-error "No merge is in progress")) + (magit-diff-setup-buffer (magit--merge-range) nil args files)) + +;;;###autoload +(defun magit-diff-while-committing (&optional args) + "While committing, show the changes that are about to be committed. +While amending, invoking the command again toggles between +showing just the new changes or all the changes that will +be committed." + (interactive (list (car (magit-diff-arguments)))) + (unless (magit-commit-message-buffer) + (user-error "No commit in progress")) + (let ((magit-display-buffer-noselect t)) + (if-let ((diff-buf (magit-get-mode-buffer 'magit-diff-mode 'selected))) + (with-current-buffer diff-buf + (cond ((and (equal magit-buffer-range "HEAD^") + (equal magit-buffer-typearg "--cached")) + (magit-diff-staged nil args)) + ((and (equal magit-buffer-range nil) + (equal magit-buffer-typearg "--cached")) + (magit-diff-while-amending args)) + ((magit-anything-staged-p) + (magit-diff-staged nil args)) + (t + (magit-diff-while-amending args)))) + (if (magit-anything-staged-p) + (magit-diff-staged nil args) + (magit-diff-while-amending args))))) + +(define-key git-commit-mode-map + (kbd "C-c C-d") 'magit-diff-while-committing) + +(defun magit-diff-while-amending (&optional args) + (magit-diff-setup-buffer "HEAD^" "--cached" args nil)) + +;;;###autoload +(defun magit-diff-buffer-file () + "Show diff for the blob or file visited in the current buffer. + +When the buffer visits a blob, then show the respective commit. +When the buffer visits a file, then show the differenced between +`HEAD' and the working tree. In both cases limit the diff to +the file or blob." + (interactive) + (require 'magit) + (if-let ((file (magit-file-relative-name))) + (if magit-buffer-refname + (magit-show-commit magit-buffer-refname + (car (magit-show-commit--arguments)) + (list file)) + (save-buffer) + (let ((line (line-number-at-pos)) + (col (current-column))) + (with-current-buffer + (magit-diff-setup-buffer (or (magit-get-current-branch) "HEAD") + nil + (car (magit-diff-arguments)) + (list file) + magit-diff-buffer-file-locked) + (magit-diff--goto-position file line col)))) + (user-error "Buffer isn't visiting a file"))) + +;;;###autoload +(defun magit-diff-paths (a b) + "Show changes between any two files on disk." + (interactive (list (read-file-name "First file: " nil nil t) + (read-file-name "Second file: " nil nil t))) + (magit-diff-setup-buffer nil "--no-index" + nil (list (magit-convert-filename-for-git + (expand-file-name a)) + (magit-convert-filename-for-git + (expand-file-name b))))) + +(defun magit-show-commit--arguments () + (pcase-let ((`(,args ,diff-files) + (magit-diff-arguments 'magit-revision-mode))) + (list args (if (derived-mode-p 'magit-log-mode) + (and (or magit-revision-filter-files-on-follow + (not (member "--follow" magit-buffer-log-args))) + magit-buffer-log-files) + diff-files)))) + +;;;###autoload +(defun magit-show-commit (rev &optional args files module) + "Visit the revision at point in another buffer. +If there is no revision at point or with a prefix argument prompt +for a revision." + (interactive + (pcase-let* ((mcommit (magit-section-value-if 'module-commit)) + (atpoint (or (and (bound-and-true-p magit-blame-mode) + (oref (magit-current-blame-chunk) orig-rev)) + mcommit + (magit-branch-or-commit-at-point))) + (`(,args ,files) (magit-show-commit--arguments))) + (list (or (and (not current-prefix-arg) atpoint) + (magit-read-branch-or-commit "Show commit" atpoint)) + args + files + (and mcommit + (magit-section-parent-value (magit-current-section)))))) + (require 'magit) + (let ((file (magit-file-relative-name))) + (magit-with-toplevel + (when module + (setq default-directory + (expand-file-name (file-name-as-directory module)))) + (unless (magit-commit-p rev) + (user-error "%s is not a commit" rev)) + (let ((buf (magit-revision-setup-buffer rev args files))) + (when file + (save-buffer) + (let ((line (magit-diff-visit--offset file (list "-R" rev) + (line-number-at-pos))) + (col (current-column))) + (with-current-buffer buf + (magit-diff--goto-position file line col)))))))) + +(defun magit-diff--locate-hunk (file line &optional parent) + (when-let ((diff (cl-find-if (lambda (section) + (and (cl-typep section 'magit-file-section) + (equal (oref section value) file))) + (oref (or parent magit-root-section) children)))) + (let (hunk (hunks (oref diff children))) + (cl-block nil + (while (setq hunk (pop hunks)) + (pcase-let* ((`(,beg ,len) (oref hunk to-range)) + (end (+ beg len))) + (cond ((> beg line) (cl-return (list diff nil))) + ((<= beg line end) (cl-return (list hunk t))) + ((null hunks) (cl-return (list hunk nil)))))))))) + +(defun magit-diff--goto-position (file line column &optional parent) + (when-let ((pos (magit-diff--locate-hunk file line parent))) + (pcase-let ((`(,section ,exact) pos)) + (cond ((cl-typep section 'magit-file-section) + (goto-char (oref section start))) + (exact + (goto-char (oref section content)) + (let ((pos (car (oref section to-range)))) + (while (or (< pos line) + (= (char-after) ?-)) + (unless (= (char-after) ?-) + (cl-incf pos)) + (forward-line))) + (forward-char (1+ column))) + (t + (goto-char (oref section start)) + (setq section (oref section parent)))) + (while section + (when (oref section hidden) + (magit-section-show section)) + (setq section (oref section parent)))) + (magit-section-update-highlight) + t)) + +(cl-defmethod magit-buffer-value (&context (major-mode magit-revision-mode)) + (cons magit-buffer-range magit-buffer-diff-files)) + +;;;; Setting Commands + +(defun magit-diff-switch-range-type () + "Convert diff range type. +Change \"revA..revB\" to \"revA...revB\", or vice versa." + (interactive) + (if (and magit-buffer-range + (derived-mode-p 'magit-diff-mode) + (string-match magit-range-re magit-buffer-range)) + (setq magit-buffer-range + (replace-match (if (string= (match-string 2 magit-buffer-range) "..") + "..." + "..") + t t magit-buffer-range 2)) + (user-error "No range to change")) + (magit-refresh)) + +(defun magit-diff-flip-revs () + "Swap revisions in diff range. +Change \"revA..revB\" to \"revB..revA\"." + (interactive) + (if (and magit-buffer-range + (derived-mode-p 'magit-diff-mode) + (string-match magit-range-re magit-buffer-range)) + (progn + (setq magit-buffer-range + (concat (match-string 3 magit-buffer-range) + (match-string 2 magit-buffer-range) + (match-string 1 magit-buffer-range))) + (magit-refresh)) + (user-error "No range to swap"))) + +(defun magit-diff-toggle-file-filter () + "Toggle the file restriction of the current buffer's diffs. +If the current buffer's mode is derived from `magit-log-mode', +toggle the file restriction in the repository's revision buffer +instead." + (interactive) + (cl-flet ((toggle () + (if (or magit-buffer-diff-files + magit-buffer-diff-files-suspended) + (cl-rotatef magit-buffer-diff-files + magit-buffer-diff-files-suspended) + (setq magit-buffer-diff-files + (magit-read-files "Limit to file(s): " + (magit-file-at-point) + nil))) + (magit-refresh))) + (cond + ((derived-mode-p 'magit-log-mode + 'magit-cherry-mode + 'magit-reflog-mode) + (if-let ((buffer (magit-get-mode-buffer 'magit-revision-mode))) + (with-current-buffer buffer (toggle)) + (message "No revision buffer"))) + ((local-variable-p 'magit-buffer-diff-files) + (toggle)) + (t + (user-error "Cannot toggle file filter in this buffer"))))) + +(defun magit-diff-less-context (&optional count) + "Decrease the context for diff hunks by COUNT lines." + (interactive "p") + (magit-diff-set-context `(lambda (cur) (max 0 (- (or cur 0) ,count))))) + +(defun magit-diff-more-context (&optional count) + "Increase the context for diff hunks by COUNT lines." + (interactive "p") + (magit-diff-set-context `(lambda (cur) (+ (or cur 0) ,count)))) + +(defun magit-diff-default-context () + "Reset context for diff hunks to the default height." + (interactive) + (magit-diff-set-context #'ignore)) + +(defun magit-diff-set-context (fn) + (let* ((def (--if-let (magit-get "diff.context") (string-to-number it) 3)) + (val magit-buffer-diff-args) + (arg (--first (string-match "^-U\\([0-9]+\\)?$" it) val)) + (num (--if-let (and arg (match-string 1 arg)) (string-to-number it) def)) + (val (delete arg val)) + (num (funcall fn num)) + (arg (and num (not (= num def)) (format "-U%i" num))) + (val (if arg (cons arg val) val))) + (setq magit-buffer-diff-args val)) + (magit-refresh)) + +(defun magit-diff-context-p () + (if-let ((arg (--first (string-match "^-U\\([0-9]+\\)$" it) + magit-buffer-diff-args))) + (not (equal arg "-U0")) + t)) + +(defun magit-diff-ignore-any-space-p () + (--any-p (member it magit-buffer-diff-args) + '("--ignore-cr-at-eol" + "--ignore-space-at-eol" + "--ignore-space-change" "-b" + "--ignore-all-space" "-w" + "--ignore-blank-space"))) + +(defun magit-diff-toggle-refine-hunk (&optional style) + "Turn diff-hunk refining on or off. + +If hunk refining is currently on, then hunk refining is turned off. +If hunk refining is off, then hunk refining is turned on, in +`selected' mode (only the currently selected hunk is refined). + +With a prefix argument, the \"third choice\" is used instead: +If hunk refining is currently on, then refining is kept on, but +the refining mode (`selected' or `all') is switched. +If hunk refining is off, then hunk refining is turned on, in +`all' mode (all hunks refined). + +Customize variable `magit-diff-refine-hunk' to change the default mode." + (interactive "P") + (setq-local magit-diff-refine-hunk + (if style + (if (eq magit-diff-refine-hunk 'all) t 'all) + (not magit-diff-refine-hunk))) + (magit-diff-update-hunk-refinement)) + +;;;; Visit Commands +;;;;; Dwim Variants + +(defun magit-diff-visit-file (file &optional other-window) + "From a diff visit the appropriate version of FILE. + +Display the buffer in the selected window. With a prefix +argument OTHER-WINDOW display the buffer in another window +instead. + +Visit the worktree version of the appropriate file. The location +of point inside the diff determines which file is being visited. +The visited version depends on what changes the diff is about. + +1. If the diff shows uncommitted changes (i.e. stage or unstaged + changes), then visit the file in the working tree (i.e. the + same \"real\" file that `find-file' would visit. In all other + cases visit a \"blob\" (i.e. the version of a file as stored + in some commit). + +2. If point is on a removed line, then visit the blob for the + first parent of the commit that removed that line, i.e. the + last commit where that line still exists. + +3. If point is on an added or context line, then visit the blob + that adds that line, or if the diff shows from more than a + single commit, then visit the blob from the last of these + commits. + +In the file-visiting buffer also go to the line that corresponds +to the line that point is on in the diff. + +Note that this command only works if point is inside a diff. In +other cases `magit-find-file' (which see) had to be used." + (interactive (list (magit-file-at-point t t) current-prefix-arg)) + (magit-diff-visit-file--internal file nil + (if other-window + #'switch-to-buffer-other-window + #'pop-to-buffer-same-window))) + +(defun magit-diff-visit-file-other-window (file) + "From a diff visit the appropriate version of FILE in another window. +Like `magit-diff-visit-file' but use +`switch-to-buffer-other-window'." + (interactive (list (magit-file-at-point t t))) + (magit-diff-visit-file--internal file nil #'switch-to-buffer-other-window)) + +(defun magit-diff-visit-file-other-frame (file) + "From a diff visit the appropriate version of FILE in another frame. +Like `magit-diff-visit-file' but use +`switch-to-buffer-other-frame'." + (interactive (list (magit-file-at-point t t))) + (magit-diff-visit-file--internal file nil #'switch-to-buffer-other-frame)) + +;;;;; Worktree Variants + +(defun magit-diff-visit-worktree-file (file &optional other-window) + "From a diff visit the worktree version of FILE. + +Display the buffer in the selected window. With a prefix +argument OTHER-WINDOW display the buffer in another window +instead. + +Visit the worktree version of the appropriate file. The location +of point inside the diff determines which file is being visited. + +Unlike `magit-diff-visit-file' always visits the \"real\" file in +the working tree, i.e the \"current version\" of the file. + +In the file-visiting buffer also go to the line that corresponds +to the line that point is on in the diff. Lines that were added +or removed in the working tree, the index and other commits in +between are automatically accounted for." + (interactive (list (magit-file-at-point t t) current-prefix-arg)) + (magit-diff-visit-file--internal file t + (if other-window + #'switch-to-buffer-other-window + #'pop-to-buffer-same-window))) + +(defun magit-diff-visit-worktree-file-other-window (file) + "From a diff visit the worktree version of FILE in another window. +Like `magit-diff-visit-worktree-file' but use +`switch-to-buffer-other-window'." + (interactive (list (magit-file-at-point t t))) + (magit-diff-visit-file--internal file t #'switch-to-buffer-other-window)) + +(defun magit-diff-visit-worktree-file-other-frame (file) + "From a diff visit the worktree version of FILE in another frame. +Like `magit-diff-visit-worktree-file' but use +`switch-to-buffer-other-frame'." + (interactive (list (magit-file-at-point t t))) + (magit-diff-visit-file--internal file t #'switch-to-buffer-other-frame)) + +;;;;; Internal + +(defun magit-diff-visit-file--internal (file force-worktree fn) + "From a diff visit the appropriate version of FILE. +If FORCE-WORKTREE is non-nil, then visit the worktree version of +the file, even if the diff is about a committed change. USE FN +to display the buffer in some window." + (if (magit-file-accessible-directory-p file) + (magit-diff-visit-directory file force-worktree) + (pcase-let ((`(,buf ,pos) + (magit-diff-visit-file--noselect file force-worktree))) + (funcall fn buf) + (magit-diff-visit-file--setup buf pos) + buf))) + +(defun magit-diff-visit-directory (directory &optional other-window) + "Visit DIRECTORY in some window. +Display the buffer in the selected window unless OTHER-WINDOW is +non-nil. If DIRECTORY is the top-level directory of the current +repository, then visit the containing directory using Dired and +in the Dired buffer put point on DIRECTORY. Otherwise display +the Magit-Status buffer for DIRECTORY." + (if (equal (magit-toplevel directory) + (magit-toplevel)) + (dired-jump other-window (concat directory "/.")) + (let ((display-buffer-overriding-action + (if other-window + '(nil (inhibit-same-window t)) + '(display-buffer-same-window)))) + (magit-status-setup-buffer directory)))) + +(defun magit-diff-visit-file--setup (buf pos) + (if-let ((win (get-buffer-window buf 'visible))) + (with-selected-window win + (when pos + (unless (<= (point-min) pos (point-max)) + (widen)) + (goto-char pos)) + (when (and buffer-file-name + (magit-anything-unmerged-p buffer-file-name)) + (smerge-start-session)) + (run-hooks 'magit-diff-visit-file-hook)) + (error "File buffer is not visible"))) + +(defun magit-diff-visit-file--noselect (&optional file goto-worktree) + (unless file + (setq file (magit-file-at-point t t))) + (let* ((hunk (magit-diff-visit--hunk)) + (goto-from (and hunk + (magit-diff-visit--goto-from-p hunk goto-worktree))) + (line (and hunk (magit-diff-hunk-line hunk goto-from))) + (col (and hunk (magit-diff-hunk-column hunk goto-from))) + (spec (magit-diff--dwim)) + (rev (if goto-from + (magit-diff-visit--range-from spec) + (magit-diff-visit--range-to spec))) + (buf (if (or goto-worktree + (and (not (stringp rev)) + (or magit-diff-visit-avoid-head-blob + (not goto-from)))) + (or (get-file-buffer file) + (find-file-noselect file)) + (magit-find-file-noselect (if (stringp rev) rev "HEAD") + file)))) + (if line + (with-current-buffer buf + (cond ((eq rev 'staged) + (setq line (magit-diff-visit--offset file nil line))) + ((and goto-worktree + (stringp rev)) + (setq line (magit-diff-visit--offset file rev line)))) + (list buf (save-restriction + (widen) + (goto-char (point-min)) + (forward-line (1- line)) + (move-to-column col) + (point)))) + (list buf nil)))) + +(defun magit-diff-visit--hunk () + (when-let ((scope (magit-diff-scope))) + (let ((section (magit-current-section))) + (cl-case scope + ((file files) + (setq section (car (oref section children)))) + (list + (setq section (car (oref section children))) + (when section + (setq section (car (oref section children)))))) + (and + ;; Unmerged files appear in the list of staged changes + ;; but unlike in the list of unstaged changes no diffs + ;; are shown here. In that case `section' is nil. + section + ;; Currently the `hunk' type is also abused for file + ;; mode changes, which we are not interested in here. + ;; Such sections have no value. + (oref section value) + section)))) + +(defun magit-diff-visit--goto-from-p (section in-worktree) + (and magit-diff-visit-previous-blob + (not in-worktree) + (not (oref section combined)) + (not (< (point) (oref section content))) + (= (char-after (line-beginning-position)) ?-))) + +(defun magit-diff-hunk-line (section goto-from) + (save-excursion + (goto-char (line-beginning-position)) + (with-slots (content combined from-ranges from-range to-range) section + (when (< (point) content) + (goto-char content) + (re-search-forward "^[-+]")) + (+ (car (if goto-from from-range to-range)) + (let ((prefix (if combined (length from-ranges) 1)) + (target (point)) + (offset 0)) + (goto-char content) + (while (< (point) target) + (unless (string-match-p + (if goto-from "\\+" "-") + (buffer-substring (point) (+ (point) prefix))) + (cl-incf offset)) + (forward-line)) + offset))))) + +(defun magit-diff-hunk-column (section goto-from) + (if (or (< (point) + (oref section content)) + (and (not goto-from) + (= (char-after (line-beginning-position)) ?-))) + 0 + (max 0 (- (+ (current-column) 2) + (length (oref section value)))))) + +(defun magit-diff-visit--range-from (spec) + (cond ((consp spec) + (concat (cdr spec) "^")) + ((stringp spec) + (car (magit-split-range spec))) + (t + spec))) + +(defun magit-diff-visit--range-to (spec) + (if (symbolp spec) + spec + (let ((rev (if (consp spec) + (cdr spec) + (cdr (magit-split-range spec))))) + (if (and magit-diff-visit-avoid-head-blob + (magit-rev-head-p spec)) + 'unstaged + rev)))) + +(defun magit-diff-visit--offset (file rev line) + (let ((offset 0)) + (with-temp-buffer + (save-excursion + (magit-with-toplevel + (magit-git-insert "diff" rev "--" file))) + (catch 'found + (while (re-search-forward + "^@@ -\\([0-9]+\\),\\([0-9]+\\) \\+\\([0-9]+\\),\\([0-9]+\\) @@.*\n" + nil t) + (let ((from-beg (string-to-number (match-string 1))) + (from-len (string-to-number (match-string 2))) + ( to-len (string-to-number (match-string 4)))) + (if (<= from-beg line) + (if (< (+ from-beg from-len) line) + (cl-incf offset (- to-len from-len)) + (let ((rest (- line from-beg))) + (while (> rest 0) + (pcase (char-after) + (?\s (cl-decf rest)) + (?- (cl-decf offset) (cl-decf rest)) + (?+ (cl-incf offset))) + (forward-line)))) + (throw 'found nil)))))) + (+ line offset))) + +;;;; Scroll Commands + +(defun magit-diff-show-or-scroll-up () + "Update the commit or diff buffer for the thing at point. + +Either show the commit or stash at point in the appropriate +buffer, or if that buffer is already being displayed in the +current frame and contains information about that commit or +stash, then instead scroll the buffer up. If there is no +commit or stash at point, then prompt for a commit." + (interactive) + (magit-diff-show-or-scroll 'scroll-up)) + +(defun magit-diff-show-or-scroll-down () + "Update the commit or diff buffer for the thing at point. + +Either show the commit or stash at point in the appropriate +buffer, or if that buffer is already being displayed in the +current frame and contains information about that commit or +stash, then instead scroll the buffer down. If there is no +commit or stash at point, then prompt for a commit." + (interactive) + (magit-diff-show-or-scroll 'scroll-down)) + +(defun magit-diff-show-or-scroll (fn) + (let (rev cmd buf win) + (cond + (magit-blame-mode + (setq rev (oref (magit-current-blame-chunk) orig-rev)) + (setq cmd 'magit-show-commit) + (setq buf (magit-get-mode-buffer 'magit-revision-mode))) + ((derived-mode-p 'git-rebase-mode) + (with-slots (action-type target) + (git-rebase-current-line) + (if (not (eq action-type 'commit)) + (user-error "No commit on this line") + (setq rev target) + (setq cmd 'magit-show-commit) + (setq buf (magit-get-mode-buffer 'magit-revision-mode))))) + (t + (magit-section-case + (branch + (setq rev (magit-ref-maybe-qualify (oref it value))) + (setq cmd 'magit-show-commit) + (setq buf (magit-get-mode-buffer 'magit-revision-mode))) + (commit + (setq rev (oref it value)) + (setq cmd 'magit-show-commit) + (setq buf (magit-get-mode-buffer 'magit-revision-mode))) + (stash + (setq rev (oref it value)) + (setq cmd 'magit-stash-show) + (setq buf (magit-get-mode-buffer 'magit-stash-mode)))))) + (if rev + (if (and buf + (setq win (get-buffer-window buf)) + (with-current-buffer buf + (and (equal rev magit-buffer-revision) + (equal (magit-rev-parse rev) + magit-buffer-revision-hash)))) + (with-selected-window win + (condition-case nil + (funcall fn) + (error + (goto-char (pcase fn + (`scroll-up (point-min)) + (`scroll-down (point-max))))))) + (let ((magit-display-buffer-noselect t)) + (if (eq cmd 'magit-show-commit) + (apply #'magit-show-commit rev (magit-show-commit--arguments)) + (funcall cmd rev)))) + (call-interactively #'magit-show-commit)))) + +;;; Diff Mode + +(defvar magit-diff-mode-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map magit-mode-map) + (define-key map (kbd "C-c C-d") 'magit-diff-while-committing) + (define-key map (kbd "C-c C-b") 'magit-go-backward) + (define-key map (kbd "C-c C-f") 'magit-go-forward) + (define-key map (kbd "SPC") 'scroll-up) + (define-key map (kbd "DEL") 'scroll-down) + (define-key map (kbd "j") 'magit-jump-to-diffstat-or-diff) + (define-key map [remap write-file] 'magit-patch-save) + map) + "Keymap for `magit-diff-mode'.") + +(define-derived-mode magit-diff-mode magit-mode "Magit Diff" + "Mode for looking at a Git diff. + +This mode is documented in info node `(magit)Diff Buffer'. + +\\\ +Type \\[magit-refresh] to refresh the current buffer. +Type \\[magit-section-toggle] to expand or hide the section at point. +Type \\[magit-visit-thing] to visit the hunk or file at point. + +Staging and applying changes is documented in info node +`(magit)Staging and Unstaging' and info node `(magit)Applying'. + +\\Type \ +\\[magit-apply] to apply the change at point, \ +\\[magit-stage] to stage, +\\[magit-unstage] to unstage, \ +\\[magit-discard] to discard, or \ +\\[magit-reverse] to reverse it. + +\\{magit-diff-mode-map}" + :group 'magit-diff + (hack-dir-local-variables-non-file-buffer) + (setq imenu-prev-index-position-function + 'magit-imenu--diff-prev-index-position-function) + (setq imenu-extract-index-name-function + 'magit-imenu--diff-extract-index-name-function)) + +(put 'magit-diff-mode 'magit-diff-default-arguments + '("--stat" "--no-ext-diff")) + +(defun magit-diff-setup-buffer (range typearg args files &optional locked) + (require 'magit) + (magit-setup-buffer #'magit-diff-mode locked + (magit-buffer-range range) + (magit-buffer-typearg typearg) + (magit-buffer-diff-args args) + (magit-buffer-diff-files files))) + +(defun magit-diff-refresh-buffer () + "Refresh the current `magit-diff-mode' buffer." + (magit-set-header-line-format + (if (equal magit-buffer-typearg "--no-index") + (apply #'format "Differences between %s and %s" magit-buffer-diff-files) + (concat (if magit-buffer-range + (if (string-match-p "\\(\\.\\.\\|\\^-\\)" + magit-buffer-range) + (format "Changes in %s" magit-buffer-range) + (format "Changes from %s to working tree" magit-buffer-range)) + (if (equal magit-buffer-typearg "--cached") + "Staged changes" + "Unstaged changes")) + (pcase (length magit-buffer-diff-files) + (0) + (1 (concat " in file " (car magit-buffer-diff-files))) + (_ (concat " in files " + (mapconcat #'identity magit-buffer-diff-files ", "))))))) + (setq magit-buffer-range-hashed + (and magit-buffer-range (magit-hash-range magit-buffer-range))) + (magit-insert-section (diffbuf) + (magit-run-section-hook 'magit-diff-sections-hook))) + +(cl-defmethod magit-buffer-value (&context (major-mode magit-diff-mode)) + (nconc (cond (magit-buffer-range + (delq nil (list magit-buffer-range magit-buffer-typearg))) + ((equal magit-buffer-typearg "--cached") + (list 'staged)) + (t + (list 'unstaged magit-buffer-typearg))) + (and magit-buffer-diff-files (cons "--" magit-buffer-diff-files)))) + +(defvar magit-file-section-map + (let ((map (make-sparse-keymap))) + (unless (featurep 'jkl) + (define-key map (kbd "C-j") 'magit-diff-visit-worktree-file)) + (define-key map [C-return] 'magit-diff-visit-worktree-file) + (define-key map [remap magit-visit-thing] 'magit-diff-visit-file) + (define-key map [remap magit-delete-thing] 'magit-discard) + (define-key map [remap magit-revert-no-commit] 'magit-reverse) + (define-key map "a" 'magit-apply) + (define-key map "C" 'magit-commit-add-log) + (define-key map "s" 'magit-stage) + (define-key map "u" 'magit-unstage) + (define-key map "&" 'magit-do-async-shell-command) + (define-key map "\C-c\C-t" 'magit-diff-trace-definition) + (define-key map "\C-c\C-e" 'magit-diff-edit-hunk-commit) + map) + "Keymap for `file' sections.") + +(defvar magit-hunk-section-map + (let ((map (make-sparse-keymap))) + (unless (featurep 'jkl) + (define-key map (kbd "C-j") 'magit-diff-visit-worktree-file)) + (define-key map [C-return] 'magit-diff-visit-worktree-file) + (define-key map [remap magit-visit-thing] 'magit-diff-visit-file) + (define-key map [remap magit-delete-thing] 'magit-discard) + (define-key map [remap magit-revert-no-commit] 'magit-reverse) + (define-key map "a" 'magit-apply) + (define-key map "C" 'magit-commit-add-log) + (define-key map "s" 'magit-stage) + (define-key map "u" 'magit-unstage) + (define-key map "&" 'magit-do-async-shell-command) + (define-key map "\C-c\C-t" 'magit-diff-trace-definition) + (define-key map "\C-c\C-e" 'magit-diff-edit-hunk-commit) + map) + "Keymap for `hunk' sections.") + +(defconst magit-diff-headline-re + (concat "^\\(@@@?\\|diff\\|Submodule\\|" + "\\* Unmerged path\\|merged\\|changed in both\\|" + "added in remote\\|removed in remote\\)")) + +(defconst magit-diff-statline-re + (concat "^ ?" + "\\(.*\\)" ; file + "\\( +| +\\)" ; separator + "\\([0-9]+\\|Bin\\(?: +[0-9]+ -> [0-9]+ bytes\\)?$\\) ?" + "\\(\\+*\\)" ; add + "\\(-*\\)$")) ; del + +(defvar magit-diff--reset-non-color-moved + (list + "-c" "color.diff.context=normal" + "-c" "color.diff.plain=normal" ; historical synonym for context + "-c" "color.diff.meta=normal" + "-c" "color.diff.frag=normal" + "-c" "color.diff.func=normal" + "-c" "color.diff.old=normal" + "-c" "color.diff.new=normal" + "-c" "color.diff.commit=normal" + "-c" "color.diff.whitespace=normal" + ;; "git-range-diff" does not support "--color-moved", so we don't + ;; need to reset contextDimmed, oldDimmed, newDimmed, contextBold, + ;; oldBold, and newBold. + )) + +(defun magit-insert-diff () + "Insert the diff into this `magit-diff-mode' buffer." + (magit--insert-diff + "diff" magit-buffer-range "-p" "--no-prefix" + (and (member "--stat" magit-buffer-diff-args) "--numstat") + magit-buffer-typearg + magit-buffer-diff-args "--" + magit-buffer-diff-files)) + +(defun magit--insert-diff (&rest args) + (declare (indent 0)) + (let ((magit-git-global-arguments + (remove "--literal-pathspecs" magit-git-global-arguments))) + (setq args (-flatten args)) + (when (cl-member-if (lambda (arg) (string-prefix-p "--color-moved" arg)) args) + (push "--color=always" (cdr args)) + (setq magit-git-global-arguments + (append magit-diff--reset-non-color-moved + magit-git-global-arguments))) + (magit-git-wash #'magit-diff-wash-diffs args))) + +(defun magit-diff-wash-diffs (args &optional limit) + (when (member "--show-signature" args) + (magit-diff-wash-signature)) + (when (member "--stat" args) + (magit-diff-wash-diffstat)) + (when (re-search-forward magit-diff-headline-re limit t) + (goto-char (line-beginning-position)) + (magit-wash-sequence (apply-partially 'magit-diff-wash-diff args)) + (insert ?\n))) + +(defun magit-jump-to-diffstat-or-diff () + "Jump to the diffstat or diff. +When point is on a file inside the diffstat section, then jump +to the respective diff section, otherwise jump to the diffstat +section or a child thereof." + (interactive) + (--if-let (magit-get-section + (append (magit-section-case + ([file diffstat] `((file . ,(oref it value)))) + (file `((file . ,(oref it value)) (diffstat))) + (t '((diffstat)))) + (magit-section-ident magit-root-section))) + (magit-section-goto it) + (user-error "No diffstat in this buffer"))) + +(defun magit-diff-wash-signature () + (when (looking-at "^gpg: ") + (magit-insert-section (signature) + (while (looking-at "^gpg: ") + (forward-line)) + (insert "\n")))) + +(defun magit-diff-wash-diffstat () + (let (heading (beg (point))) + (when (re-search-forward "^ ?\\([0-9]+ +files? change[^\n]*\n\\)" nil t) + (setq heading (match-string 1)) + (magit-delete-match) + (goto-char beg) + (magit-insert-section (diffstat) + (insert (propertize heading 'font-lock-face 'magit-diff-file-heading)) + (magit-insert-heading) + (let (files) + (while (looking-at "^[-0-9]+\t[-0-9]+\t\\(.+\\)$") + (push (magit-decode-git-path + (let ((f (match-string 1))) + (cond + ((string-match "\\`\\([^{]+\\){\\(.+\\) => \\(.+\\)}\\'" f) + (concat (match-string 1 f) + (match-string 3 f))) + ((string-match " => " f) + (substring f (match-end 0))) + (t f)))) + files) + (magit-delete-line)) + (setq files (nreverse files)) + (while (looking-at magit-diff-statline-re) + (magit-bind-match-strings (file sep cnt add del) nil + (magit-delete-line) + (when (string-match " +$" file) + (setq sep (concat (match-string 0 file) sep)) + (setq file (substring file 0 (match-beginning 0)))) + (let ((le (length file)) ld) + (setq file (magit-decode-git-path file)) + (setq ld (length file)) + (when (> le ld) + (setq sep (concat (make-string (- le ld) ?\s) sep)))) + (magit-insert-section (file (pop files)) + (insert (propertize file 'font-lock-face 'magit-filename) + sep cnt " ") + (when add + (insert (propertize add 'font-lock-face + 'magit-diffstat-added))) + (when del + (insert (propertize del 'font-lock-face + 'magit-diffstat-removed))) + (insert "\n"))))) + (if (looking-at "^$") (forward-line) (insert "\n")))))) + +(defun magit-diff-wash-diff (args) + (when (cl-member-if (lambda (arg) (string-prefix-p "--color-moved" arg)) args) + (require 'ansi-color) + (ansi-color-apply-on-region (point-min) (point-max))) + (cond + ((looking-at "^Submodule") + (magit-diff-wash-submodule)) + ((looking-at "^\\* Unmerged path \\(.*\\)") + (let ((file (magit-decode-git-path (match-string 1)))) + (magit-delete-line) + (unless (and (derived-mode-p 'magit-status-mode) + (not (member "--cached" args))) + (magit-insert-section (file file) + (insert (propertize + (format "unmerged %s%s" file + (pcase (cddr (car (magit-file-status file))) + (`(?D ?D) " (both deleted)") + (`(?D ?U) " (deleted by us)") + (`(?U ?D) " (deleted by them)") + (`(?A ?A) " (both added)") + (`(?A ?U) " (added by us)") + (`(?U ?A) " (added by them)") + (`(?U ?U) ""))) + 'font-lock-face 'magit-diff-file-heading)) + (insert ?\n)))) + t) + ((looking-at (concat "^\\(merged\\|changed in both\\|" + "added in remote\\|removed in remote\\)")) + (let ((status (pcase (match-string 1) + ("merged" "merged") + ("changed in both" "conflict") + ("added in remote" "new file") + ("removed in remote" "deleted"))) + file orig base modes) + (magit-delete-line) + (while (looking-at + "^ \\([^ ]+\\) +[0-9]\\{6\\} \\([a-z0-9]\\{40\\}\\) \\(.+\\)$") + (magit-bind-match-strings (side _blob name) nil + (pcase side + ("result" (setq file name)) + ("our" (setq orig name)) + ("their" (setq file name)) + ("base" (setq base name)))) + (magit-delete-line)) + (when orig (setq orig (magit-decode-git-path orig))) + (when file (setq file (magit-decode-git-path file))) + (magit-diff-insert-file-section (or file base) orig status modes nil))) + ((looking-at + "^diff --\\(?:\\(git\\) \\(?:\\(.+?\\) \\2\\)?\\|\\(cc\\|combined\\) \\(.+\\)\\)") + (let ((status (cond ((equal (match-string 1) "git") "modified") + ((derived-mode-p 'magit-revision-mode) "resolved") + (t "unmerged"))) + (file (or (match-string 2) (match-string 4))) + (beg (point)) + orig header modes) + (save-excursion + (forward-line 1) + (setq header (buffer-substring + beg (if (re-search-forward magit-diff-headline-re nil t) + (match-beginning 0) + (point-max))))) + (magit-delete-line) + (while (not (or (eobp) (looking-at magit-diff-headline-re))) + (if (looking-at "^old mode \\([^\n]+\\)\nnew mode \\([^\n]+\\)\n") + (progn (setq modes (match-string 0)) + (magit-delete-match)) + (cond + ((looking-at "^--- \\([^/].*?\\)\t?$") ; i.e. not /dev/null + (setq orig (match-string 1))) + ((looking-at "^\\+\\+\\+ \\([^/].*?\\)\t?$") + (setq file (match-string 1))) + ((looking-at "^\\(copy\\|rename\\) from \\(.+\\)$") + (setq orig (match-string 2))) + ((looking-at "^\\(copy\\|rename\\) to \\(.+\\)$") + (setq file (match-string 2)) + (setq status (if (equal (match-string 1) "copy") "new file" "renamed"))) + ((looking-at "^\\(new file\\|deleted\\)") + (setq status (match-string 1)))) + (magit-delete-line))) + (when orig + (setq orig (magit-decode-git-path orig))) + (setq file (magit-decode-git-path file)) + ;; KLUDGE `git-log' ignores `--no-prefix' when `-L' is used. + (when (and (derived-mode-p 'magit-log-mode) + (--first (string-match-p "\\`-L" it) magit-buffer-log-args)) + (setq file (substring file 2)) + (when orig + (setq orig (substring orig 2)))) + (magit-diff-insert-file-section file orig status modes header))))) + +(defun magit-diff-insert-file-section (file orig status modes header) + (magit-insert-section section + (file file (or (equal status "deleted") + (derived-mode-p 'magit-status-mode))) + (insert (propertize (format "%-10s %s\n" status + (if (or (not orig) (equal orig file)) + file + (format "%s -> %s" orig file))) + 'font-lock-face 'magit-diff-file-heading)) + (magit-insert-heading) + (unless (equal orig file) + (oset section source orig)) + (oset section header header) + (when modes + (magit-insert-section (hunk) + (insert modes) + (magit-insert-heading))) + (magit-wash-sequence #'magit-diff-wash-hunk))) + +(defun magit-diff-wash-submodule () + ;; See `show_submodule_summary' in submodule.c and "this" commit. + (when (looking-at "^Submodule \\([^ ]+\\)") + (let ((module (match-string 1)) + untracked modified) + (when (looking-at "^Submodule [^ ]+ contains untracked content$") + (magit-delete-line) + (setq untracked t)) + (when (looking-at "^Submodule [^ ]+ contains modified content$") + (magit-delete-line) + (setq modified t)) + (cond + ((and (looking-at "^Submodule \\([^ ]+\\) \\([^ :]+\\)\\( (rewind)\\)?:$") + (equal (match-string 1) module)) + (magit-bind-match-strings (_module range rewind) nil + (magit-delete-line) + (while (looking-at "^ \\([<>]\\) \\(.+\\)$") + (magit-delete-line)) + (when rewind + (setq range (replace-regexp-in-string "[^.]\\(\\.\\.\\)[^.]" + "..." range t t 1))) + (magit-insert-section (magit-module-section module t) + (magit-insert-heading + (propertize (concat "modified " module) + 'font-lock-face 'magit-diff-file-heading) + " (" + (cond (rewind "rewind") + ((string-match-p "\\.\\.\\." range) "non-ff") + (t "new commits")) + (and (or modified untracked) + (concat ", " + (and modified "modified") + (and modified untracked " and ") + (and untracked "untracked") + " content")) + ")") + (let ((default-directory + (file-name-as-directory + (expand-file-name module (magit-toplevel))))) + (magit-git-wash (apply-partially 'magit-log-wash-log 'module) + "log" "--oneline" "--left-right" range) + (delete-char -1))))) + ((and (looking-at "^Submodule \\([^ ]+\\) \\([^ ]+\\) (\\([^)]+\\))$") + (equal (match-string 1) module)) + (magit-bind-match-strings (_module _range msg) nil + (magit-delete-line) + (magit-insert-section (magit-module-section module) + (magit-insert-heading + (propertize (concat "submodule " module) + 'font-lock-face 'magit-diff-file-heading) + " (" msg ")")))) + (t + (magit-insert-section (magit-module-section module) + (magit-insert-heading + (propertize (concat "modified " module) + 'font-lock-face 'magit-diff-file-heading) + " (" + (and modified "modified") + (and modified untracked " and ") + (and untracked "untracked") + " content)"))))))) + +(defun magit-diff-wash-hunk () + (when (looking-at "^@\\{2,\\} \\(.+?\\) @\\{2,\\}\\(?: \\(.*\\)\\)?") + (let* ((heading (match-string 0)) + (ranges (mapcar (lambda (str) + (mapcar (lambda (n) (string-to-number n)) + (split-string (substring str 1) ","))) + (split-string (match-string 1)))) + (about (match-string 2)) + (combined (= (length ranges) 3)) + (value (cons about ranges))) + (magit-delete-line) + (magit-insert-section section (hunk value) + (insert (propertize (concat heading "\n") + 'font-lock-face 'magit-diff-hunk-heading)) + (magit-insert-heading) + (while (not (or (eobp) (looking-at "^[^-+\s\\]"))) + (forward-line)) + (oset section end (point)) + (oset section washer 'magit-diff-paint-hunk) + (oset section combined combined) + (if combined + (oset section from-ranges (butlast ranges)) + (oset section from-range (car ranges))) + (oset section to-range (car (last ranges))) + (oset section about about))) + t)) + +(defun magit-diff-expansion-threshold (section) + "Keep new diff sections collapsed if washing takes too long." + (and (magit-file-section-p section) + (> (float-time (time-subtract (current-time) magit-refresh-start-time)) + magit-diff-expansion-threshold) + 'hide)) + +;;; Revision Mode + +(define-derived-mode magit-revision-mode magit-diff-mode "Magit Rev" + "Mode for looking at a Git commit. + +This mode is documented in info node `(magit)Revision Buffer'. + +\\\ +Type \\[magit-refresh] to refresh the current buffer. +Type \\[magit-section-toggle] to expand or hide the section at point. +Type \\[magit-visit-thing] to visit the hunk or file at point. + +Staging and applying changes is documented in info node +`(magit)Staging and Unstaging' and info node `(magit)Applying'. + +\\Type \ +\\[magit-apply] to apply the change at point, \ +\\[magit-stage] to stage, +\\[magit-unstage] to unstage, \ +\\[magit-discard] to discard, or \ +\\[magit-reverse] to reverse it. + +\\{magit-revision-mode-map}" + :group 'magit-revision + (hack-dir-local-variables-non-file-buffer)) + +(put 'magit-revision-mode 'magit-diff-default-arguments + '("--stat" "--no-ext-diff")) + +(defun magit-revision-setup-buffer (rev args files) + (magit-setup-buffer #'magit-revision-mode nil + (magit-buffer-revision rev) + (magit-buffer-range (format "%s^..%s" rev rev)) + (magit-buffer-diff-args args) + (magit-buffer-diff-files files))) + +(defun magit-revision-refresh-buffer () + (magit-set-header-line-format + (concat (capitalize (magit-object-type magit-buffer-revision)) + " " magit-buffer-revision + (pcase (length magit-buffer-diff-files) + (0) + (1 (concat " limited to file " (car magit-buffer-diff-files))) + (_ (concat " limited to files " + (mapconcat #'identity magit-buffer-diff-files ", ")))))) + (setq magit-buffer-revision-hash (magit-rev-parse magit-buffer-revision)) + (magit-insert-section (commitbuf) + (magit-run-section-hook 'magit-revision-sections-hook))) + +(cl-defmethod magit-buffer-value (&context (major-mode magit-revision-mode)) + (cons magit-buffer-revision magit-buffer-diff-files)) + +(defun magit-insert-revision-diff () + "Insert the diff into this `magit-revision-mode' buffer." + (magit--insert-diff + "show" "-p" "--cc" "--format=" "--no-prefix" + (and (member "--stat" magit-buffer-diff-args) "--numstat") + magit-buffer-diff-args + (concat magit-buffer-revision "^{commit}") + "--" magit-buffer-diff-files)) + +(defun magit-insert-revision-tag () + "Insert tag message and headers into a revision buffer. +This function only inserts anything when `magit-show-commit' is +called with a tag as argument, when that is called with a commit +or a ref which is not a branch, then it inserts nothing." + (when (equal (magit-object-type magit-buffer-revision) "tag") + (magit-insert-section (taginfo) + (let ((beg (point))) + ;; "git verify-tag -v" would output what we need, but the gpg + ;; output is send to stderr and we have no control over the + ;; order in which stdout and stderr are inserted, which would + ;; make parsing hard. We are forced to use "git cat-file tag" + ;; instead, which inserts the signature instead of verifying + ;; it. We remove that later and then insert the verification + ;; output using "git verify-tag" (without the "-v"). + (magit-git-insert "cat-file" "tag" magit-buffer-revision) + (goto-char beg) + (forward-line 3) + (delete-region beg (point))) + (looking-at "^tagger \\([^<]+\\) <\\([^>]+\\)") + (let ((heading (format "Tagger: %s <%s>" + (match-string 1) + (match-string 2)))) + (magit-delete-line) + (insert (propertize heading 'font-lock-face + 'magit-section-secondary-heading))) + (magit-insert-heading) + (if (re-search-forward "-----BEGIN PGP SIGNATURE-----" nil t) + (progn + (let ((beg (match-beginning 0))) + (re-search-forward "-----END PGP SIGNATURE-----") + (delete-region beg (point))) + (insert ?\n) + (process-file magit-git-executable nil t nil + "verify-tag" magit-buffer-revision)) + (goto-char (point-max))) + (insert ?\n)))) + +(defvar magit-commit-message-section-map + (let ((map (make-sparse-keymap))) + (define-key map [remap magit-visit-thing] 'magit-show-commit) + map) + "Keymap for `commit-message' sections.") + +(defun magit-insert-revision-message () + "Insert the commit message into a revision buffer." + (magit-insert-section section (commit-message) + (oset section heading-highlight-face 'magit-diff-revision-summary-highlight) + (let ((beg (point)) + (rev magit-buffer-revision)) + (insert (with-temp-buffer + (magit-rev-insert-format "%B" rev) + (magit-revision--wash-message))) + (if (= (point) (+ beg 2)) + (progn (backward-delete-char 2) + (insert "(no message)\n")) + (goto-char beg) + (save-excursion + (while (search-forward "\r\n" nil t) ; Remove trailing CRs. + (delete-region (match-beginning 0) (1+ (match-beginning 0))))) + (when magit-revision-fill-summary-line + (let ((fill-column (min magit-revision-fill-summary-line + (window-width)))) + (fill-region (point) (line-end-position)))) + (when magit-revision-use-hash-sections + (save-excursion + (while (not (eobp)) + (re-search-forward "\\_<" nil 'move) + (let ((beg (point))) + (re-search-forward "\\_>" nil t) + (when (> (point) beg) + (let ((text (buffer-substring-no-properties beg (point)))) + (when (pcase magit-revision-use-hash-sections + (`quickest ; false negatives and positives + (and (>= (length text) 7) + (string-match-p "[0-9]" text) + (string-match-p "[a-z]" text))) + (`quicker ; false negatives (number-less hashes) + (and (>= (length text) 7) + (string-match-p "[0-9]" text) + (magit-commit-p text))) + (`quick ; false negatives (short hashes) + (and (>= (length text) 7) + (magit-commit-p text))) + (`slow + (magit-commit-p text))) + (put-text-property beg (point) + 'font-lock-face 'magit-hash) + (let ((end (point))) + (goto-char beg) + (magit-insert-section (commit text) + (goto-char end)))))))))) + (save-excursion + (forward-line) + (magit--add-face-text-property + beg (point) 'magit-diff-revision-summary) + (magit-insert-heading)) + (when magit-diff-highlight-keywords + (save-excursion + (while (re-search-forward "\\[[^[]*\\]" nil t) + (let ((beg (match-beginning 0)) + (end (match-end 0))) + (put-text-property + beg end 'font-lock-face + (if-let ((face (get-text-property beg 'font-lock-face))) + (list face 'magit-keyword) + 'magit-keyword)))))) + (goto-char (point-max)))))) + +(defun magit-insert-revision-notes () + "Insert commit notes into a revision buffer." + (let* ((var "core.notesRef") + (def (or (magit-get var) "refs/notes/commits"))) + (dolist (ref (or (magit-list-active-notes-refs))) + (magit-insert-section section (notes ref (not (equal ref def))) + (oset section heading-highlight-face 'magit-diff-hunk-heading-highlight) + (let ((beg (point)) + (rev magit-buffer-revision)) + (insert (with-temp-buffer + (magit-git-insert "-c" (concat "core.notesRef=" ref) + "notes" "show" rev) + (magit-revision--wash-message))) + (if (= (point) beg) + (magit-cancel-section) + (goto-char beg) + (end-of-line) + (insert (format " (%s)" + (propertize (if (string-prefix-p "refs/notes/" ref) + (substring ref 11) + ref) + 'font-lock-face 'magit-refname))) + (forward-char) + (magit--add-face-text-property beg (point) 'magit-diff-hunk-heading) + (magit-insert-heading) + (goto-char (point-max)) + (insert ?\n))))))) + +(defun magit-revision--wash-message () + (let ((major-mode 'git-commit-mode)) + (hack-dir-local-variables) + (hack-local-variables-apply)) + (unless (memq git-commit-major-mode '(nil text-mode)) + (funcall git-commit-major-mode) + (font-lock-ensure)) + (buffer-string)) + +(defun magit-insert-revision-headers () + "Insert headers about the commit into a revision buffer." + (magit-insert-section (headers) + (--when-let (magit-rev-format "%D" magit-buffer-revision "--decorate=full") + (insert (magit-format-ref-labels it) ?\s)) + (insert (propertize + (magit-rev-parse (concat magit-buffer-revision "^{commit}")) + 'font-lock-face 'magit-hash)) + (magit-insert-heading) + (let ((beg (point))) + (magit-rev-insert-format magit-revision-headers-format + magit-buffer-revision) + (magit-insert-revision-gravatars magit-buffer-revision beg)) + (when magit-revision-insert-related-refs + (dolist (parent (magit-commit-parents magit-buffer-revision)) + (magit-insert-section (commit parent) + (let ((line (magit-rev-format "%h %s" parent))) + (string-match "^\\([^ ]+\\) \\(.*\\)" line) + (magit-bind-match-strings (hash msg) line + (insert "Parent: ") + (insert (propertize hash 'font-lock-face 'magit-hash)) + (insert " " msg "\n"))))) + (magit--insert-related-refs + magit-buffer-revision "--merged" "Merged" + (eq magit-revision-insert-related-refs 'all)) + (magit--insert-related-refs + magit-buffer-revision "--contains" "Contained" + (eq magit-revision-insert-related-refs '(all mixed))) + (when-let ((follows (magit-get-current-tag magit-buffer-revision t))) + (let ((tag (car follows)) + (cnt (cadr follows))) + (magit-insert-section (tag tag) + (insert + (format "Follows: %s (%s)\n" + (propertize tag 'font-lock-face 'magit-tag) + (propertize (number-to-string cnt) + 'font-lock-face 'magit-branch-local)))))) + (when-let ((precedes (magit-get-next-tag magit-buffer-revision t))) + (let ((tag (car precedes)) + (cnt (cadr precedes))) + (magit-insert-section (tag tag) + (insert (format "Precedes: %s (%s)\n" + (propertize tag 'font-lock-face 'magit-tag) + (propertize (number-to-string cnt) + 'font-lock-face 'magit-tag)))))) + (insert ?\n)))) + +(defun magit--insert-related-refs (rev arg title remote) + (when-let ((refs (magit-list-related-branches arg rev (and remote "-a")))) + (insert title ":" (make-string (- 10 (length title)) ?\s)) + (dolist (branch refs) + (if (<= (+ (current-column) 1 (length branch)) + (window-width)) + (insert ?\s) + (insert ?\n (make-string 12 ?\s))) + (magit-insert-section (branch branch) + (insert (propertize branch 'font-lock-face + (if (string-prefix-p "remotes/" branch) + 'magit-branch-remote + 'magit-branch-local))))) + (insert ?\n))) + +(defun magit-insert-revision-gravatars (rev beg) + (when (and magit-revision-show-gravatars + (window-system)) + (require 'gravatar) + (pcase-let ((`(,author . ,committer) + (pcase magit-revision-show-gravatars + (`t '("^Author: " . "^Commit: ")) + (`author '("^Author: " . nil)) + (`committer '(nil . "^Commit: ")) + (_ magit-revision-show-gravatars)))) + (--when-let (and author (magit-rev-format "%aE" rev)) + (magit-insert-revision-gravatar beg rev it author)) + (--when-let (and committer (magit-rev-format "%cE" rev)) + (magit-insert-revision-gravatar beg rev it committer))))) + +(defun magit-insert-revision-gravatar (beg rev email regexp) + (save-excursion + (goto-char beg) + (when (re-search-forward regexp nil t) + (when-let ((window (get-buffer-window))) + (let* ((column (length (match-string 0))) + (font-obj (query-font (font-at (point) window))) + (size (* 2 (+ (aref font-obj 4) + (aref font-obj 5)))) + (align-to (+ column + (ceiling (/ size (aref font-obj 7) 1.0)) + 1)) + (gravatar-size (- size 2))) + (ignore-errors ; service may be unreachable + (gravatar-retrieve email 'magit-insert-revision-gravatar-cb + (list rev (point-marker) align-to column)))))))) + +(defun magit-insert-revision-gravatar-cb (image rev marker align-to column) + (unless (eq image 'error) + (when-let ((buffer (marker-buffer marker))) + (with-current-buffer buffer + (save-excursion + (goto-char marker) + ;; The buffer might display another revision by now or + ;; it might have been refreshed, in which case another + ;; process might already have inserted the image. + (when (and (equal rev magit-buffer-revision) + (not (eq (car-safe + (car-safe + (get-text-property (point) 'display))) + 'image))) + (let ((top `((,@image :ascent center :relief 1) + (slice 0.0 0.0 1.0 0.5))) + (bot `((,@image :ascent center :relief 1) + (slice 0.0 0.5 1.0 1.0))) + (align `((space :align-to ,align-to)))) + (when magit-revision-use-gravatar-kludge + (cl-rotatef top bot)) + (let ((inhibit-read-only t)) + (insert (propertize " " 'display top)) + (insert (propertize " " 'display align)) + (forward-line) + (forward-char column) + (insert (propertize " " 'display bot)) + (insert (propertize " " 'display align)))))))))) + +;;; Merge-Preview Mode + +(define-derived-mode magit-merge-preview-mode magit-diff-mode "Magit Merge" + "Mode for previewing a merge." + :group 'magit-diff + (hack-dir-local-variables-non-file-buffer)) + +(put 'magit-merge-preview-mode 'magit-diff-default-arguments + '("--no-ext-diff")) + +(defun magit-merge-preview-setup-buffer (rev) + (magit-setup-buffer #'magit-merge-preview-mode nil + (magit-buffer-revision rev) + (magit-buffer-range (format "%s^..%s" rev rev)))) + +(defun magit-merge-preview-refresh-buffer () + (let* ((branch (magit-get-current-branch)) + (head (or branch (magit-rev-verify "HEAD")))) + (magit-set-header-line-format (format "Preview merge of %s into %s" + magit-buffer-revision + (or branch "HEAD"))) + (magit-insert-section (diffbuf) + (magit--insert-diff + "merge-tree" (magit-git-string "merge-base" head magit-buffer-revision) + head magit-buffer-revision)))) + +(cl-defmethod magit-buffer-value (&context (major-mode magit-merge-preview-mode)) + magit-buffer-revision) + +;;; Diff Sections + +(defvar magit-unstaged-section-map + (let ((map (make-sparse-keymap))) + (define-key map [remap magit-visit-thing] 'magit-diff-unstaged) + (define-key map [remap magit-delete-thing] 'magit-discard) + (define-key map "s" 'magit-stage) + (define-key map "u" 'magit-unstage) + map) + "Keymap for the `unstaged' section.") + +(magit-define-section-jumper magit-jump-to-unstaged "Unstaged changes" unstaged) + +(defun magit-insert-unstaged-changes () + "Insert section showing unstaged changes." + (magit-insert-section (unstaged) + (magit-insert-heading "Unstaged changes:") + (magit--insert-diff + "diff" magit-buffer-diff-args "--no-prefix" + "--" magit-buffer-diff-files))) + +(defvar magit-staged-section-map + (let ((map (make-sparse-keymap))) + (define-key map [remap magit-visit-thing] 'magit-diff-staged) + (define-key map [remap magit-delete-thing] 'magit-discard) + (define-key map [remap magit-revert-no-commit] 'magit-reverse) + (define-key map "s" 'magit-stage) + (define-key map "u" 'magit-unstage) + map) + "Keymap for the `staged' section.") + +(magit-define-section-jumper magit-jump-to-staged "Staged changes" staged) + +(defun magit-insert-staged-changes () + "Insert section showing staged changes." + ;; Avoid listing all files as deleted when visiting a bare repo. + (unless (magit-bare-repo-p) + (magit-insert-section (staged) + (magit-insert-heading "Staged changes:") + (magit--insert-diff + "diff" "--cached" magit-buffer-diff-args "--no-prefix" + "--" magit-buffer-diff-files)))) + +;;; Diff Type + +(defun magit-diff-type (&optional section) + "Return the diff type of SECTION. + +The returned type is one of the symbols `staged', `unstaged', +`committed', or `undefined'. This type serves a similar purpose +as the general type common to all sections (which is stored in +the `type' slot of the corresponding `magit-section' struct) but +takes additional information into account. When the SECTION +isn't related to diffs and the buffer containing it also isn't +a diff-only buffer, then return nil. + +Currently the type can also be one of `tracked' and `untracked' +but these values are not handled explicitly everywhere they +should be and a possible fix could be to just return nil here. + +The section has to be a `diff' or `hunk' section, or a section +whose children are of type `diff'. If optional SECTION is nil, +return the diff type for the current section. In buffers whose +major mode is `magit-diff-mode' SECTION is ignored and the type +is determined using other means. In `magit-revision-mode' +buffers the type is always `committed'. + +Do not confuse this with `magit-diff-scope' (which see)." + (--when-let (or section (magit-current-section)) + (cond ((derived-mode-p 'magit-revision-mode 'magit-stash-mode) 'committed) + ((derived-mode-p 'magit-diff-mode) + (let ((range magit-buffer-range) + (const magit-buffer-typearg)) + (cond ((equal const "--no-index") 'undefined) + ((or (not range) + (magit-rev-eq range "HEAD")) + (if (equal const "--cached") + 'staged + 'unstaged)) + ((equal const "--cached") + (if (magit-rev-head-p range) + 'staged + 'undefined)) ; i.e. committed and staged + (t 'committed)))) + ((derived-mode-p 'magit-status-mode) + (let ((stype (oref it type))) + (if (memq stype '(staged unstaged tracked untracked)) + stype + (pcase stype + ((or `file `module) + (let* ((parent (oref it parent)) + (type (oref parent type))) + (if (memq type '(file module)) + (magit-diff-type parent) + type))) + (`hunk (-> it + (oref parent) + (oref parent) + (oref type))))))) + ((derived-mode-p 'magit-log-mode) + (if (or (and (magit-section-match 'commit section) + (oref section children)) + (magit-section-match [* file commit] section)) + 'committed + 'undefined)) + (t 'undefined)))) + +(cl-defun magit-diff-scope (&optional (section nil ssection) strict) + "Return the diff scope of SECTION or the selected section(s). + +A diff's \"scope\" describes what part of a diff is selected, it is +a symbol, one of `region', `hunk', `hunks', `file', `files', or +`list'. Do not confuse this with the diff \"type\", as returned by +`magit-diff-type'. + +If optional SECTION is non-nil, then return the scope of that, +ignoring the sections selected by the region. Otherwise return +the scope of the current section, or if the region is active and +selects a valid group of diff related sections, the type of these +sections, i.e. `hunks' or `files'. If SECTION, or if that is nil +the current section, is a `hunk' section; and the region region +starts and ends inside the body of a that section, then the type +is `region'. If the region is empty after a mouse click, then +`hunk' is returned instead of `region'. + +If optional STRICT is non-nil, then return nil if the diff type of +the section at point is `untracked' or the section at point is not +actually a `diff' but a `diffstat' section." + (let ((siblings (and (not ssection) (magit-region-sections nil t)))) + (setq section (or section (car siblings) (magit-current-section))) + (when (and section + (or (not strict) + (and (not (eq (magit-diff-type section) 'untracked)) + (not (eq (--when-let (oref section parent) + (oref it type)) + 'diffstat))))) + (pcase (list (oref section type) + (and siblings t) + (magit-diff-use-hunk-region-p) + ssection) + (`(hunk nil t ,_) + (if (magit-section-internal-region-p section) 'region 'hunk)) + (`(hunk t t nil) 'hunks) + (`(hunk ,_ ,_ ,_) 'hunk) + (`(file t t nil) 'files) + (`(file ,_ ,_ ,_) 'file) + (`(module t t nil) 'files) + (`(module ,_ ,_ ,_) 'file) + (`(,(or `staged `unstaged `untracked) + nil ,_ ,_) 'list))))) + +(defun magit-diff-use-hunk-region-p () + (and (region-active-p) + ;; TODO implement this from first principals + ;; currently it's trial-and-error + (not (and (or (eq this-command 'mouse-drag-region) + (eq last-command 'mouse-drag-region) + ;; When another window was previously + ;; selected then the last-command is + ;; some byte-code function. + (byte-code-function-p last-command)) + (eq (region-end) (region-beginning)))))) + +;;; Diff Highlight + +(defun magit-diff-unhighlight (section selection) + "Remove the highlighting of the diff-related SECTION." + (when (magit-hunk-section-p section) + (magit-diff-paint-hunk section selection nil) + t)) + +(defun magit-diff-highlight (section selection) + "Highlight the diff-related SECTION. +If SECTION is not a diff-related section, then do nothing and +return nil. If SELECTION is non-nil, then it is a list of sections +selected by the region, including SECTION. All of these sections +are highlighted." + (if (and (magit-section-match 'commit section) + (oref section children)) + (progn (if selection + (dolist (section selection) + (magit-diff-highlight-list section selection)) + (magit-diff-highlight-list section)) + t) + (when-let ((scope (magit-diff-scope section t))) + (cond ((eq scope 'region) + (magit-diff-paint-hunk section selection t)) + (selection + (dolist (section selection) + (magit-diff-highlight-recursive section selection))) + (t + (magit-diff-highlight-recursive section))) + t))) + +(defun magit-diff-highlight-recursive (section &optional selection) + (pcase (magit-diff-scope section) + (`list (magit-diff-highlight-list section selection)) + (`file (magit-diff-highlight-file section selection)) + (`hunk (magit-diff-highlight-heading section selection) + (magit-diff-paint-hunk section selection t)) + (_ (magit-section-highlight section nil)))) + +(defun magit-diff-highlight-list (section &optional selection) + (let ((beg (oref section start)) + (cnt (oref section content)) + (end (oref section end))) + (when (or (eq this-command 'mouse-drag-region) + (not selection)) + (unless (and (region-active-p) + (<= (region-beginning) beg)) + (magit-section-make-overlay beg cnt 'magit-section-highlight)) + (unless (oref section hidden) + (dolist (child (oref section children)) + (when (or (eq this-command 'mouse-drag-region) + (not (and (region-active-p) + (<= (region-beginning) + (oref child start))))) + (magit-diff-highlight-recursive child selection))))) + (when magit-diff-highlight-hunk-body + (magit-section-make-overlay (1- end) end 'magit-section-highlight)))) + +(defun magit-diff-highlight-file (section &optional selection) + (magit-diff-highlight-heading section selection) + (unless (oref section hidden) + (dolist (child (oref section children)) + (magit-diff-highlight-recursive child selection)))) + +(defun magit-diff-highlight-heading (section &optional selection) + (magit-section-make-overlay + (oref section start) + (or (oref section content) + (oref section end)) + (pcase (list (oref section type) + (and (member section selection) + (not (eq this-command 'mouse-drag-region)))) + (`(file t) 'magit-diff-file-heading-selection) + (`(file nil) 'magit-diff-file-heading-highlight) + (`(module t) 'magit-diff-file-heading-selection) + (`(module nil) 'magit-diff-file-heading-highlight) + (`(hunk t) 'magit-diff-hunk-heading-selection) + (`(hunk nil) 'magit-diff-hunk-heading-highlight)))) + +;;; Hunk Paint + +(cl-defun magit-diff-paint-hunk + (section &optional selection + (highlight (magit-section-selected-p section selection))) + (let (paint) + (unless magit-diff-highlight-hunk-body + (setq highlight nil)) + (cond (highlight + (unless (oref section hidden) + (add-to-list 'magit-section-highlighted-sections section) + (cond ((memq section magit-section-unhighlight-sections) + (setq magit-section-unhighlight-sections + (delq section magit-section-unhighlight-sections))) + (magit-diff-highlight-hunk-body + (setq paint t))))) + (t + (cond ((and (oref section hidden) + (memq section magit-section-unhighlight-sections)) + (add-to-list 'magit-section-highlighted-sections section) + (setq magit-section-unhighlight-sections + (delq section magit-section-unhighlight-sections))) + (t + (setq paint t))))) + (when paint + (save-excursion + (goto-char (oref section start)) + (let ((end (oref section end)) + (merging (looking-at "@@@")) + (diff-type (magit-diff-type)) + (stage nil) + (tab-width (magit-diff-tab-width + (magit-section-parent-value section)))) + (forward-line) + (while (< (point) end) + (when (and magit-diff-hide-trailing-cr-characters + (char-equal ?\r (char-before (line-end-position)))) + (put-text-property (1- (line-end-position)) (line-end-position) + 'invisible t)) + (put-text-property + (point) (1+ (line-end-position)) 'font-lock-face + (cond + ((looking-at "^\\+\\+?\\([<=|>]\\)\\{7\\}") + (setq stage (pcase (list (match-string 1) highlight) + (`("<" nil) 'magit-diff-our) + (`("<" t) 'magit-diff-our-highlight) + (`("|" nil) 'magit-diff-base) + (`("|" t) 'magit-diff-base-highlight) + (`("=" nil) 'magit-diff-their) + (`("=" t) 'magit-diff-their-highlight) + (`(">" nil) nil))) + 'magit-diff-conflict-heading) + ((looking-at (if merging "^\\(\\+\\| \\+\\)" "^\\+")) + (magit-diff-paint-tab merging tab-width) + (magit-diff-paint-whitespace merging 'added diff-type) + (or stage + (if highlight 'magit-diff-added-highlight 'magit-diff-added))) + ((looking-at (if merging "^\\(-\\| -\\)" "^-")) + (magit-diff-paint-tab merging tab-width) + (magit-diff-paint-whitespace merging 'removed diff-type) + (if highlight 'magit-diff-removed-highlight 'magit-diff-removed)) + (t + (magit-diff-paint-tab merging tab-width) + (magit-diff-paint-whitespace merging 'context diff-type) + (if highlight 'magit-diff-context-highlight 'magit-diff-context)))) + (forward-line)))))) + (magit-diff-update-hunk-refinement section)) + +(defvar magit-diff--tab-width-cache nil) + +(defun magit-diff-tab-width (file) + (setq file (expand-file-name file)) + (cl-flet ((cache (value) + (let ((elt (assoc file magit-diff--tab-width-cache))) + (if elt + (setcdr elt value) + (setq magit-diff--tab-width-cache + (cons (cons file value) + magit-diff--tab-width-cache)))) + value)) + (cond + ((not magit-diff-adjust-tab-width) + tab-width) + ((--when-let (find-buffer-visiting file) + (cache (buffer-local-value 'tab-width it)))) + ((--when-let (assoc file magit-diff--tab-width-cache) + (or (cdr it) + tab-width))) + ((or (eq magit-diff-adjust-tab-width 'always) + (and (numberp magit-diff-adjust-tab-width) + (>= magit-diff-adjust-tab-width + (nth 7 (file-attributes file))))) + (cache (buffer-local-value 'tab-width (find-file-noselect file)))) + (t + (cache nil) + tab-width)))) + +(defun magit-diff-paint-tab (merging width) + (save-excursion + (forward-char (if merging 2 1)) + (while (= (char-after) ?\t) + (put-text-property (point) (1+ (point)) + 'display (list (list 'space :width width))) + (forward-char)))) + +(defun magit-diff-paint-whitespace (merging line-type diff-type) + (when (and magit-diff-paint-whitespace + (or (not (memq magit-diff-paint-whitespace '(uncommitted status))) + (memq diff-type '(staged unstaged))) + (cl-case line-type + (added t) + (removed (memq magit-diff-paint-whitespace-lines '(all both))) + (context (memq magit-diff-paint-whitespace-lines '(all))))) + (let ((prefix (if merging "^[-\\+\s]\\{2\\}" "^[-\\+\s]")) + (indent + (if (local-variable-p 'magit-diff-highlight-indentation) + magit-diff-highlight-indentation + (setq-local + magit-diff-highlight-indentation + (cdr (--first (string-match-p (car it) default-directory) + (nreverse + (default-value + 'magit-diff-highlight-indentation)))))))) + (when (and magit-diff-highlight-trailing + (looking-at (concat prefix ".*?\\([ \t]+\\)$"))) + (let ((ov (make-overlay (match-beginning 1) (match-end 1) nil t))) + (overlay-put ov 'font-lock-face 'magit-diff-whitespace-warning) + (overlay-put ov 'priority 2) + (overlay-put ov 'evaporate t))) + (when (or (and (eq indent 'tabs) + (looking-at (concat prefix "\\( *\t[ \t]*\\)"))) + (and (integerp indent) + (looking-at (format "%s\\([ \t]* \\{%s,\\}[ \t]*\\)" + prefix indent)))) + (let ((ov (make-overlay (match-beginning 1) (match-end 1) nil t))) + (overlay-put ov 'font-lock-face 'magit-diff-whitespace-warning) + (overlay-put ov 'priority 2) + (overlay-put ov 'evaporate t)))))) + +(defun magit-diff-update-hunk-refinement (&optional section) + (if section + (unless (oref section hidden) + (pcase (list magit-diff-refine-hunk + (oref section refined) + (eq section (magit-current-section))) + ((or `(all nil ,_) `(t nil t)) + (oset section refined t) + (save-excursion + (goto-char (oref section start)) + ;; `diff-refine-hunk' does not handle combined diffs. + (unless (looking-at "@@@") + (let ((smerge-refine-ignore-whitespace + magit-diff-refine-ignore-whitespace) + ;; Avoid fsyncing many small temp files + (write-region-inhibit-fsync t)) + (diff-refine-hunk))))) + ((or `(nil t ,_) `(t t nil)) + (oset section refined nil) + (remove-overlays (oref section start) + (oref section end) + 'diff-mode 'fine)))) + (cl-labels ((recurse (section) + (if (magit-section-match 'hunk section) + (magit-diff-update-hunk-refinement section) + (dolist (child (oref section children)) + (recurse child))))) + (recurse magit-root-section)))) + + +;;; Hunk Region + +(defun magit-diff-hunk-region-beginning () + (save-excursion (goto-char (region-beginning)) + (line-beginning-position))) + +(defun magit-diff-hunk-region-end () + (save-excursion (goto-char (region-end)) + (line-end-position))) + +(defun magit-diff-update-hunk-region (section) + "Highlight the hunk-internal region if any." + (when (eq (magit-diff-scope section t) 'region) + (magit-diff--make-hunk-overlay + (oref section start) + (1- (oref section content)) + 'font-lock-face 'magit-diff-lines-heading + 'display (magit-diff-hunk-region-header section) + 'after-string (magit-diff--hunk-after-string 'magit-diff-lines-heading)) + (run-hook-with-args 'magit-diff-highlight-hunk-region-functions section) + t)) + +(defun magit-diff-highlight-hunk-region-dim-outside (section) + "Dim the parts of the hunk that are outside the hunk-internal region. +This is done by using the same foreground and background color +for added and removed lines as for context lines." + (let ((face (if magit-diff-highlight-hunk-body + 'magit-diff-context-highlight + 'magit-diff-context))) + (when magit-diff-unmarked-lines-keep-foreground + (setq face (list :background (face-attribute face :background)))) + (magit-diff--make-hunk-overlay (oref section content) + (magit-diff-hunk-region-beginning) + 'font-lock-face face + 'priority 2) + (magit-diff--make-hunk-overlay (1+ (magit-diff-hunk-region-end)) + (oref section end) + 'font-lock-face face + 'priority 2))) + +(defun magit-diff-highlight-hunk-region-using-face (_section) + "Highlight the hunk-internal region by making it bold. +Or rather highlight using the face `magit-diff-hunk-region', though +changing only the `:weight' and/or `:slant' is recommended for that +face." + (magit-diff--make-hunk-overlay (magit-diff-hunk-region-beginning) + (1+ (magit-diff-hunk-region-end)) + 'font-lock-face 'magit-diff-hunk-region)) + +(defun magit-diff-highlight-hunk-region-using-overlays (section) + "Emphasize the hunk-internal region using delimiting horizontal lines. +This is implemented as single-pixel newlines places inside overlays." + (if (window-system) + (let ((beg (magit-diff-hunk-region-beginning)) + (end (magit-diff-hunk-region-end)) + (str (propertize + (concat (propertize "\s" 'display '(space :height (1))) + (propertize "\n" 'line-height t)) + 'font-lock-face 'magit-diff-lines-boundary))) + (magit-diff--make-hunk-overlay beg (1+ beg) 'before-string str) + (magit-diff--make-hunk-overlay end (1+ end) 'after-string str)) + (magit-diff-highlight-hunk-region-using-face section))) + +(defun magit-diff-highlight-hunk-region-using-underline (section) + "Emphasize the hunk-internal region using delimiting horizontal lines. +This is implemented by overlining and underlining the first and +last (visual) lines of the region." + (if (window-system) + (let* ((beg (magit-diff-hunk-region-beginning)) + (end (magit-diff-hunk-region-end)) + (beg-eol (save-excursion (goto-char beg) + (end-of-visual-line) + (point))) + (end-bol (save-excursion (goto-char end) + (beginning-of-visual-line) + (point))) + (color (face-background 'magit-diff-lines-boundary nil t))) + (cl-flet ((ln (b e &rest face) + (magit-diff--make-hunk-overlay + b e 'font-lock-face face 'after-string + (magit-diff--hunk-after-string face)))) + (if (= beg end-bol) + (ln beg beg-eol :overline color :underline color) + (ln beg beg-eol :overline color) + (ln end-bol end :underline color)))) + (magit-diff-highlight-hunk-region-using-face section))) + +(defun magit-diff--make-hunk-overlay (start end &rest args) + (let ((ov (make-overlay start end nil t))) + (overlay-put ov 'evaporate t) + (while args (overlay-put ov (pop args) (pop args))) + (push ov magit-region-overlays) + ov)) + +(defun magit-diff--hunk-after-string (face) + (propertize "\s" + 'font-lock-face face + 'display (list 'space :align-to + `(+ (0 . right) + ,(min (window-hscroll) + (- (line-end-position) + (line-beginning-position))))) + ;; This prevents the cursor from being rendered at the + ;; edge of the window. + 'cursor t)) + +;;; Hunk Utilities + +(defun magit-diff-inside-hunk-body-p () + "Return non-nil if point is inside the body of a hunk." + (and (magit-section-match 'hunk) + (when-let ((content (oref (magit-current-section) content))) + (> (point) content)))) + +;;; Diff Extract + +(defun magit-diff-file-header (section) + (when (magit-hunk-section-p section) + (setq section (oref section parent))) + (when (magit-file-section-p section) + (oref section header))) + +(defun magit-diff-hunk-region-header (section) + (let ((patch (magit-diff-hunk-region-patch section))) + (string-match "\n" patch) + (substring patch 0 (1- (match-end 0))))) + +(defun magit-diff-hunk-region-patch (section &optional args) + (let ((op (if (member "--reverse" args) "+" "-")) + (sbeg (oref section start)) + (rbeg (magit-diff-hunk-region-beginning)) + (rend (region-end)) + (send (oref section end)) + (patch nil)) + (save-excursion + (goto-char sbeg) + (while (< (point) send) + (looking-at "\\(.\\)\\([^\n]*\n\\)") + (cond ((or (string-match-p "[@ ]" (match-string-no-properties 1)) + (and (>= (point) rbeg) + (<= (point) rend))) + (push (match-string-no-properties 0) patch)) + ((equal op (match-string-no-properties 1)) + (push (concat " " (match-string-no-properties 2)) patch))) + (forward-line))) + (let ((buffer-list-update-hook nil)) ; #3759 + (with-temp-buffer + (insert (mapconcat #'identity (reverse patch) "")) + (diff-fixup-modifs (point-min) (point-max)) + (setq patch (buffer-string)))) + patch)) + +;;; _ +(provide 'magit-diff) +;;; magit-diff.el ends here diff --git a/elpa/magit-20191122.2040/magit-diff.elc b/elpa/magit-20191122.2040/magit-diff.elc new file mode 100644 index 0000000000000000000000000000000000000000..04af2844d73ea577fbc495735001cee139df91fa GIT binary patch literal 156338 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 +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; This library provides basic support for Ediff. + +;;; Code: + +(require 'magit) + +(require 'ediff) +(require 'smerge-mode) + +(defvar smerge-ediff-buf) +(defvar smerge-ediff-windows) + +;;; Options + +(defgroup magit-ediff nil + "Ediff support for Magit." + :link '(info-link "(magit)Ediffing") + :group 'magit-extensions) + +(defcustom magit-ediff-quit-hook + '(magit-ediff-cleanup-auxiliary-buffers + magit-ediff-restore-previous-winconf) + "Hooks to run after finishing Ediff, when that was invoked using Magit. +The hooks are run in the Ediff control buffer. This is similar +to `ediff-quit-hook' but takes the needs of Magit into account. +The `ediff-quit-hook' is ignored by Ediff sessions which were +invoked using Magit." + :package-version '(magit . "2.2.0") + :group 'magit-ediff + :type 'hook + :get 'magit-hook-custom-get + :options '(magit-ediff-cleanup-auxiliary-buffers + magit-ediff-restore-previous-winconf)) + +(defcustom magit-ediff-dwim-show-on-hunks nil + "Whether `magit-ediff-dwim' runs show variants on hunks. +If non-nil, `magit-ediff-show-staged' or +`magit-ediff-show-unstaged' are called based on what section the +hunk is in. Otherwise, `magit-ediff-dwim' runs +`magit-ediff-stage' when point is on an uncommitted hunk." + :package-version '(magit . "2.2.0") + :group 'magit-ediff + :type 'boolean) + +(defcustom magit-ediff-show-stash-with-index t + "Whether `magit-ediff-show-stash' shows the state of the index. + +If non-nil, use a third Ediff buffer to distinguish which changes +in the stash were staged. In cases where the stash contains no +staged changes, fall back to a two-buffer Ediff. + +More specifically, a stash is a merge commit, stash@{N}, with +potentially three parents. + +* stash@{N}^1 represents the `HEAD' commit at the time the stash + was created. + +* stash@{N}^2 records any changes that were staged when the stash + was made. + +* stash@{N}^3, if it exists, contains files that were untracked + when stashing. + +If this option is non-nil, `magit-ediff-show-stash' will run +Ediff on a file using three buffers: one for stash@{N}, another +for stash@{N}^1, and a third for stash@{N}^2. + +Otherwise, Ediff uses two buffers, comparing +stash@{N}^1..stash@{N}. Along with any unstaged changes, changes +in the index commit, stash@{N}^2, will be shown in this +comparison unless they conflicted with changes in the working +tree at the time of stashing." + :package-version '(magit . "2.6.0") + :group 'magit-ediff + :type 'boolean) + +;;; Commands + +(defvar magit-ediff-previous-winconf nil) + +;;;###autoload (autoload 'magit-ediff "magit-ediff" nil) +(define-transient-command magit-ediff () + "Show differences using the Ediff package." + :info-manual "(ediff)" + ["Ediff" + [("E" "Dwim" magit-ediff-dwim) + ("s" "Stage" magit-ediff-stage) + ("m" "Resolve" magit-ediff-resolve)] + [("u" "Show unstaged" magit-ediff-show-unstaged) + ("i" "Show staged" magit-ediff-show-staged) + ("w" "Show worktree" magit-ediff-show-working-tree)] + [("c" "Show commit" magit-ediff-show-commit) + ("r" "Show range" magit-ediff-compare) + ("z" "Show stash" magit-ediff-show-stash)]]) + +;;;###autoload +(defun magit-ediff-resolve (file) + "Resolve outstanding conflicts in FILE using Ediff. +FILE has to be relative to the top directory of the repository. + +In the rare event that you want to manually resolve all +conflicts, including those already resolved by Git, use +`ediff-merge-revisions-with-ancestor'." + (interactive + (let ((current (magit-current-file)) + (unmerged (magit-unmerged-files))) + (unless unmerged + (user-error "There are no unresolved conflicts")) + (list (magit-completing-read "Resolve file" unmerged nil t nil nil + (car (member current unmerged)))))) + (magit-with-toplevel + (with-current-buffer (find-file-noselect file) + (smerge-ediff) + (setq-local + ediff-quit-hook + (lambda () + (let ((bufC ediff-buffer-C) + (bufS smerge-ediff-buf)) + (with-current-buffer bufS + (when (yes-or-no-p (format "Conflict resolution finished; save %s? " + buffer-file-name)) + (erase-buffer) + (insert-buffer-substring bufC) + (save-buffer)))) + (when (buffer-live-p ediff-buffer-A) (kill-buffer ediff-buffer-A)) + (when (buffer-live-p ediff-buffer-B) (kill-buffer ediff-buffer-B)) + (when (buffer-live-p ediff-buffer-C) (kill-buffer ediff-buffer-C)) + (when (buffer-live-p ediff-ancestor-buffer) + (kill-buffer ediff-ancestor-buffer)) + (let ((magit-ediff-previous-winconf smerge-ediff-windows)) + (run-hooks 'magit-ediff-quit-hook))))))) + +;;;###autoload +(defun magit-ediff-stage (file) + "Stage and unstage changes to FILE using Ediff. +FILE has to be relative to the top directory of the repository." + (interactive + (let ((files (magit-tracked-files))) + (list (magit-completing-read "Selectively stage file" files nil t nil nil + (car (member (magit-current-file) files)))))) + (magit-with-toplevel + (let* ((conf (current-window-configuration)) + (bufA (magit-get-revision-buffer "HEAD" file)) + (bufB (magit-get-revision-buffer "{index}" file)) + (bufBrw (and bufB (with-current-buffer bufB (not buffer-read-only)))) + (bufC (get-file-buffer file)) + (fileBufC (or bufC (find-file-noselect file))) + (coding-system-for-read + (with-current-buffer fileBufC buffer-file-coding-system))) + (ediff-buffers3 + (or bufA (magit-find-file-noselect "HEAD" file)) + (with-current-buffer (magit-find-file-index-noselect file t) + (setq buffer-read-only nil) + (current-buffer)) + fileBufC + `((lambda () + (setq-local + ediff-quit-hook + (lambda () + (and (buffer-live-p ediff-buffer-B) + (buffer-modified-p ediff-buffer-B) + (with-current-buffer ediff-buffer-B + (magit-update-index))) + (and (buffer-live-p ediff-buffer-C) + (buffer-modified-p ediff-buffer-C) + (with-current-buffer ediff-buffer-C + (when (y-or-n-p + (format "Save file %s? " buffer-file-name)) + (save-buffer)))) + ,@(unless bufA '((ediff-kill-buffer-carefully ediff-buffer-A))) + ,@(if bufB + (unless bufBrw '((with-current-buffer ediff-buffer-B + (setq buffer-read-only t)))) + '((ediff-kill-buffer-carefully ediff-buffer-B))) + ,@(unless bufC '((ediff-kill-buffer-carefully ediff-buffer-C))) + (let ((magit-ediff-previous-winconf ,conf)) + (run-hooks 'magit-ediff-quit-hook)))))) + 'ediff-buffers3)))) + +;;;###autoload +(defun magit-ediff-compare (revA revB fileA fileB) + "Compare REVA:FILEA with REVB:FILEB using Ediff. + +FILEA and FILEB have to be relative to the top directory of the +repository. If REVA or REVB is nil, then this stands for the +working tree state. + +If the region is active, use the revisions on the first and last +line of the region. With a prefix argument, instead of diffing +the revisions, choose a revision to view changes along, starting +at the common ancestor of both revisions (i.e., use a \"...\" +range)." + (interactive + (pcase-let ((`(,revA ,revB) (magit-ediff-compare--read-revisions + nil current-prefix-arg))) + (nconc (list revA revB) + (magit-ediff-read-files revA revB)))) + (magit-with-toplevel + (let ((conf (current-window-configuration)) + (bufA (if revA + (magit-get-revision-buffer revA fileA) + (get-file-buffer fileA))) + (bufB (if revB + (magit-get-revision-buffer revB fileB) + (get-file-buffer fileB)))) + (ediff-buffers + (or bufA (if revA + (magit-find-file-noselect revA fileA) + (find-file-noselect fileA))) + (or bufB (if revB + (magit-find-file-noselect revB fileB) + (find-file-noselect fileB))) + `((lambda () + (setq-local + ediff-quit-hook + (lambda () + ,@(unless bufA '((ediff-kill-buffer-carefully ediff-buffer-A))) + ,@(unless bufB '((ediff-kill-buffer-carefully ediff-buffer-B))) + (let ((magit-ediff-previous-winconf ,conf)) + (run-hooks 'magit-ediff-quit-hook)))))) + 'ediff-revision)))) + +(defun magit-ediff-compare--read-revisions (&optional arg mbase) + (let ((input (or arg (magit-diff-read-range-or-commit + "Compare range or commit" + nil mbase)))) + (--if-let (magit-split-range input) + (-cons-to-list it) + (list input nil)))) + +(defun magit-ediff-read-files (revA revB &optional fileB) + "Read file in REVB, return it and the corresponding file in REVA. +When FILEB is non-nil, use this as REVB's file instead of +prompting for it." + (unless fileB + (setq fileB (magit-read-file-choice + (format "File to compare between %s and %s" + revA (or revB "the working tree")) + (magit-changed-files revA revB) + (format "No changed files between %s and %s" + revA (or revB "the working tree"))))) + (list (or (car (member fileB (magit-revision-files revA))) + (cdr (assoc fileB (magit-renamed-files revB revA))) + (magit-read-file-choice + (format "File in %s to compare with %s in %s" + revA fileB (or revB "the working tree")) + (magit-changed-files revB revA) + (format "No files have changed between %s and %s" + revA revB))) + fileB)) + +;;;###autoload +(defun magit-ediff-dwim () + "Compare, stage, or resolve using Ediff. +This command tries to guess what file, and what commit or range +the user wants to compare, stage, or resolve using Ediff. It +might only be able to guess either the file, or range or commit, +in which case the user is asked about the other. It might not +always guess right, in which case the appropriate `magit-ediff-*' +command has to be used explicitly. If it cannot read the user's +mind at all, then it asks the user for a command to run." + (interactive) + (magit-section-case + (hunk (save-excursion + (goto-char (oref (oref it parent) start)) + (magit-ediff-dwim))) + (t + (let ((range (magit-diff--dwim)) + (file (magit-current-file)) + command revA revB) + (pcase range + ((and (guard (not magit-ediff-dwim-show-on-hunks)) + (or `unstaged `staged)) + (setq command (if (magit-anything-unmerged-p) + #'magit-ediff-resolve + #'magit-ediff-stage))) + (`unstaged (setq command #'magit-ediff-show-unstaged)) + (`staged (setq command #'magit-ediff-show-staged)) + (`(commit . ,value) + (setq command #'magit-ediff-show-commit) + (setq revB value)) + (`(stash . ,value) + (setq command #'magit-ediff-show-stash) + (setq revB value)) + ((pred stringp) + (pcase-let ((`(,a ,b) (magit-ediff-compare--read-revisions range))) + (setq command #'magit-ediff-compare) + (setq revA a) + (setq revB b))) + (_ + (when (derived-mode-p 'magit-diff-mode) + (pcase (magit-diff-type) + (`committed (pcase-let ((`(,a ,b) + (magit-ediff-compare--read-revisions + magit-buffer-range))) + (setq revA a) + (setq revB b))) + ((guard (not magit-ediff-dwim-show-on-hunks)) + (setq command #'magit-ediff-stage)) + (`unstaged (setq command #'magit-ediff-show-unstaged)) + (`staged (setq command #'magit-ediff-show-staged)) + (`undefined (setq command nil)) + (_ (setq command nil)))))) + (cond ((not command) + (call-interactively + (magit-read-char-case + "Failed to read your mind; do you want to " t + (?c "[c]ommit" 'magit-ediff-show-commit) + (?r "[r]ange" 'magit-ediff-compare) + (?s "[s]tage" 'magit-ediff-stage) + (?v "resol[v]e" 'magit-ediff-resolve)))) + ((eq command 'magit-ediff-compare) + (apply 'magit-ediff-compare revA revB + (magit-ediff-read-files revA revB file))) + ((eq command 'magit-ediff-show-commit) + (magit-ediff-show-commit revB)) + ((eq command 'magit-ediff-show-stash) + (magit-ediff-show-stash revB)) + (file + (funcall command file)) + (t + (call-interactively command))))))) + +;;;###autoload +(defun magit-ediff-show-staged (file) + "Show staged changes using Ediff. + +This only allows looking at the changes; to stage, unstage, +and discard changes using Ediff, use `magit-ediff-stage'. + +FILE must be relative to the top directory of the repository." + (interactive + (list (magit-read-file-choice "Show staged changes for file" + (magit-staged-files) + "No staged files"))) + (let ((conf (current-window-configuration)) + (bufA (magit-get-revision-buffer "HEAD" file)) + (bufB (get-buffer (concat file ".~{index}~")))) + (ediff-buffers + (or bufA (magit-find-file-noselect "HEAD" file)) + (or bufB (magit-find-file-index-noselect file t)) + `((lambda () + (setq-local + ediff-quit-hook + (lambda () + ,@(unless bufA '((ediff-kill-buffer-carefully ediff-buffer-A))) + ,@(unless bufB '((ediff-kill-buffer-carefully ediff-buffer-B))) + (let ((magit-ediff-previous-winconf ,conf)) + (run-hooks 'magit-ediff-quit-hook)))))) + 'ediff-buffers))) + +;;;###autoload +(defun magit-ediff-show-unstaged (file) + "Show unstaged changes using Ediff. + +This only allows looking at the changes; to stage, unstage, +and discard changes using Ediff, use `magit-ediff-stage'. + +FILE must be relative to the top directory of the repository." + (interactive + (list (magit-read-file-choice "Show unstaged changes for file" + (magit-unstaged-files) + "No unstaged files"))) + (magit-with-toplevel + (let ((conf (current-window-configuration)) + (bufA (get-buffer (concat file ".~{index}~"))) + (bufB (get-file-buffer file))) + (ediff-buffers + (or bufA (magit-find-file-index-noselect file t)) + (or bufB (find-file-noselect file)) + `((lambda () + (setq-local + ediff-quit-hook + (lambda () + ,@(unless bufA '((ediff-kill-buffer-carefully ediff-buffer-A))) + ,@(unless bufB '((ediff-kill-buffer-carefully ediff-buffer-B))) + (let ((magit-ediff-previous-winconf ,conf)) + (run-hooks 'magit-ediff-quit-hook)))))) + 'ediff-buffers)))) + +;;;###autoload +(defun magit-ediff-show-working-tree (file) + "Show changes between `HEAD' and working tree using Ediff. +FILE must be relative to the top directory of the repository." + (interactive + (list (magit-read-file-choice "Show changes in file" + (magit-changed-files "HEAD") + "No changed files"))) + (magit-with-toplevel + (let ((conf (current-window-configuration)) + (bufA (magit-get-revision-buffer "HEAD" file)) + (bufB (get-file-buffer file))) + (ediff-buffers + (or bufA (magit-find-file-noselect "HEAD" file)) + (or bufB (find-file-noselect file)) + `((lambda () + (setq-local + ediff-quit-hook + (lambda () + ,@(unless bufA '((ediff-kill-buffer-carefully ediff-buffer-A))) + ,@(unless bufB '((ediff-kill-buffer-carefully ediff-buffer-B))) + (let ((magit-ediff-previous-winconf ,conf)) + (run-hooks 'magit-ediff-quit-hook)))))) + 'ediff-buffers)))) + +;;;###autoload +(defun magit-ediff-show-commit (commit) + "Show changes introduced by COMMIT using Ediff." + (interactive (list (magit-read-branch-or-commit "Revision"))) + (let ((revA (concat commit "^")) + (revB commit)) + (apply #'magit-ediff-compare + revA revB + (magit-ediff-read-files revA revB (magit-current-file))))) + +;;;###autoload +(defun magit-ediff-show-stash (stash) + "Show changes introduced by STASH using Ediff. +`magit-ediff-show-stash-with-index' controls whether a +three-buffer Ediff is used in order to distinguish changes in the +stash that were staged." + (interactive (list (magit-read-stash "Stash"))) + (pcase-let* ((revA (concat stash "^1")) + (revB (concat stash "^2")) + (revC stash) + (`(,fileA ,fileC) (magit-ediff-read-files revA revC)) + (fileB fileC)) + (if (and magit-ediff-show-stash-with-index + (member fileA (magit-changed-files revB revA))) + (let ((conf (current-window-configuration)) + (bufA (magit-get-revision-buffer revA fileA)) + (bufB (magit-get-revision-buffer revB fileB)) + (bufC (magit-get-revision-buffer revC fileC))) + (ediff-buffers3 + (or bufA (magit-find-file-noselect revA fileA)) + (or bufB (magit-find-file-noselect revB fileB)) + (or bufC (magit-find-file-noselect revC fileC)) + `((lambda () + (setq-local + ediff-quit-hook + (lambda () + ,@(unless bufA + '((ediff-kill-buffer-carefully ediff-buffer-A))) + ,@(unless bufB + '((ediff-kill-buffer-carefully ediff-buffer-B))) + ,@(unless bufC + '((ediff-kill-buffer-carefully ediff-buffer-C))) + (let ((magit-ediff-previous-winconf ,conf)) + (run-hooks 'magit-ediff-quit-hook)))))) + 'ediff-buffers3)) + (magit-ediff-compare revA revC fileA fileC)))) + +(defun magit-ediff-cleanup-auxiliary-buffers () + (let* ((ctl-buf ediff-control-buffer) + (ctl-win (ediff-get-visible-buffer-window ctl-buf)) + (ctl-frm ediff-control-frame) + (main-frame (cond ((window-live-p ediff-window-A) + (window-frame ediff-window-A)) + ((window-live-p ediff-window-B) + (window-frame ediff-window-B))))) + (ediff-kill-buffer-carefully ediff-diff-buffer) + (ediff-kill-buffer-carefully ediff-custom-diff-buffer) + (ediff-kill-buffer-carefully ediff-fine-diff-buffer) + (ediff-kill-buffer-carefully ediff-tmp-buffer) + (ediff-kill-buffer-carefully ediff-error-buffer) + (ediff-kill-buffer-carefully ediff-msg-buffer) + (ediff-kill-buffer-carefully ediff-debug-buffer) + (when (boundp 'ediff-patch-diagnostics) + (ediff-kill-buffer-carefully ediff-patch-diagnostics)) + (cond ((and (ediff-window-display-p) + (frame-live-p ctl-frm)) + (delete-frame ctl-frm)) + ((window-live-p ctl-win) + (delete-window ctl-win))) + (ediff-kill-buffer-carefully ctl-buf) + (when (frame-live-p main-frame) + (select-frame main-frame)))) + +(defun magit-ediff-restore-previous-winconf () + (set-window-configuration magit-ediff-previous-winconf)) + +;;; _ +(provide 'magit-ediff) +;;; magit-ediff.el ends here diff --git a/elpa/magit-20191122.2040/magit-ediff.elc b/elpa/magit-20191122.2040/magit-ediff.elc new file mode 100644 index 0000000000000000000000000000000000000000..11d7108f2b070a40e0fd9193aba15606b024d9f5 GIT binary patch literal 18902 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 26.2 + (with-no-warnings (setq fallback 'magit-status)) ; for Emacs 25 + (exit-minibuffer)) + +;;;###autoload +(defun magit-dired-jump (&optional other-window) + "Visit file at point using Dired. +With a prefix argument, visit in another window. If there +is no file at point, then instead visit `default-directory'." + (interactive "P") + (dired-jump other-window + (when-let ((file (magit-file-at-point))) + (expand-file-name (if (file-directory-p file) + (file-name-as-directory file) + file))))) + +;;;###autoload +(defun magit-dired-log (&optional follow) + "Show log for all marked files, or the current file." + (interactive "P") + (if-let ((topdir (magit-toplevel default-directory))) + (let ((args (car (magit-log-arguments))) + (files (dired-get-marked-files nil nil #'magit-file-tracked-p))) + (unless files + (user-error "No marked file is being tracked by Git")) + (when (and follow + (not (member "--follow" args)) + (not (cdr files))) + (push "--follow" args)) + (magit-log-setup-buffer + (list (or (magit-get-current-branch) "HEAD")) + args + (let ((default-directory topdir)) + (mapcar #'file-relative-name files)) + magit-log-buffer-file-locked)) + (magit--not-inside-repository-error))) + +;;;###autoload +(defun magit-do-async-shell-command (file) + "Open FILE with `dired-do-async-shell-command'. +Interactively, open the file at point." + (interactive (list (or (magit-file-at-point) + (completing-read "Act on file: " + (magit-list-files))))) + (require 'dired-aux) + (dired-do-async-shell-command + (dired-read-shell-command "& on %s: " current-prefix-arg (list file)) + nil (list file))) + +;;; Shift Selection + +(defun magit--turn-on-shift-select-mode-p () + (and shift-select-mode + this-command-keys-shift-translated + (not mark-active) + (not (eq (car-safe transient-mark-mode) 'only)))) + +;;;###autoload +(defun magit-previous-line (&optional arg try-vscroll) + "Like `previous-line' but with Magit-specific shift-selection. + +Magit's selection mechanism is based on the region but selects an +area that is larger than the region. This causes `previous-line' +when invoked while holding the shift key to move up one line and +thereby select two lines. When invoked inside a hunk body this +command does not move point on the first invocation and thereby +it only selects a single line. Which inconsistency you prefer +is a matter of preference." + (declare (interactive-only + "use `forward-line' with negative argument instead.")) + (interactive "p\np") + (unless arg (setq arg 1)) + (let ((stay (or (magit-diff-inside-hunk-body-p) + (magit-section-position-in-heading-p)))) + (if (and stay (= arg 1) (magit--turn-on-shift-select-mode-p)) + (push-mark nil nil t) + (with-no-warnings + (handle-shift-selection) + (previous-line (if stay (max (1- arg) 1) arg) try-vscroll))))) + +;;;###autoload +(defun magit-next-line (&optional arg try-vscroll) + "Like `next-line' but with Magit-specific shift-selection. + +Magit's selection mechanism is based on the region but selects +an area that is larger than the region. This causes `next-line' +when invoked while holding the shift key to move down one line +and thereby select two lines. When invoked inside a hunk body +this command does not move point on the first invocation and +thereby it only selects a single line. Which inconsistency you +prefer is a matter of preference." + (declare (interactive-only forward-line)) + (interactive "p\np") + (unless arg (setq arg 1)) + (let ((stay (or (magit-diff-inside-hunk-body-p) + (magit-section-position-in-heading-p)))) + (if (and stay (= arg 1) (magit--turn-on-shift-select-mode-p)) + (push-mark nil nil t) + (with-no-warnings + (handle-shift-selection) + (next-line (if stay (max (1- arg) 1) arg) try-vscroll))))) + +;;; Clean + +;;;###autoload +(defun magit-clean (&optional arg) + "Remove untracked files from the working tree. +With a prefix argument also remove ignored files, +with two prefix arguments remove ignored files only. +\n(git clean -f -d [-x|-X])" + (interactive "p") + (when (yes-or-no-p (format "Remove %s files? " + (pcase arg + (1 "untracked") + (4 "untracked and ignored") + (_ "ignored")))) + (magit-wip-commit-before-change) + (magit-run-git "clean" "-f" "-d" (pcase arg (4 "-x") (16 "-X"))))) + +(put 'magit-clean 'disabled t) + +;;; ChangeLog + +;;;###autoload +(defun magit-add-change-log-entry (&optional whoami file-name other-window) + "Find change log file and add date entry and item for current change. +This differs from `add-change-log-entry' (which see) in that +it acts on the current hunk in a Magit buffer instead of on +a position in a file-visiting buffer." + (interactive (list current-prefix-arg + (prompt-for-change-log-name))) + (pcase-let ((`(,buf ,pos) (magit-diff-visit-file--noselect))) + (magit--with-temp-position buf pos + (add-change-log-entry whoami file-name other-window)))) + +;;;###autoload +(defun magit-add-change-log-entry-other-window (&optional whoami file-name) + "Find change log file in other window and add entry and item. +This differs from `add-change-log-entry-other-window' (which see) +in that it acts on the current hunk in a Magit buffer instead of +on a position in a file-visiting buffer." + (interactive (and current-prefix-arg + (list current-prefix-arg + (prompt-for-change-log-name)))) + (magit-add-change-log-entry whoami file-name t)) + +;;; Edit Line Commit + +;;;###autoload +(defun magit-edit-line-commit (&optional type) + "Edit the commit that added the current line. + +With a prefix argument edit the commit that removes the line, +if any. The commit is determined using `git blame' and made +editable using `git rebase --interactive' if it is reachable +from `HEAD', or by checking out the commit (or a branch that +points at it) otherwise." + (interactive (list (and current-prefix-arg 'removal))) + (let* ((chunk (magit-current-blame-chunk (or type 'addition))) + (rev (oref chunk orig-rev))) + (if (equal rev "0000000000000000000000000000000000000000") + (message "This line has not been committed yet") + (let ((rebase (magit-rev-ancestor-p rev "HEAD")) + (file (expand-file-name (oref chunk orig-file) + (magit-toplevel)))) + (if rebase + (let ((magit--rebase-published-symbol 'edit-published)) + (magit-rebase-edit-commit rev (magit-rebase-arguments))) + (magit-checkout (or (magit-rev-branch rev) rev))) + (unless (and buffer-file-name + (file-equal-p file buffer-file-name)) + (let ((blame-type (and magit-blame-mode magit-blame-type))) + (if rebase + (set-process-sentinel + magit-this-process + (lambda (process event) + (magit-sequencer-process-sentinel process event) + (when (eq (process-status process) 'exit) + (find-file file) + (when blame-type + (magit-blame--pre-blame-setup blame-type) + (magit-blame--run (magit-blame-arguments)))))) + (find-file file) + (when blame-type + (magit-blame--pre-blame-setup blame-type) + (magit-blame--run (magit-blame-arguments)))))))))) + +(put 'magit-edit-line-commit 'disabled t) + +;;;###autoload +(defun magit-diff-edit-hunk-commit (file) + "From a hunk, edit the respective commit and visit the file. + +First visit the file being modified by the hunk at the correct +location using `magit-diff-visit-file'. This actually visits a +blob. When point is on a diff header, not within an individual +hunk, then this visits the blob the first hunk is about. + +Then invoke `magit-edit-line-commit', which uses an interactive +rebase to make the commit editable, or if that is not possible +because the commit is not reachable from `HEAD' by checking out +that commit directly. This also causes the actual worktree file +to be visited. + +Neither the blob nor the file buffer are killed when finishing +the rebase. If that is undesirable, then it might be better to +use `magit-rebase-edit-command' instead of this command." + (interactive (list (magit-file-at-point t t))) + (let ((magit-diff-visit-previous-blob nil)) + (with-current-buffer + (magit-diff-visit-file--internal file nil #'pop-to-buffer-same-window) + (magit-edit-line-commit)))) + +(put 'magit-diff-edit-hunk-commit 'disabled t) + +;;; Reshelve + +;;;###autoload +(defun magit-reshelve-since (rev) + "Change the author and committer dates of the commits since REV. + +Ask the user for the first reachable commit whose dates should +be changed. Then read the new date for that commit. The initial +minibuffer input and the previous history element offer good +values. The next commit will be created one minute later and so +on. + +This command is only intended for interactive use and should only +be used on highly rearranged and unpublished history." + (interactive (list nil)) + (cond + ((not rev) + (let ((backup (concat "refs/original/refs/heads/" + (magit-get-current-branch)))) + (when (and (magit-ref-p backup) + (not (magit-y-or-n-p + "Backup ref %s already exists. Override? " backup))) + (user-error "Abort"))) + (magit-log-select 'magit-reshelve-since + "Type %p on a commit to reshelve it and the commits above it,")) + (t + (cl-flet ((adjust (time offset) + (format-time-string + "%F %T %z" + (+ (floor time) + (* offset 60) + (- (car (decode-time time))))))) + (let* ((start (concat rev "^")) + (range (concat start ".." (magit-get-current-branch))) + (time-rev (adjust (float-time (string-to-number + (magit-rev-format "%at" start))) + 1)) + (time-now (adjust (float-time) + (- (string-to-number + (magit-git-string "rev-list" "--count" + range)))))) + (push time-rev magit--reshelve-history) + (let ((date (floor + (float-time + (date-to-time + (read-string "Date for first commit: " + time-now 'magit--reshelve-history)))))) + (magit-with-toplevel + (magit-run-git-async + "filter-branch" "--force" "--env-filter" + (format "case $GIT_COMMIT in %s\nesac" + (mapconcat (lambda (rev) + (prog1 (format "%s) \ +export GIT_AUTHOR_DATE=\"%s\"; \ +export GIT_COMMITTER_DATE=\"%s\";;" rev date date) + (cl-incf date 60))) + (magit-git-lines "rev-list" "--reverse" + range) + " ")) + range "--") + (set-process-sentinel + magit-this-process + (lambda (process event) + (when (memq (process-status process) '(exit signal)) + (if (> (process-exit-status process) 0) + (magit-process-sentinel process event) + (process-put process 'inhibit-refresh t) + (magit-process-sentinel process event) + (magit-run-git "update-ref" "-d" + (concat "refs/original/refs/heads/" + (magit-get-current-branch)))))))))))))) + +;;; Revision Stack + +(defvar magit-revision-stack nil) + +(defcustom magit-pop-revision-stack-format + '("[%N: %h] " "%N: %H\n %s\n" "\\[\\([0-9]+\\)[]:]") + "Control how `magit-pop-revision-stack' inserts a revision. + +The command `magit-pop-revision-stack' inserts a representation +of the revision last pushed to the `magit-revision-stack' into +the current buffer. It inserts text at point and/or near the end +of the buffer, and removes the consumed revision from the stack. + +The entries on the stack have the format (HASH TOPLEVEL) and this +option has the format (POINT-FORMAT EOB-FORMAT INDEX-REGEXP), all +of which may be nil or a string (though either one of EOB-FORMAT +or POINT-FORMAT should be a string, and if INDEX-REGEXP is +non-nil, then the two formats should be too). + +First INDEX-REGEXP is used to find the previously inserted entry, +by searching backward from point. The first submatch must match +the index number. That number is incremented by one, and becomes +the index number of the entry to be inserted. If you don't want +to number the inserted revisions, then use nil for INDEX-REGEXP. + +If INDEX-REGEXP is non-nil, then both POINT-FORMAT and EOB-FORMAT +should contain \"%N\", which is replaced with the number that was +determined in the previous step. + +Both formats, if non-nil and after removing %N, are then expanded +using `git show --format=FORMAT ...' inside TOPLEVEL. + +The expansion of POINT-FORMAT is inserted at point, and the +expansion of EOB-FORMAT is inserted at the end of the buffer (if +the buffer ends with a comment, then it is inserted right before +that)." + :package-version '(magit . "2.3.0") + :group 'magit-commands + :type '(list (choice (string :tag "Insert at point format") + (cons (string :tag "Insert at point format") + (repeat (string :tag "Argument to git show"))) + (const :tag "Don't insert at point" nil)) + (choice (string :tag "Insert at eob format") + (cons (string :tag "Insert at eob format") + (repeat (string :tag "Argument to git show"))) + (const :tag "Don't insert at eob" nil)) + (choice (regexp :tag "Find index regexp") + (const :tag "Don't number entries" nil)))) + +;;;###autoload +(defun magit-pop-revision-stack (rev toplevel) + "Insert a representation of a revision into the current buffer. + +Pop a revision from the `magit-revision-stack' and insert it into +the current buffer according to `magit-pop-revision-stack-format'. +Revisions can be put on the stack using `magit-copy-section-value' +and `magit-copy-buffer-revision'. + +If the stack is empty or with a prefix argument, instead read a +revision in the minibuffer. By using the minibuffer history this +allows selecting an item which was popped earlier or to insert an +arbitrary reference or revision without first pushing it onto the +stack. + +When reading the revision from the minibuffer, then it might not +be possible to guess the correct repository. When this command +is called inside a repository (e.g. while composing a commit +message), then that repository is used. Otherwise (e.g. while +composing an email) then the repository recorded for the top +element of the stack is used (even though we insert another +revision). If not called inside a repository and with an empty +stack, or with two prefix arguments, then read the repository in +the minibuffer too." + (interactive + (if (or current-prefix-arg (not magit-revision-stack)) + (let ((default-directory + (or (and (not (= (prefix-numeric-value current-prefix-arg) 16)) + (or (magit-toplevel) + (cadr (car magit-revision-stack)))) + (magit-read-repository)))) + (list (magit-read-branch-or-commit "Insert revision") + default-directory)) + (push (caar magit-revision-stack) magit-revision-history) + (pop magit-revision-stack))) + (if rev + (pcase-let ((`(,pnt-format ,eob-format ,idx-format) + magit-pop-revision-stack-format)) + (let ((default-directory toplevel) + (idx (and idx-format + (save-excursion + (if (re-search-backward idx-format nil t) + (number-to-string + (1+ (string-to-number (match-string 1)))) + "1")))) + pnt-args eob-args) + (when (listp pnt-format) + (setq pnt-args (cdr pnt-format)) + (setq pnt-format (car pnt-format))) + (when (listp eob-format) + (setq eob-args (cdr eob-format)) + (setq eob-format (car eob-format))) + (when pnt-format + (when idx-format + (setq pnt-format + (replace-regexp-in-string "%N" idx pnt-format t t))) + (magit-rev-insert-format pnt-format rev pnt-args) + (backward-delete-char 1)) + (when eob-format + (when idx-format + (setq eob-format + (replace-regexp-in-string "%N" idx eob-format t t))) + (save-excursion + (goto-char (point-max)) + (skip-syntax-backward ">s-") + (beginning-of-line) + (if (and comment-start (looking-at comment-start)) + (while (looking-at comment-start) + (forward-line -1)) + (forward-line) + (unless (= (current-column) 0) + (insert ?\n))) + (insert ?\n) + (magit-rev-insert-format eob-format rev eob-args) + (backward-delete-char 1))))) + (user-error "Revision stack is empty"))) + +(define-key git-commit-mode-map + (kbd "C-c C-w") 'magit-pop-revision-stack) + +;;;###autoload +(defun magit-copy-section-value () + "Save the value of the current section for later use. + +Save the section value to the `kill-ring', and, provided that +the current section is a commit, branch, or tag section, push +the (referenced) revision to the `magit-revision-stack' for use +with `magit-pop-revision-stack'. + +When the current section is a branch or a tag, and a prefix +argument is used, then save the revision at its tip to the +`kill-ring' instead of the reference name. + +When the region is active, then save that to the `kill-ring', +like `kill-ring-save' would, instead of behaving as described +above. If a prefix argument is used and the region is within a +hunk, strip the outer diff marker column." + (interactive) + (cond + ((and current-prefix-arg + (magit-section-internal-region-p) + (magit-section-match 'hunk)) + (deactivate-mark) + (kill-new (replace-regexp-in-string + "^[ \\+\\-]" "" + (buffer-substring-no-properties + (region-beginning) (region-end))))) + ((use-region-p) + (call-interactively #'copy-region-as-kill)) + (t + (when-let ((section (magit-current-section)) + (value (oref section value))) + (magit-section-case + ((branch commit module-commit tag) + (let ((default-directory default-directory) ref) + (magit-section-case + ((branch tag) + (setq ref value)) + (module-commit + (setq default-directory + (file-name-as-directory + (expand-file-name (magit-section-parent-value section) + (magit-toplevel)))))) + (setq value (magit-rev-parse value)) + (push (list value default-directory) magit-revision-stack) + (kill-new (message "%s" (or (and current-prefix-arg ref) + value))))) + (t (kill-new (message "%s" value)))))))) + +;;;###autoload +(defun magit-copy-buffer-revision () + "Save the revision of the current buffer for later use. + +Save the revision shown in the current buffer to the `kill-ring' +and push it to the `magit-revision-stack'. + +This command is mainly intended for use in `magit-revision-mode' +buffers, the only buffers where it is always unambiguous exactly +which revision should be saved. + +Most other Magit buffers usually show more than one revision, in +some way or another, so this command has to select one of them, +and that choice might not always be the one you think would have +been the best pick. + +In such buffers it is often more useful to save the value of +the current section instead, using `magit-copy-section-value'. + +When the region is active, then save that to the `kill-ring', +like `kill-ring-save' would, instead of behaving as described +above." + (interactive) + (if (use-region-p) + (call-interactively #'copy-region-as-kill) + (when-let ((rev (or magit-buffer-revision + (cl-case major-mode + (magit-diff-mode + (if (string-match "\\.\\.\\.?\\(.+\\)" + magit-buffer-range) + (match-string 1 magit-buffer-range) + magit-buffer-range)) + (magit-status-mode "HEAD"))))) + (when (magit-commit-p rev) + (setq rev (magit-rev-parse rev)) + (push (list rev default-directory) magit-revision-stack) + (kill-new (message "%s" rev)))))) + +;;; Miscellaneous + +;;;###autoload +(defun magit-abort-dwim () + "Abort current operation. +Depending on the context, this will abort a merge, a rebase, a +patch application, a cherry-pick, a revert, or a bisect." + (interactive) + (cond ((magit-merge-in-progress-p) (magit-merge-abort)) + ((magit-rebase-in-progress-p) (magit-rebase-abort)) + ((magit-am-in-progress-p) (magit-am-abort)) + ((magit-sequencer-in-progress-p) (magit-sequencer-abort)) + ((magit-bisect-in-progress-p) (magit-bisect-reset)))) + +;;; _ +(provide 'magit-extras) +;;; magit-extras.el ends here diff --git a/elpa/magit-20191122.2040/magit-extras.elc b/elpa/magit-20191122.2040/magit-extras.elc new file mode 100644 index 0000000000000000000000000000000000000000..108e72c1dc3427e641ab029bb8e96264eb5413a6 GIT binary patch literal 22004 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 literal 0 HcmV?d00001 diff --git a/elpa/magit-20191122.2040/magit-fetch.el b/elpa/magit-20191122.2040/magit-fetch.el new file mode 100644 index 00000000..4a1676ec --- /dev/null +++ b/elpa/magit-20191122.2040/magit-fetch.el @@ -0,0 +1,186 @@ +;;; magit-fetch.el --- download objects and refs -*- lexical-binding: t -*- + +;; Copyright (C) 2008-2019 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; This library implements fetch commands. + +;;; Code: + +(require 'magit) + +;;; Options + +(defcustom magit-fetch-modules-jobs 4 + "Number of submodules to fetch in parallel. +Ignored for Git versions before v2.8.0." + :package-version '(magit . "2.12.0") + :group 'magit-commands + :type '(choice (const :tag "one at a time" nil) number)) + +;;; Commands + +;;;###autoload (autoload 'magit-fetch "magit-fetch" nil t) +(define-transient-command magit-fetch () + "Fetch from another repository." + :man-page "git-fetch" + ["Arguments" + ("-p" "Prune deleted branches" ("-p" "--prune")) + ("-t" "Fetch all tags" ("-t" "--tags"))] + ["Fetch from" + ("p" magit-fetch-from-pushremote) + ("u" magit-fetch-from-upstream) + ("e" "elsewhere" magit-fetch-other) + ("a" "all remotes" magit-fetch-all)] + ["Fetch" + ("o" "another branch" magit-fetch-branch) + ("r" "explicit refspec" magit-fetch-refspec) + ("m" "submodules" magit-fetch-modules)] + ["Configure" + ("C" "variables..." magit-branch-configure)]) + +(defun magit-fetch-arguments () + (transient-args 'magit-fetch)) + +(defun magit-git-fetch (remote args) + (run-hooks 'magit-credential-hook) + (magit-run-git-async "fetch" remote args)) + +;;;###autoload (autoload 'magit-fetch-from-pushremote "magit-fetch" nil t) +(define-suffix-command magit-fetch-from-pushremote (args) + "Fetch from the current push-remote. + +When the push-remote is not configured, then read the push-remote +from the user, set it, and then fetch from it. With a prefix +argument the push-remote can be changed before fetching from it." + :description 'magit-fetch--pushremote-description + (interactive (list (magit-fetch-arguments))) + (let ((remote (magit-get-push-remote))) + (when (or current-prefix-arg + (not (member remote (magit-list-remotes)))) + (let ((var (magit--push-remote-variable))) + (setq remote + (magit-read-remote (format "Set %s and fetch from there" var))) + (magit-set remote var))) + (magit-git-fetch remote args))) + +(defun magit-fetch--pushremote-description () + (let* ((branch (magit-get-current-branch)) + (remote (magit-get-push-remote branch)) + (v (magit--push-remote-variable branch t))) + (cond + ((member remote (magit-list-remotes)) remote) + (remote + (format "%s, replacing invalid" v)) + (t + (format "%s, setting that" v))))) + +;;;###autoload (autoload 'magit-fetch-from-upstream "magit-fetch" nil t) +(define-suffix-command magit-fetch-from-upstream (remote args) + "Fetch from the \"current\" remote, usually the upstream. + +If the upstream is configured for the current branch and names +an existing remote, then use that. Otherwise try to use another +remote: If only a single remote is configured, then use that. +Otherwise if a remote named \"origin\" exists, then use that. + +If no remote can be determined, then this command is not available +from the `magit-fetch' transient prefix and invoking it directly +results in an error." + :if (lambda () (magit-get-current-remote t)) + :description (lambda () (magit-get-current-remote t)) + (interactive (list (magit-get-current-remote t) + (magit-fetch-arguments))) + (unless remote + (error "The \"current\" remote could not be determined")) + (magit-git-fetch remote args)) + +;;;###autoload +(defun magit-fetch-other (remote args) + "Fetch from another repository." + (interactive (list (magit-read-remote "Fetch remote") + (magit-fetch-arguments))) + (magit-git-fetch remote args)) + +;;;###autoload +(defun magit-fetch-branch (remote branch args) + "Fetch a BRANCH from a REMOTE." + (interactive + (let ((remote (magit-read-remote-or-url "Fetch from remote or url"))) + (list remote + (magit-read-remote-branch "Fetch branch" remote) + (magit-fetch-arguments)))) + (magit-git-fetch remote (cons branch args))) + +;;;###autoload +(defun magit-fetch-refspec (remote refspec args) + "Fetch a REFSPEC from a REMOTE." + (interactive + (let ((remote (magit-read-remote-or-url "Fetch from remote or url"))) + (list remote + (magit-read-refspec "Fetch using refspec" remote) + (magit-fetch-arguments)))) + (magit-git-fetch remote (cons refspec args))) + +;;;###autoload +(defun magit-fetch-all (args) + "Fetch from all remotes." + (interactive (list (magit-fetch-arguments))) + (magit-git-fetch nil (cons "--all" args))) + +;;;###autoload +(defun magit-fetch-all-prune () + "Fetch from all remotes, and prune. +Prune remote tracking branches for branches that have been +removed on the respective remote." + (interactive) + (run-hooks 'magit-credential-hook) + (magit-run-git-async "remote" "update" "--prune")) + +;;;###autoload +(defun magit-fetch-all-no-prune () + "Fetch from all remotes." + (interactive) + (run-hooks 'magit-credential-hook) + (magit-run-git-async "remote" "update")) + +;;;###autoload +(defun magit-fetch-modules (&optional all) + "Fetch all submodules. + +Option `magit-fetch-modules-jobs' controls how many submodules +are being fetched in parallel. Also fetch the super-repository, +because `git-fetch' does not support not doing that. With a +prefix argument fetch all remotes." + (interactive "P") + (magit-with-toplevel + (magit-run-git-async + "fetch" "--verbose" "--recurse-submodules" + (and magit-fetch-modules-jobs + (version<= "2.8.0" (magit-git-version)) + (list "-j" (number-to-string magit-fetch-modules-jobs))) + (and all "--all")))) + +;;; _ +(provide 'magit-fetch) +;;; magit-fetch.el ends here diff --git a/elpa/magit-20191122.2040/magit-fetch.elc b/elpa/magit-20191122.2040/magit-fetch.elc new file mode 100644 index 0000000000000000000000000000000000000000..f097d5af8ed95b94a8d1d5a687d926ffffdfc88f GIT binary patch literal 7101 zcmcIpTW{OQ6?S4E*cH&X0_{t&C-f$f3R94%o9(o~dL3sQAl(E>fPIJzEKQCiZYYk* zA)UCtzTcUPMCz6}+ch9d91ai9^*fh&dinC=F9!z)ji*na(uJHal2pX{BFX4-9!838 zM6MEYH8Rpd!F zRmZrStAfHf7BMZ~(miblryDe42^yI!D3VzbVslwc{1dEX{`uRB7cVH9g?ShiVDVVL zKFnfLlAj{u(@K7D)!_za&t!~fB^$9KD3e6XX79bN3`4jz9y4mu-`-sj>!Ws(b; zhtmYgEL9=rek`Ii%!Pjw=1F)Bi|M=mL=@4?pUb#Rh4O!s*RW@qMQm{XW@FRQ`;KMK z(C=SS_lmrq%lS35Dkr4MYfFI&Ntz_vdI4*tsYu)7?8P*bIXqw@bNUHPEp2lxuq5av zXrHt@ZI8|tVe}!Kf=}y+O(R8{yrA6;+8wV&XVYAk3oAe*=X3ahqO;<5A*dP6WD@Z= zytKe#I3-VJfe9?G9U8Tm1XAUB>=c)XXi)qH0)J z0nvhxNp6HMv-FmVrCEJMX*q`+I-<#Y&YnP%T+S&(5YAxQTr8wY3Yp)+GAp_LMJ^`E zr^MU<1&x!{D5T-71gp*W-3paRrsX`N=2WlJBPn0)hritS%?ksYedR@M9Kvcgb3&RNw6Vm78R)yAK{r*3so7^ zZo8jmxK5MJVdPy*W(MVdswTLi3Hh-e3G zdv`za`8x3x>hB@S;Jtza#%2 z9y)9XGWjzpKe(4hNT`7CBuw?PWrcS!-~=F#`mrl8+Bg#y54w`bYh z#h-q3J?6n{Fc@iGyYvmRPXA8_$Yn@Poq)zcZ@^1`JHTa+TwcTX@Nn#*tQiLPaWT4o zf9&C6h>LFL9&Xv}6_t6;iPfYNwuBXGDzFIL@lBxG)ihCsU2!_8?piN(fH$!tfTClL ziokm-3VNiF@KBnp@*gKZK#V~aWO>JhOJ!Fya_St6hVa(4Oive9pei;k{R$-qTVVYm zC`M}$-@UaQf5-A*TP3hz$FHjlpcxdD+DcS02r9gB_RCCUsIf)$2BAN&6}^e=_?Wk3 z0HiQp-#pHA^}!_2PUOeLs!xhzZ65tp#YRcdCi+D;CuIC(oH-S*6LuW}`iE@FrGP0q zH8pf8rsx5|T8W|z=qw8W-!3firIwnimae2ol-Qel+Tu+Vt@7@W*AXwjr=9i3XjMEhUk`L0c%|qQ_MqC$P&JELPejyx6BZw`ITbY)1vx zzpM88o$jtI@<(b8WQz?S>gAIh4XwP2;8UF$}JG zw7IjL4z2B%CX-(#kZTJ6FVb95&&n_if~pL| zW$?r5tBD4D_m!DHR&!@PTj!uxN$9_kV}GJmve$AI9RbKB-p;d3{w}VvE;X~$1OXeh8@VdBGSHy zgU#5P4{$gkJmym!nT08xzkIoENMXFtP4_uchdLQ>vyZMn==7Sp|NkpvIs-aBy7Az{ zh=CpiEDtPD`M5=Ma`ElMXAd6m61OMa{-YLt2Y=_^1CZBMIuGVig7~H;!6e!i;5EL? zxrKqLLM~EqBT~C>>o|mc8|MqxQW-x-xl`s!pu= +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; This library implements support for finding blobs, staged files, +;; and Git configuration files. It also implements modes useful in +;; buffers visiting files and blobs, and the commands used by those +;; modes. + +;;; Code: + +(eval-when-compile + (require 'subr-x)) + +(require 'magit) + +;;; Find Blob + +(defvar magit-find-file-hook nil) +(add-hook 'magit-find-file-hook #'magit-blob-mode) + +;;;###autoload +(defun magit-find-file (rev file) + "View FILE from REV. +Switch to a buffer visiting blob REV:FILE, creating one if none +already exists. If prior to calling this command the current +buffer and/or cursor position is about the same file, then go +to the line and column corresponding to that location." + (interactive (magit-find-file-read-args "Find file")) + (magit-find-file--internal rev file #'pop-to-buffer-same-window)) + +;;;###autoload +(defun magit-find-file-other-window (rev file) + "View FILE from REV, in another window. +Switch to a buffer visiting blob REV:FILE, creating one if none +already exists. If prior to calling this command the current +buffer and/or cursor position is about the same file, then go to +the line and column corresponding to that location." + (interactive (magit-find-file-read-args "Find file in other window")) + (magit-find-file--internal rev file #'switch-to-buffer-other-window)) + +;;;###autoload +(defun magit-find-file-other-frame (rev file) + "View FILE from REV, in another frame. +Switch to a buffer visiting blob REV:FILE, creating one if none +already exists. If prior to calling this command the current +buffer and/or cursor position is about the same file, then go to +the line and column corresponding to that location." + (interactive (magit-find-file-read-args "Find file in other frame")) + (magit-find-file--internal rev file #'switch-to-buffer-other-frame)) + +(defun magit-find-file-read-args (prompt) + (let ((pseudo-revs '("{worktree}" "{index}"))) + (if-let ((rev (magit-completing-read "Find file from revision" + (append pseudo-revs + (magit-list-refnames nil t)) + nil nil nil 'magit-revision-history + (or (magit-branch-or-commit-at-point) + (magit-get-current-branch))))) + (list rev (magit-read-file-from-rev (if (member rev pseudo-revs) + "HEAD" + rev) + prompt)) + (user-error "Nothing selected")))) + +(defun magit-find-file--internal (rev file fn) + (let ((buf (magit-find-file-noselect rev file)) + line col) + (when-let ((visited-file (magit-file-relative-name))) + (setq line (line-number-at-pos)) + (setq col (current-column)) + (cond + ((not (equal visited-file file))) + ((equal magit-buffer-revision rev)) + ((equal rev "{worktree}") + (setq line (magit-diff-visit--offset file magit-buffer-revision line))) + ((equal rev "{index}") + (setq line (magit-diff-visit--offset file nil line))) + (magit-buffer-revision + (setq line (magit-diff-visit--offset + file (concat magit-buffer-revision ".." rev) line))) + (t + (setq line (magit-diff-visit--offset file (list "-R" rev) line))))) + (funcall fn buf) + (when line + (with-current-buffer buf + (widen) + (goto-char (point-min)) + (forward-line (1- line)) + (move-to-column col))) + buf)) + +(defun magit-find-file-noselect (rev file) + "Read FILE from REV into a buffer and return the buffer. +REV is a revision or one of \"{worktree}\" or \"{index}\". +FILE must be relative to the top directory of the repository." + (magit-find-file-noselect-1 rev file)) + +(defun magit-find-file-noselect-1 (rev file &optional revert) + "Read FILE from REV into a buffer and return the buffer. +REV is a revision or one of \"{worktree}\" or \"{index}\". +FILE must be relative to the top directory of the repository. +Non-nil REVERT means to revert the buffer. If `ask-revert', +then only after asking. A non-nil value for REVERT is ignored if REV is +\"{worktree}\"." + (if (equal rev "{worktree}") + (find-file-noselect (expand-file-name file (magit-toplevel))) + (let ((topdir (magit-toplevel))) + (when (file-name-absolute-p file) + (setq file (file-relative-name file topdir))) + (with-current-buffer (magit-get-revision-buffer-create rev file) + (when (or (not magit-buffer-file-name) + (if (eq revert 'ask-revert) + (y-or-n-p (format "%s already exists; revert it? " + (buffer-name)))) + revert) + (setq magit-buffer-revision + (if (equal rev "{index}") + "{index}" + (magit-rev-format "%H" rev))) + (setq magit-buffer-refname rev) + (setq magit-buffer-file-name (expand-file-name file topdir)) + (setq default-directory + (let ((dir (file-name-directory magit-buffer-file-name))) + (if (file-exists-p dir) dir topdir))) + (setq-local revert-buffer-function #'magit-revert-rev-file-buffer) + (revert-buffer t t) + (run-hooks (if (equal rev "{index}") + 'magit-find-index-hook + 'magit-find-file-hook))) + (current-buffer))))) + +(defun magit-get-revision-buffer-create (rev file) + (magit-get-revision-buffer rev file t)) + +(defun magit-get-revision-buffer (rev file &optional create) + (funcall (if create 'get-buffer-create 'get-buffer) + (format "%s.~%s~" file (subst-char-in-string ?/ ?_ rev)))) + +(defun magit-revert-rev-file-buffer (_ignore-auto noconfirm) + (when (or noconfirm + (and (not (buffer-modified-p)) + (catch 'found + (dolist (regexp revert-without-query) + (when (string-match regexp magit-buffer-file-name) + (throw 'found t))))) + (yes-or-no-p (format "Revert buffer from Git %s? " + (if (equal magit-buffer-refname "{index}") + "index" + (concat "revision " magit-buffer-refname))))) + (let* ((inhibit-read-only t) + (default-directory (magit-toplevel)) + (file (file-relative-name magit-buffer-file-name)) + (coding-system-for-read (or coding-system-for-read 'undecided))) + (erase-buffer) + (magit-git-insert "cat-file" "-p" + (if (equal magit-buffer-refname "{index}") + (concat ":" file) + (concat magit-buffer-refname ":" file))) + (setq buffer-file-coding-system last-coding-system-used)) + (let ((buffer-file-name magit-buffer-file-name) + (after-change-major-mode-hook + (remq 'global-diff-hl-mode-enable-in-buffers + after-change-major-mode-hook))) + (normal-mode t)) + (setq buffer-read-only t) + (set-buffer-modified-p nil) + (goto-char (point-min)))) + +;;; Find Index + +(defvar magit-find-index-hook nil) + +(defun magit-find-file-index-noselect (file &optional revert) + "Read FILE from the index into a buffer and return the buffer. +FILE must to be relative to the top directory of the repository." + (magit-find-file-noselect-1 "{index}" file (or revert 'ask-revert))) + +(defun magit-update-index () + "Update the index with the contents of the current buffer. +The current buffer has to be visiting a file in the index, which +is done using `magit-find-index-noselect'." + (interactive) + (let ((file (magit-file-relative-name))) + (unless (equal magit-buffer-refname "{index}") + (user-error "%s isn't visiting the index" file)) + (if (y-or-n-p (format "Update index with contents of %s" (buffer-name))) + (let ((index (make-temp-file "index")) + (buffer (current-buffer))) + (when magit-wip-before-change-mode + (magit-wip-commit-before-change (list file) " before un-/stage")) + (let ((coding-system-for-write buffer-file-coding-system)) + (with-temp-file index + (insert-buffer-substring buffer))) + (magit-with-toplevel + (magit-call-git "update-index" "--cacheinfo" + (substring (magit-git-string "ls-files" "-s" file) + 0 6) + (magit-git-string "hash-object" "-t" "blob" "-w" + (concat "--path=" file) + "--" index) + file)) + (set-buffer-modified-p nil) + (when magit-wip-after-apply-mode + (magit-wip-commit-after-apply (list file) " after un-/stage"))) + (message "Abort"))) + (--when-let (magit-get-mode-buffer 'magit-status-mode) + (with-current-buffer it (magit-refresh))) + t) + +;;; Find Config File + +(defun magit-find-git-config-file (filename &optional wildcards) + "Edit a file located in the current repository's git directory. + +When \".git\", located at the root of the working tree, is a +regular file, then that makes it cumbersome to open a file +located in the actual git directory. + +This command is like `find-file', except that it temporarily +binds `default-directory' to the actual git directory, while +reading the FILENAME." + (interactive + (let ((default-directory (magit-git-dir))) + (find-file-read-args "Find file: " + (confirm-nonexistent-file-or-buffer)))) + (find-file filename wildcards)) + +(defun magit-find-git-config-file-other-window (filename &optional wildcards) + "Edit a file located in the current repository's git directory, in another window. + +When \".git\", located at the root of the working tree, is a +regular file, then that makes it cumbersome to open a file +located in the actual git directory. + +This command is like `find-file-other-window', except that it +temporarily binds `default-directory' to the actual git +directory, while reading the FILENAME." + (interactive + (let ((default-directory (magit-git-dir))) + (find-file-read-args "Find file in other window: " + (confirm-nonexistent-file-or-buffer)))) + (find-file-other-window filename wildcards)) + +(defun magit-find-git-config-file-other-frame (filename &optional wildcards) + "Edit a file located in the current repository's git directory, in another frame. + +When \".git\", located at the root of the working tree, is a +regular file, then that makes it cumbersome to open a file +located in the actual git directory. + +This command is like `find-file-other-frame', except that it +temporarily binds `default-directory' to the actual git +directory, while reading the FILENAME." + (interactive + (let ((default-directory (magit-git-dir))) + (find-file-read-args "Find file in other frame: " + (confirm-nonexistent-file-or-buffer)))) + (find-file-other-frame filename wildcards)) + +;;; File Mode + +(defvar magit-file-mode-map + (let ((map (make-sparse-keymap))) + (define-key map "\C-xg" 'magit-status) + (define-key map "\C-x\M-g" 'magit-dispatch) + (define-key map "\C-c\M-g" 'magit-file-dispatch) + map) + "Keymap for `magit-file-mode'.") + +;;;###autoload (autoload 'magit-file-dispatch "magit" nil t) +(define-transient-command magit-file-dispatch () + "Invoke a Magit command that acts on the visited file." + :info-manual "(magit) Minor Mode for Buffers Visiting Files" + ["Actions" + [("s" "Stage" magit-stage-file) + ("u" "Unstage" magit-unstage-file) + ("c" "Commit" magit-commit) + ("e" "Edit line" magit-edit-line-commit)] + [("D" "Diff..." magit-diff) + ("d" "Diff" magit-diff-buffer-file) + ("g" "Status" magit-status-here)] + [("L" "Log..." magit-log) + ("l" "Log" magit-log-buffer-file) + ("t" "Trace" magit-log-trace-definition)] + [("B" "Blame..." magit-blame) + ("b" "Blame" magit-blame-addition) + ("r" "...removal" magit-blame-removal) + ("f" "...reverse" magit-blame-reverse) + ("m" "Blame echo" magit-blame-echo) + ("q" "Quit blame" magit-blame-quit)] + [("p" "Prev blob" magit-blob-previous) + ("n" "Next blob" magit-blob-next) + ("v" "Goto blob" magit-find-file) + ("V" "Goto file" magit-blob-visit-file)] + [(5 "C-c r" "Rename file" magit-file-rename) + (5 "C-c d" "Delete file" magit-file-delete) + (5 "C-c u" "Untrack file" magit-file-untrack) + (5 "C-c c" "Checkout file" magit-file-checkout)]]) + +(defvar magit-file-mode-lighter "") + +(define-minor-mode magit-file-mode + "Enable some Magit features in a file-visiting buffer. + +Currently this only adds the following key bindings. +\n\\{magit-file-mode-map}" + :package-version '(magit . "2.2.0") + :lighter magit-file-mode-lighter + :keymap magit-file-mode-map) + +(defun magit-file-mode-turn-on () + (and buffer-file-name + (magit-inside-worktree-p t) + (magit-file-mode))) + +;;;###autoload +(define-globalized-minor-mode global-magit-file-mode + magit-file-mode magit-file-mode-turn-on + :package-version '(magit . "2.13.0") + :link '(info-link "(magit)Minor Mode for Buffers Visiting Files") + :group 'magit-essentials + :group 'magit-modes + :init-value t) +;; Unfortunately `:init-value t' only sets the value of the mode +;; variable but does not cause the mode function to be called, and we +;; cannot use `:initialize' to call that explicitly because the option +;; is defined before the functions, so we have to do it here. +(cl-eval-when (load eval) + (when global-magit-file-mode + (global-magit-file-mode 1))) + +;;; Blob Mode + +(defvar magit-blob-mode-map + (let ((map (make-sparse-keymap))) + (cond ((featurep 'jkl) + (define-key map "i" 'magit-blob-previous) + (define-key map "k" 'magit-blob-next) + (define-key map "j" 'magit-blame-addition) + (define-key map "l" 'magit-blame-removal) + (define-key map "f" 'magit-blame-reverse)) + (t + (define-key map "p" 'magit-blob-previous) + (define-key map "n" 'magit-blob-next) + (define-key map "b" 'magit-blame-addition) + (define-key map "r" 'magit-blame-removal) + (define-key map "f" 'magit-blame-reverse))) + (define-key map "q" 'magit-kill-this-buffer) + map) + "Keymap for `magit-blob-mode'.") + +(define-minor-mode magit-blob-mode + "Enable some Magit features in blob-visiting buffers. + +Currently this only adds the following key bindings. +\n\\{magit-blob-mode-map}" + :package-version '(magit . "2.3.0")) + +(defun magit-blob-next () + "Visit the next blob which modified the current file." + (interactive) + (if magit-buffer-file-name + (magit-blob-visit (or (magit-blob-successor magit-buffer-revision + magit-buffer-file-name) + magit-buffer-file-name)) + (if (buffer-file-name (buffer-base-buffer)) + (user-error "You have reached the end of time") + (user-error "Buffer isn't visiting a file or blob")))) + +(defun magit-blob-previous () + "Visit the previous blob which modified the current file." + (interactive) + (if-let ((file (or magit-buffer-file-name + (buffer-file-name (buffer-base-buffer))))) + (--if-let (magit-blob-ancestor magit-buffer-revision file) + (magit-blob-visit it) + (user-error "You have reached the beginning of time")) + (user-error "Buffer isn't visiting a file or blob"))) + +;;;###autoload +(defun magit-blob-visit-file () + "View the file from the worktree corresponding to the current blob. +When visiting a blob or the version from the index, then go to +the same location in the respective file in the working tree." + (interactive) + (if-let ((file (magit-file-relative-name))) + (magit-find-file--internal "{worktree}" file #'pop-to-buffer-same-window) + (user-error "Not visiting a blob"))) + +(defun magit-blob-visit (blob-or-file) + (if (stringp blob-or-file) + (find-file blob-or-file) + (pcase-let ((`(,rev ,file) blob-or-file)) + (magit-find-file rev file) + (apply #'message "%s (%s %s ago)" + (magit-rev-format "%s" rev) + (magit--age (magit-rev-format "%ct" rev)))))) + +(defun magit-blob-ancestor (rev file) + (let ((lines (magit-with-toplevel + (magit-git-lines "log" "-2" "--format=%H" "--name-only" + "--follow" (or rev "HEAD") "--" file)))) + (if rev (cddr lines) (butlast lines 2)))) + +(defun magit-blob-successor (rev file) + (let ((lines (magit-with-toplevel + (magit-git-lines "log" "--format=%H" "--name-only" "--follow" + "HEAD" "--" file)))) + (catch 'found + (while lines + (if (equal (nth 2 lines) rev) + (throw 'found (list (nth 0 lines) (nth 1 lines))) + (setq lines (nthcdr 2 lines))))))) + +;;; File Commands + +(defun magit-file-rename (file newname) + "Rename the FILE to NEWNAME. +If FILE isn't tracked in Git, fallback to using `rename-file'." + (interactive + (let* ((file (magit-read-file "Rename file")) + (dir (file-name-directory file)) + (newname (read-file-name (format "Rename %s to file: " file) + (and dir (expand-file-name dir))))) + (list (expand-file-name file (magit-toplevel)) + (expand-file-name newname)))) + (let ((oldbuf (get-file-buffer file))) + (when (and oldbuf (buffer-modified-p oldbuf)) + (user-error "Save %s before moving it" file)) + (when (file-exists-p newname) + (user-error "%s already exists" newname)) + (if (magit-file-tracked-p (magit-convert-filename-for-git file)) + (magit-call-git "mv" + (magit-convert-filename-for-git file) + (magit-convert-filename-for-git newname)) + (rename-file file newname current-prefix-arg)) + (when oldbuf + (with-current-buffer oldbuf + (let ((buffer-read-only buffer-read-only)) + (set-visited-file-name newname nil t)) + (if (fboundp 'vc-refresh-state) + (vc-refresh-state) + (with-no-warnings + (vc-find-file-hook)))))) + (magit-refresh)) + +(defun magit-file-untrack (files &optional force) + "Untrack the selected FILES or one file read in the minibuffer. + +With a prefix argument FORCE do so even when the files have +staged as well as unstaged changes." + (interactive (list (or (--if-let (magit-region-values 'file t) + (progn + (unless (magit-file-tracked-p (car it)) + (user-error "Already untracked")) + (magit-confirm-files 'untrack it "Untrack")) + (list (magit-read-tracked-file "Untrack file")))) + current-prefix-arg)) + (magit-with-toplevel + (magit-run-git "rm" "--cached" (and force "--force") "--" files))) + +(defun magit-file-delete (files &optional force) + "Delete the selected FILES or one file read in the minibuffer. + +With a prefix argument FORCE do so even when the files have +uncommitted changes. When the files aren't being tracked in +Git, then fallback to using `delete-file'." + (interactive (list (--if-let (magit-region-values 'file t) + (magit-confirm-files 'delete it "Delete") + (list (magit-read-file "Delete file"))) + current-prefix-arg)) + (if (magit-file-tracked-p (car files)) + (magit-call-git "rm" (and force "--force") "--" files) + (let ((topdir (magit-toplevel))) + (dolist (file files) + (delete-file (expand-file-name file topdir) t)))) + (magit-refresh)) + +;;;###autoload +(defun magit-file-checkout (rev file) + "Checkout FILE from REV." + (interactive + (let ((rev (magit-read-branch-or-commit + "Checkout from revision" magit-buffer-revision))) + (list rev (magit-read-file-from-rev rev "Checkout file")))) + (magit-with-toplevel + (magit-run-git "checkout" rev "--" file))) + +;;; Read File + +(defvar magit-read-file-hist nil) + +(defun magit-read-file-from-rev (rev prompt &optional default) + (let ((files (magit-revision-files rev))) + (magit-completing-read + prompt files nil t nil 'magit-read-file-hist + (car (member (or default (magit-current-file)) files))))) + +(defun magit-read-file (prompt &optional tracked-only) + (let ((choices (nconc (magit-list-files) + (unless tracked-only (magit-untracked-files))))) + (magit-completing-read + prompt choices nil t nil nil + (car (member (or (magit-section-value-if '(file submodule)) + (magit-file-relative-name nil tracked-only)) + choices))))) + +(defun magit-read-tracked-file (prompt) + (magit-read-file prompt t)) + +(defun magit-read-file-choice (prompt files &optional error default) + "Read file from FILES. + +If FILES has only one member, return that instead of prompting. +If FILES has no members, give a user error. ERROR can be given +to provide a more informative error. + +If DEFAULT is non-nil, use this as the default value instead of +`magit-current-file'." + (pcase (length files) + (0 (user-error (or error "No file choices"))) + (1 (car files)) + (_ (magit-completing-read + prompt files nil t nil 'magit-read-file-hist + (car (member (or default (magit-current-file)) files)))))) + +(defun magit-read-changed-file (rev-or-range prompt &optional default) + (magit-read-file-choice + prompt + (magit-changed-files rev-or-range) + default + (concat "No file changed in " rev-or-range))) + +;;; _ +(provide 'magit-files) +;;; magit-files.el ends here diff --git a/elpa/magit-20191122.2040/magit-files.elc b/elpa/magit-20191122.2040/magit-files.elc new file mode 100644 index 0000000000000000000000000000000000000000..647b637c87c81e0b7416c3d28652048a55a7906e GIT binary patch literal 26952 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 C +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; This library implements wrappers for various Git plumbing commands. + +;;; Code: + +(require 'cl-lib) +(require 'dash) + +(eval-when-compile + (require 'subr-x)) + +(require 'magit-utils) +(require 'magit-section) + +;; From `magit-branch'. +(defvar magit-branch-prefer-remote-upstream) +(defvar magit-published-branches) + +;; From `magit-margin'. +(declare-function magit-maybe-make-margin-overlay "magit-margin" ()) + +;; From `magit-mode'. +(declare-function magit-get-mode-buffer "magit-mode" + (mode &optional value frame)) +(declare-function magit-refresh "magit-mode" ()) +(defvar magit-buffer-diff-args) +(defvar magit-buffer-file-name) +(defvar magit-buffer-log-args) +(defvar magit-buffer-log-files) +(defvar magit-buffer-refname) +(defvar magit-buffer-revision) + +;; From `magit-process'. +(declare-function magit-call-git "magit-process" (&rest args)) +(declare-function magit-process-buffer "magit-process" (&optional nodisplay)) +(declare-function magit-process-file "magit-process" (&rest args)) +(declare-function magit-process-insert-section "magit-process" + (pwd program args &optional errcode errlog)) +(defvar magit-this-error) +(defvar magit-process-error-message-regexps) + +;; From later in `magit-git'. +(defvar magit-tramp-process-environment nil) + +(eval-when-compile + (cl-pushnew 'number eieio--known-slot-names)) + +;;; Git implementations + +(defvar magit-inhibit-libgit nil + "Whether to inhibit the use of libgit.") + +(defvar magit--libgit-available-p eieio-unbound + "Whether libgit is available. +Use the function by the same name instead of this variable.") + +(defun magit--libgit-available-p () + (if (eq magit--libgit-available-p eieio-unbound) + (setq magit--libgit-available-p + (and module-file-suffix + (let ((libgit (locate-library "libgit"))) + (and libgit + (or (locate-library "libegit2") + (let ((load-path + (cons (expand-file-name + (convert-standard-filename "build") + (file-name-directory libgit)) + load-path))) + (locate-library "libegit2"))))))) + magit--libgit-available-p)) + +(defun magit-gitimpl () + "Return the Git implementation used in this repository." + (if (and (not magit-inhibit-libgit) + (not (file-remote-p default-directory)) + (magit--libgit-available-p)) + 'libgit + 'git)) + +;;; Options + +;; For now this is shared between `magit-process' and `magit-git'. +(defgroup magit-process nil + "Git and other external processes used by Magit." + :group 'magit) + +(defvar magit-git-environment + (list (format "INSIDE_EMACS=%s,magit" emacs-version)) + "Prepended to `process-environment' while running git.") + +(defcustom magit-git-output-coding-system + (and (eq system-type 'windows-nt) 'utf-8) + "Coding system for receiving output from Git. + +If non-nil, the Git config value `i18n.logOutputEncoding' should +be set via `magit-git-global-arguments' to value consistent with +this." + :package-version '(magit . "2.9.0") + :group 'magit-process + :type '(choice (coding-system :tag "Coding system to decode Git output") + (const :tag "Use system default" nil))) + +(defvar magit-git-w32-path-hack nil + "Alist of (EXE . (PATHENTRY)). +This specifies what additional PATH setting needs to be added to +the environment in order to run the non-wrapper git executables +successfully.") + +(defcustom magit-git-executable + ;; Git might be installed in a different location on a remote, so + ;; it is better not to use the full path to the executable, except + ;; on Window were we would otherwise end up using one one of the + ;; wrappers "cmd/git.exe" or "cmd/git.cmd", which are much slower + ;; than using "bin/git.exe" directly. + (or (and (eq system-type 'windows-nt) + (--when-let (executable-find "git") + (ignore-errors + ;; Git for Windows 2.x provides cygpath so we can + ;; ask it for native paths. + (let* ((core-exe + (car + (process-lines + it "-c" + "alias.X=!x() { which \"$1\" | cygpath -mf -; }; x" + "X" "git"))) + (hack-entry (assoc core-exe magit-git-w32-path-hack)) + ;; Running the libexec/git-core executable + ;; requires some extra PATH entries. + (path-hack + (list (concat "PATH=" + (car (process-lines + it "-c" + "alias.P=!cygpath -wp \"$PATH\"" + "P")))))) + ;; The defcustom STANDARD expression can be + ;; evaluated many times, so make sure it is + ;; idempotent. + (if hack-entry + (setcdr hack-entry path-hack) + (push (cons core-exe path-hack) magit-git-w32-path-hack)) + core-exe)))) + "git") + "The Git executable used by Magit." + :group 'magit-process + :type 'string) + +(defcustom magit-git-global-arguments + `("--no-pager" "--literal-pathspecs" "-c" "core.preloadindex=true" + "-c" "log.showSignature=false" + ,@(and (eq system-type 'windows-nt) + (list "-c" "i18n.logOutputEncoding=UTF-8"))) + "Global Git arguments. + +The arguments set here are used every time the git executable is +run as a subprocess. They are placed right after the executable +itself and before the git command - as in `git HERE... COMMAND +REST'. See the manpage `git(1)' for valid arguments. + +Be careful what you add here, especially if you are using Tramp +to connect to servers with ancient Git versions. Never remove +anything that is part of the default value, unless you really +know what you are doing. And think very hard before adding +something; it will be used every time Magit runs Git for any +purpose." + :package-version '(magit . "2.9.0") + :group 'magit-commands + :group 'magit-process + :type '(repeat string)) + +(defvar magit-git-debug nil + "Whether to enable additional reporting of git errors. + +Magit basically calls git for one of these two reasons: for +side-effects or to do something with its standard output. + +When git is run for side-effects then its output, including error +messages, go into the process buffer which is shown when using \ +\\\\[magit-process]. + +When git's output is consumed in some way, then it would be too +expensive to also insert it into this buffer, but when this +option is non-nil and git returns with a non-zero exit status, +then at least its standard error is inserted into this buffer. + +This is only intended for debugging purposes. Do not enable this +permanently, that would negatively affect performance.") + + +(defcustom magit-prefer-remote-upstream nil + "Whether to favor remote branches when reading the upstream branch. + +This controls whether commands that read a branch from the user +and then set it as the upstream branch, offer a local or a remote +branch as default completion candidate, when they have the choice. + +This affects all commands that use `magit-read-upstream-branch' +or `magit-read-starting-point', which includes most commands +that change the upstream and many that create new branches." + :package-version '(magit . "2.4.2") + :group 'magit-commands + :type 'boolean) + +(defcustom magit-list-refs-sortby nil + "How to sort the ref collection in the prompt. + +This affects commands that read a ref. More specifically, it +controls the order of refs returned by `magit-list-refs', which +is called by functions like `magit-list-branch-names' to generate +the collection of refs. By default, refs are sorted according to +their full refname (i.e., 'refs/...'). + +Any value accepted by the `--sort' flag of `git for-each-ref' can +be used. For example, \"-creatordate\" places refs with more +recent committer or tagger dates earlier in the list. A list of +strings can also be given in order to pass multiple sort keys to +`git for-each-ref'. + +Note that, depending on the completion framework you use, this +may not be sufficient to change the order in which the refs are +displayed. It only controls the order of the collection passed +to `magit-completing-read' or, for commands that support reading +multiple strings, `read-from-minibuffer'. The completion +framework ultimately determines how the collection is displayed." + :package-version '(magit . "2.11.0") + :group 'magit-miscellaneous + :type '(choice string (repeat string))) + +;;; Git + +(defvar magit--refresh-cache nil) + +(defmacro magit--with-refresh-cache (key &rest body) + (declare (indent 1) (debug (form body))) + (let ((k (cl-gensym))) + `(if magit--refresh-cache + (let ((,k ,key)) + (--if-let (assoc ,k (cdr magit--refresh-cache)) + (progn (cl-incf (caar magit--refresh-cache)) + (cdr it)) + (cl-incf (cdar magit--refresh-cache)) + (let ((value ,(macroexp-progn body))) + (push (cons ,k value) + (cdr magit--refresh-cache)) + value))) + ,@body))) + +(defvar magit-with-editor-envvar "GIT_EDITOR" + "The environment variable exported by `magit-with-editor'. +Set this to \"GIT_SEQUENCE_EDITOR\" if you do not want to use +Emacs to edit commit messages but would like to do so to edit +rebase sequences.") + +(defmacro magit-with-editor (&rest body) + "Like `with-editor' but let-bind some more variables. +Also respect the value of `magit-with-editor-envvar'." + (declare (indent 0) (debug (body))) + `(let ((magit-process-popup-time -1) + ;; The user may have customized `shell-file-name' to + ;; something which results in `w32-shell-dos-semantics' nil + ;; (which changes the quoting style used by + ;; `shell-quote-argument'), but Git for Windows expects shell + ;; quoting in the dos style. + (shell-file-name (if (and (eq system-type 'windows-nt) + ;; If we have Cygwin mount points, + ;; the git flavor is cygwin, so dos + ;; shell quoting is probably wrong. + (not magit-cygwin-mount-points)) + "cmdproxy" + shell-file-name))) + (with-editor* magit-with-editor-envvar + ,@body))) + +(defun magit-process-git-arguments (args) + "Prepare ARGS for a function that invokes Git. + +Magit has many specialized functions for running Git; they all +pass arguments through this function before handing them to Git, +to do the following. + +* Flatten ARGS, removing nil arguments. +* Prepend `magit-git-global-arguments' to ARGS. +* On w32 systems, encode to `w32-ansi-code-page'." + (setq args (append magit-git-global-arguments (-flatten args))) + (if (and (eq system-type 'windows-nt) (boundp 'w32-ansi-code-page)) + ;; On w32, the process arguments *must* be encoded in the + ;; current code-page (see #3250). + (mapcar (lambda (arg) + (encode-coding-string + arg (intern (format "cp%d" w32-ansi-code-page)))) + args) + args)) + +(defun magit-git-exit-code (&rest args) + "Execute Git with ARGS, returning its exit code." + (apply #'magit-process-file magit-git-executable nil nil nil + (magit-process-git-arguments args))) + +(defun magit-git-success (&rest args) + "Execute Git with ARGS, returning t if its exit code is 0." + (= (magit-git-exit-code args) 0)) + +(defun magit-git-failure (&rest args) + "Execute Git with ARGS, returning t if its exit code is 1." + (= (magit-git-exit-code args) 1)) + +(defun magit-git-string-p (&rest args) + "Execute Git with ARGS, returning the first line of its output. +If the exit code isn't zero or if there is no output, then return +nil. Neither of these results is considered an error; if that is +what you want, then use `magit-git-string-ng' instead. + +This is an experimental replacement for `magit-git-string', and +still subject to major changes." + (magit--with-refresh-cache (cons default-directory args) + (with-temp-buffer + (and (zerop (apply #'magit-process-file magit-git-executable nil t nil + (magit-process-git-arguments args))) + (not (bobp)) + (progn + (goto-char (point-min)) + (buffer-substring-no-properties (point) (line-end-position))))))) + +(defun magit-git-string-ng (&rest args) + "Execute Git with ARGS, returning the first line of its output. +If the exit code isn't zero or if there is no output, then that +is considered an error, but instead of actually signaling an +error, return nil. Additionally the output is put in the process +buffer (creating it if necessary) and the error message is shown +in the status buffer (provided it exists). + +This is an experimental replacement for `magit-git-string', and +still subject to major changes. Also see `magit-git-string-p'." + (magit--with-refresh-cache + (list default-directory 'magit-git-string-ng args) + (with-temp-buffer + (let* ((args (magit-process-git-arguments args)) + (status (apply #'magit-process-file magit-git-executable + nil t nil args))) + (if (zerop status) + (and (not (bobp)) + (progn + (goto-char (point-min)) + (buffer-substring-no-properties + (point) (line-end-position)))) + (let ((buf (current-buffer))) + (with-current-buffer (magit-process-buffer t) + (magit-process-insert-section default-directory + magit-git-executable args + status buf))) + (when-let ((status-buf (magit-get-mode-buffer 'magit-status-mode))) + (let ((msg (magit--locate-error-message))) + (with-current-buffer status-buf + (setq magit-this-error msg)))) + nil))))) + +(defun magit-git-str (&rest args) + "Execute Git with ARGS, returning the first line of its output. +If there is no output, return nil. If the output begins with a +newline, return an empty string. Like `magit-git-string' but +ignore `magit-git-debug'." + (setq args (-flatten args)) + (magit--with-refresh-cache (cons default-directory args) + (with-temp-buffer + (apply #'magit-process-file magit-git-executable nil (list t nil) nil + (magit-process-git-arguments args)) + (unless (bobp) + (goto-char (point-min)) + (buffer-substring-no-properties (point) (line-end-position)))))) + +(defun magit-git-output (&rest args) + "Execute Git with ARGS, returning its output." + (setq args (-flatten args)) + (magit--with-refresh-cache (cons default-directory args) + (with-temp-buffer + (apply #'magit-process-file magit-git-executable nil (list t nil) nil + (magit-process-git-arguments args)) + (buffer-substring-no-properties (point-min) (point-max))))) + +(define-error 'magit-invalid-git-boolean "Not a Git boolean") + +(defun magit-git-true (&rest args) + "Execute Git with ARGS, returning t if it prints \"true\". +If it prints \"false\", then return nil. For any other output +signal `magit-invalid-git-boolean'." + (pcase (magit-git-output args) + ((or "true" "true\n") t) + ((or "false" "false\n") nil) + (output (signal 'magit-invalid-git-boolean output)))) + +(defun magit-git-false (&rest args) + "Execute Git with ARGS, returning t if it prints \"false\". +If it prints \"true\", then return nil. For any other output +signal `magit-invalid-git-boolean'." + (pcase (magit-git-output args) + ((or "true" "true\n") nil) + ((or "false" "false\n") t) + (output (signal 'magit-invalid-git-boolean output)))) + +(defun magit-git-insert (&rest args) + "Execute Git with ARGS, inserting its output at point. +If Git exits with a non-zero exit status, then show a message and +add a section in the respective process buffer." + (setq args (magit-process-git-arguments args)) + (if magit-git-debug + (let (log) + (unwind-protect + (progn + (setq log (make-temp-file "magit-stderr")) + (delete-file log) + (let ((exit (apply #'magit-process-file magit-git-executable + nil (list t log) nil args))) + (when (> exit 0) + (let ((msg "Git failed")) + (when (file-exists-p log) + (setq msg (with-temp-buffer + (insert-file-contents log) + (goto-char (point-max)) + (if (functionp magit-git-debug) + (funcall magit-git-debug (buffer-string)) + (magit--locate-error-message)))) + (let ((magit-git-debug nil)) + (with-current-buffer (magit-process-buffer t) + (magit-process-insert-section default-directory + magit-git-executable + args exit log)))) + (message "%s" msg))) + exit)) + (ignore-errors (delete-file log)))) + (apply #'magit-process-file magit-git-executable + nil (list t nil) nil args))) + +(defun magit--locate-error-message () + (goto-char (point-max)) + (and (run-hook-wrapped 'magit-process-error-message-regexps + (lambda (re) (re-search-backward re nil t))) + (match-string-no-properties 1))) + +(defun magit-git-string (&rest args) + "Execute Git with ARGS, returning the first line of its output. +If there is no output, return nil. If the output begins with a +newline, return an empty string." + (setq args (-flatten args)) + (magit--with-refresh-cache (cons default-directory args) + (with-temp-buffer + (apply #'magit-git-insert args) + (unless (bobp) + (goto-char (point-min)) + (buffer-substring-no-properties (point) (line-end-position)))))) + +(defun magit-git-lines (&rest args) + "Execute Git with ARGS, returning its output as a list of lines. +Empty lines anywhere in the output are omitted. + +If Git exits with a non-zero exit status, then report show a +message and add a section in the respective process buffer." + (with-temp-buffer + (apply #'magit-git-insert args) + (split-string (buffer-string) "\n" t))) + +(defun magit-git-items (&rest args) + "Execute Git with ARGS, returning its null-separated output as a list. +Empty items anywhere in the output are omitted. + +If Git exits with a non-zero exit status, then report show a +message and add a section in the respective process buffer." + (with-temp-buffer + (apply #'magit-git-insert args) + (split-string (buffer-string) "\0" t))) + +(defun magit-git-wash (washer &rest args) + "Execute Git with ARGS, inserting washed output at point. +Actually first insert the raw output at point. If there is no +output, call `magit-cancel-section'. Otherwise temporarily narrow +the buffer to the inserted text, move to its beginning, and then +call function WASHER with ARGS as its sole argument." + (declare (indent 1)) + (let ((beg (point))) + (setq args (-flatten args)) + (magit-git-insert args) + (if (= (point) beg) + (magit-cancel-section) + (unless (bolp) + (insert "\n")) + (save-restriction + (narrow-to-region beg (point)) + (goto-char beg) + (funcall washer args)) + (when (or (= (point) beg) + (= (point) (1+ beg))) + (magit-cancel-section)) + (magit-maybe-make-margin-overlay)))) + +(defun magit-git-version (&optional raw) + (--when-let (let (magit-git-global-arguments) + (ignore-errors (substring (magit-git-string "version") 12))) + (if raw it (and (string-match "\\`\\([0-9]+\\(\\.[0-9]+\\)\\{1,2\\}\\)" it) + (match-string 1 it))))) + +;;; Variables + +(defun magit-config-get-from-cached-list (key) + (gethash + ;; `git config --list' downcases first and last components of the key. + (--> key + (replace-regexp-in-string "\\`[^.]+" #'downcase it t t) + (replace-regexp-in-string "[^.]+\\'" #'downcase it t t)) + (magit--with-refresh-cache (cons (magit-toplevel) 'config) + (let ((configs (make-hash-table :test 'equal))) + (dolist (conf (magit-git-items "config" "--list" "-z")) + (let* ((nl-pos (cl-position ?\n conf)) + (key (substring conf 0 nl-pos)) + (val (if nl-pos (substring conf (1+ nl-pos)) ""))) + (puthash key (nconc (gethash key configs) (list val)) configs))) + configs)))) + +(defun magit-get (&rest keys) + "Return the value of the Git variable specified by KEYS." + (car (last (apply 'magit-get-all keys)))) + +(defun magit-get-all (&rest keys) + "Return all values of the Git variable specified by KEYS." + (let ((magit-git-debug nil) + (arg (and (or (null (car keys)) + (string-prefix-p "--" (car keys))) + (pop keys))) + (key (mapconcat 'identity keys "."))) + (if (and magit--refresh-cache (not arg)) + (magit-config-get-from-cached-list key) + (magit-git-items "config" arg "-z" "--get-all" key)))) + +(defun magit-get-boolean (&rest keys) + "Return the boolean value of the Git variable specified by KEYS." + (let ((key (mapconcat 'identity keys "."))) + (if magit--refresh-cache + (equal "true" (car (last (magit-config-get-from-cached-list key)))) + (equal (magit-git-str "config" "--bool" key) "true")))) + +(defun magit-set (value &rest keys) + "Set the value of the Git variable specified by KEYS to VALUE." + (let ((arg (and (or (null (car keys)) + (string-prefix-p "--" (car keys))) + (pop keys))) + (key (mapconcat 'identity keys "."))) + (if value + (magit-git-success "config" arg key value) + (magit-git-success "config" arg "--unset" key)) + value)) + +(gv-define-setter magit-get (val &rest keys) + `(magit-set ,val ,@keys)) + +(defun magit-set-all (values &rest keys) + "Set all values of the Git variable specified by KEYS to VALUES." + (let ((arg (and (or (null (car keys)) + (string-prefix-p "--" (car keys))) + (pop keys))) + (var (mapconcat 'identity keys "."))) + (when (magit-get var) + (magit-call-git "config" arg "--unset-all" var)) + (dolist (v values) + (magit-call-git "config" arg "--add" var v)))) + +;;; Files + +(defun magit--safe-default-directory (&optional file) + (catch 'unsafe-default-dir + (let ((dir (file-name-as-directory + (expand-file-name (or file default-directory)))) + (previous nil)) + (while (not (magit-file-accessible-directory-p dir)) + (setq dir (file-name-directory (directory-file-name dir))) + (when (equal dir previous) + (throw 'unsafe-default-dir nil)) + (setq previous dir)) + dir))) + +(defmacro magit--with-safe-default-directory (file &rest body) + (declare (indent 1) (debug (form body))) + `(when-let ((default-directory (magit--safe-default-directory ,file))) + ,@body)) + +(defun magit-gitdir (&optional directory) + "Return the absolute and resolved path of the .git directory. + +If the `GIT_DIR' environment variable is define then return that. +Otherwise return the .git directory for DIRECTORY, or if that is +nil, then for `default-directory' instead. If the directory is +not located inside a Git repository, then return nil." + (let ((default-directory (or directory default-directory))) + (magit-git-dir))) + +(defun magit-git-dir (&optional path) + "Return the absolute and resolved path of the .git directory. + +If the `GIT_DIR' environment variable is define then return that. +Otherwise return the .git directory for `default-directory'. If +the directory is not located inside a Git repository, then return +nil." + (magit--with-refresh-cache (list default-directory 'magit-git-dir path) + (magit--with-safe-default-directory nil + (when-let ((dir (magit-rev-parse-safe "--git-dir"))) + (setq dir (file-name-as-directory (magit-expand-git-file-name dir))) + (unless (file-remote-p dir) + (setq dir (concat (file-remote-p default-directory) dir))) + (if path (expand-file-name (convert-standard-filename path) dir) dir))))) + +(defvar magit--separated-gitdirs nil) + +(defun magit--record-separated-gitdir () + (let ((topdir (magit-toplevel)) + (gitdir (magit-git-dir))) + ;; Kludge: git-annex converts submodule gitdirs to symlinks. See #3599. + (when (file-symlink-p (directory-file-name gitdir)) + (setq gitdir (file-truename gitdir))) + ;; We want to delete the entry for `topdir' here, rather than within + ;; (unless ...), in case a `--separate-git-dir' repository was switched to + ;; the standard structure (i.e., "topdir/.git/"). + (setq magit--separated-gitdirs (cl-delete topdir + magit--separated-gitdirs + :key #'car :test #'equal)) + (unless (equal (file-name-as-directory (expand-file-name ".git" topdir)) + gitdir) + (push (cons topdir gitdir) magit--separated-gitdirs)))) + +(defun magit-toplevel (&optional directory) + "Return the absolute path to the toplevel of the current repository. + +From within the working tree or control directory of a repository +return the absolute path to the toplevel directory of the working +tree. As a special case, from within a bare repository return +the control directory instead. When called outside a repository +then return nil. + +When optional DIRECTORY is non-nil then return the toplevel for +that directory instead of the one for `default-directory'. + +Try to respect the option `find-file-visit-truename', i.e. when +the value of that option is nil, then avoid needlessly returning +the truename. When a symlink to a sub-directory of the working +tree is involved, or when called from within a sub-directory of +the gitdir or from the toplevel of a gitdir, which itself is not +located within the working tree, then it is not possible to avoid +returning the truename." + (magit--with-refresh-cache + (cons (or directory default-directory) 'magit-toplevel) + (magit--with-safe-default-directory directory + (if-let ((topdir (magit-rev-parse-safe "--show-toplevel"))) + (let (updir) + (setq topdir (magit-expand-git-file-name topdir)) + (if (and + ;; Always honor these settings. + (not find-file-visit-truename) + (not (getenv "GIT_WORK_TREE")) + ;; `--show-cdup' is the relative path to the toplevel + ;; from `(file-truename default-directory)'. Here we + ;; pretend it is relative to `default-directory', and + ;; go to that directory. Then we check whether + ;; `--show-toplevel' still returns the same value and + ;; whether `--show-cdup' now is the empty string. If + ;; both is the case, then we are at the toplevel of + ;; the same working tree, but also avoided needlessly + ;; following any symlinks. + (progn + (setq updir (file-name-as-directory + (magit-rev-parse-safe "--show-cdup"))) + (setq updir (if (file-name-absolute-p updir) + (concat (file-remote-p default-directory) updir) + (expand-file-name updir))) + (let ((default-directory updir)) + (and (string-equal (magit-rev-parse-safe "--show-cdup") "") + (--when-let (magit-rev-parse-safe "--show-toplevel") + (string-equal (magit-expand-git-file-name it) + topdir)))))) + updir + (concat (file-remote-p default-directory) + (file-name-as-directory topdir)))) + (when-let ((gitdir (magit-rev-parse-safe "--git-dir"))) + (setq gitdir (file-name-as-directory + (if (file-name-absolute-p gitdir) + ;; We might have followed a symlink. + (concat (file-remote-p default-directory) + (magit-expand-git-file-name gitdir)) + (expand-file-name gitdir)))) + (if (magit-bare-repo-p) + gitdir + (let* ((link (expand-file-name "gitdir" gitdir)) + (wtree (and (file-exists-p link) + (magit-file-line link)))) + (cond + ((and wtree + ;; Ignore .git/gitdir files that result from a + ;; Git bug. See #2364. + (not (equal wtree ".git"))) + ;; Return the linked working tree. + (file-name-directory wtree)) + ;; The working directory may not be the parent directory of + ;; .git if it was set up with `git init --separate-git-dir'. + ;; See #2955. + ((car (rassoc gitdir magit--separated-gitdirs))) + (t + ;; Step outside the control directory to enter the working tree. + (file-name-directory (directory-file-name gitdir))))))))))) + +(defmacro magit-with-toplevel (&rest body) + (declare (indent defun) (debug (body))) + (let ((toplevel (cl-gensym "toplevel"))) + `(let ((,toplevel (magit-toplevel))) + (if ,toplevel + (let ((default-directory ,toplevel)) + ,@body) + (magit--not-inside-repository-error))))) + +(define-error 'magit-outside-git-repo "Not inside Git repository") +(define-error 'magit-git-executable-not-found + "Git executable cannot be found (see https://magit.vc/goto/e6a78ed2)") + +(defun magit--not-inside-repository-error () + (if (executable-find magit-git-executable) + (signal 'magit-outside-git-repo default-directory) + (signal 'magit-git-executable-not-found magit-git-executable))) + +(defun magit-inside-gitdir-p (&optioal noerror) + "Return t if `default-directory' is below the repository directory. +If it is below the working directory, then return nil. +If it isn't below either, then signal an error unless NOERROR +is non-nil, in which case return nil." + (and (magit--assert-default-directory noerror) + ;; Below a repository directory that is not located below the + ;; working directory "git rev-parse --is-inside-git-dir" prints + ;; "false", which is wrong. + (let ((gitdir (magit-git-dir))) + (cond (gitdir (file-in-directory-p default-directory gitdir)) + (noerror nil) + (t (signal 'magit-outside-git-repo default-directory)))))) + +(defun magit-inside-worktree-p (&optional noerror) + "Return t if `default-directory' is below the working directory. +If it is below the repository directory, then return nil. +If it isn't below either, then signal an error unless NOERROR +is non-nil, in which case return nil." + (and (magit--assert-default-directory noerror) + (condition-case nil + (magit-rev-parse-true "--is-inside-work-tree") + (magit-invalid-git-boolean + (and (not noerror) + (signal 'magit-outside-git-repo default-directory)))))) + +(cl-defgeneric magit-bare-repo-p (&optional noerror) + "Return t if the current repository is bare. +If it is non-bare, then return nil. If `default-directory' +isn't below a Git repository, then signal an error unless +NOERROR is non-nil, in which case return nil." + (and (magit--assert-default-directory noerror) + (condition-case nil + (magit-rev-parse-true "--is-bare-repository") + (magit-invalid-git-boolean + (and (not noerror) + (signal 'magit-outside-git-repo default-directory)))))) + +(defun magit--assert-default-directory (&optional noerror) + (or (file-directory-p default-directory) + (and (not noerror) + (let ((exists (file-exists-p default-directory))) + (signal (if exists 'file-error 'file-missing) + (list "Running git in directory" + (if exists + "Not a directory" + "No such file or directory") + default-directory)))))) + +(defun magit-git-repo-p (directory &optional non-bare) + "Return t if DIRECTORY is a Git repository. +When optional NON-BARE is non-nil also return nil if DIRECTORY is +a bare repository." + (and (file-directory-p directory) ; Avoid archives, see #3397. + (or (file-regular-p (expand-file-name ".git" directory)) + (file-directory-p (expand-file-name ".git" directory)) + (and (not non-bare) + (file-regular-p (expand-file-name "HEAD" directory)) + (file-directory-p (expand-file-name "refs" directory)) + (file-directory-p (expand-file-name "objects" directory)))))) + +(defun magit-file-relative-name (&optional file tracked) + "Return the path of FILE relative to the repository root. + +If optional FILE is nil or omitted, return the relative path of +the file being visited in the current buffer, if any, else nil. +If the file is not inside a Git repository, then return nil. + +If TRACKED is non-nil, return the path only if it matches a +tracked file." + (unless file + (with-current-buffer (or (buffer-base-buffer) + (current-buffer)) + (setq file (or magit-buffer-file-name buffer-file-name + (and (derived-mode-p 'dired-mode) default-directory))))) + (when (and file (or (not tracked) + (magit-file-tracked-p (file-relative-name file)))) + (--when-let (magit-toplevel + (magit--safe-default-directory + (directory-file-name (file-name-directory file)))) + (file-relative-name file it)))) + +(defun magit-file-tracked-p (file) + (magit-git-success "ls-files" "--error-unmatch" file)) + +(defun magit-list-files (&rest args) + (apply #'magit-git-items "ls-files" "-z" "--full-name" args)) + +(defun magit-tracked-files () + (magit-list-files "--cached")) + +(defun magit-untracked-files (&optional all files) + (magit-list-files "--other" (unless all "--exclude-standard") "--" files)) + +(defun magit-unstaged-files (&optional nomodules files) + (magit-git-items "diff-files" "-z" "--name-only" + (and nomodules "--ignore-submodules") + "--" files)) + +(defun magit-staged-files (&optional nomodules files) + (magit-git-items "diff-index" "-z" "--name-only" "--cached" + (and nomodules "--ignore-submodules") + (magit-headish) "--" files)) + +(defun magit-binary-files (&rest args) + (--mapcat (and (string-match "^-\t-\t\\(.+\\)" it) + (list (match-string 1 it))) + (apply #'magit-git-items + "diff" "-z" "--numstat" "--ignore-submodules" + args))) + +(defun magit-unmerged-files () + (magit-git-items "diff-files" "-z" "--name-only" "--diff-filter=U")) + +(defun magit-ignored-files () + (magit-git-items "ls-files" "-z" "--others" "--ignored" + "--exclude-standard" "--directory")) + +(defun magit-skip-worktree-files () + (--keep (and (and (= (aref it 0) ?S) + (substring it 2))) + (magit-list-files "-t"))) + +(defun magit-assume-unchanged-files () + (--keep (and (and (memq (aref it 0) '(?h ?s ?m ?r ?c ?k)) + (substring it 2))) + (magit-list-files "-v"))) + +(defun magit-revision-files (rev) + (magit-with-toplevel + (magit-git-items "ls-tree" "-z" "-r" "--name-only" rev))) + +(defun magit-changed-files (rev-or-range &optional other-rev) + "Return list of files the have changed between two revisions. +If OTHER-REV is non-nil, REV-OR-RANGE should be a revision, not a +range. Otherwise, it can be any revision or range accepted by +\"git diff\" (i.e., , .., or ...)." + (magit-with-toplevel + (magit-git-items "diff" "-z" "--name-only" rev-or-range other-rev))) + +(defun magit-renamed-files (revA revB) + (--map (cons (nth 1 it) (nth 2 it)) + (-partition 3 (magit-git-items + "diff-tree" "-r" "--diff-filter=R" "-z" "-M" + revA revB)))) + +(defun magit-file-status (&rest args) + (with-temp-buffer + (save-excursion (magit-git-insert "status" "-z" args)) + (let ((pos (point)) status) + (while (> (skip-chars-forward "[:print:]") 0) + (let ((x (char-after pos)) + (y (char-after (1+ pos))) + (file (buffer-substring (+ pos 3) (point)))) + (forward-char) + (if (memq x '(?R ?C)) + (progn + (setq pos (point)) + (skip-chars-forward "[:print:]") + (push (list file (buffer-substring pos (point)) x y) status) + (forward-char)) + (push (list file nil x y) status))) + (setq pos (point))) + status))) + +(defcustom magit-cygwin-mount-points + (when (eq system-type 'windows-nt) + (cl-sort (--map (if (string-match "^\\(.*\\) on \\(.*\\) type" it) + (cons (file-name-as-directory (match-string 2 it)) + (file-name-as-directory (match-string 1 it))) + (lwarn '(magit) :error + "Failed to parse Cygwin mount: %S" it)) + ;; If --exec-path is not a native Windows path, + ;; then we probably have a cygwin git. + (let ((process-environment + (append magit-git-environment process-environment))) + (and (not (string-match-p + "\\`[a-zA-Z]:" + (car (process-lines + magit-git-executable "--exec-path")))) + (ignore-errors (process-lines "mount"))))) + #'> :key (pcase-lambda (`(,cyg . ,_win)) (length cyg)))) + "Alist of (CYGWIN . WIN32) directory names. +Sorted from longest to shortest CYGWIN name." + :package-version '(magit . "2.3.0") + :group 'magit-process + :type '(alist :key-type string :value-type directory)) + +(defun magit-expand-git-file-name (filename) + (unless (file-name-absolute-p filename) + (setq filename (expand-file-name filename))) + (-if-let ((cyg . win) + (cl-assoc filename magit-cygwin-mount-points + :test (lambda (f cyg) (string-prefix-p cyg f)))) + (concat win (substring filename (length cyg))) + filename)) + +(defun magit-convert-filename-for-git (filename) + "Convert FILENAME so that it can be passed to git. +1. If it's a remote filename, then remove the remote part. +2. Deal with an `windows-nt' Emacs vs. Cygwin Git incompatibility." + (if (file-name-absolute-p filename) + (-if-let ((cyg . win) + (cl-rassoc filename magit-cygwin-mount-points + :test (lambda (f win) (string-prefix-p win f)))) + (concat cyg (substring filename (length win))) + (or (file-remote-p filename 'localname) + filename)) + filename)) + +(defun magit-decode-git-path (path) + (if (eq (aref path 0) ?\") + (decode-coding-string (read path) + (or magit-git-output-coding-system + (car default-process-coding-system)) + t) + path)) + +(defun magit-file-at-point (&optional expand assert) + (if-let ((file (magit-section-case + (file (oref it value)) + (hunk (magit-section-parent-value it))))) + (if expand + (expand-file-name file (magit-toplevel)) + file) + (when assert + (user-error "No file at point")))) + +(defun magit-current-file () + (or (magit-file-relative-name) + (magit-file-at-point) + (and (derived-mode-p 'magit-log-mode) + (car magit-buffer-log-files)))) + +;;; Predicates + +(defun magit-no-commit-p () + "Return t if there is no commit in the current Git repository." + (not (magit-rev-verify "HEAD"))) + +(defun magit-merge-commit-p (commit) + "Return t if COMMIT is a merge commit." + (> (length (magit-commit-parents commit)) 1)) + +(defun magit-anything-staged-p (&optional ignore-submodules &rest files) + "Return t if there are any staged changes. +If optional FILES is non-nil, then only changes to those files +are considered." + (magit-git-failure "diff" "--quiet" "--cached" + (and ignore-submodules "--ignore-submodules") + "--" files)) + +(defun magit-anything-unstaged-p (&optional ignore-submodules &rest files) + "Return t if there are any unstaged changes. +If optional FILES is non-nil, then only changes to those files +are considered." + (magit-git-failure "diff" "--quiet" + (and ignore-submodules "--ignore-submodules") + "--" files)) + +(defun magit-anything-modified-p (&optional ignore-submodules &rest files) + "Return t if there are any staged or unstaged changes. +If optional FILES is non-nil, then only changes to those files +are considered." + (or (apply 'magit-anything-staged-p ignore-submodules files) + (apply 'magit-anything-unstaged-p ignore-submodules files))) + +(defun magit-anything-unmerged-p (&rest files) + "Return t if there are any merge conflicts. +If optional FILES is non-nil, then only conflicts in those files +are considered." + (and (magit-git-string "ls-files" "--unmerged" files) t)) + +(defun magit-module-worktree-p (module) + (magit-with-toplevel + (file-exists-p (expand-file-name (expand-file-name ".git" module))))) + +(defun magit-module-no-worktree-p (module) + (not (magit-module-worktree-p module))) + +(defun magit-ignore-submodules-p () + (cl-find-if (lambda (arg) + (string-prefix-p "--ignore-submodules" arg)) + magit-buffer-diff-args)) + +;;; Revisions and References + +(defun magit-rev-parse (&rest args) + "Execute `git rev-parse ARGS', returning first line of output. +If there is no output, return nil." + (apply #'magit-git-string "rev-parse" args)) + +(defun magit-rev-parse-safe (&rest args) + "Execute `git rev-parse ARGS', returning first line of output. +If there is no output, return nil. Like `magit-rev-parse' but +ignore `magit-git-debug'." + (apply #'magit-git-str "rev-parse" args)) + +(defun magit-rev-parse-true (&rest args) + "Execute `git rev-parse ARGS', returning t if it prints \"true\". +If it prints \"false\", then return nil. For any other output +signal an error." + (magit-git-true "rev-parse" args)) + +(defun magit-rev-parse-false (&rest args) + "Execute `git rev-parse ARGS', returning t if it prints \"false\". +If it prints \"true\", then return nil. For any other output +signal an error." + (magit-git-false "rev-parse" args)) + +(defun magit-rev-parse-p (&rest args) + "Execute `git rev-parse ARGS', returning t if it prints \"true\". +Return t if the first (and usually only) output line is the +string \"true\", otherwise return nil." + (equal (magit-git-str "rev-parse" args) "true")) + +(defun magit-rev-verify (rev) + (magit-git-string-p "rev-parse" "--verify" rev)) + +(defun magit-commit-p (rev) + "Return full hash for REV if it names an existing commit." + (magit-rev-verify (concat rev "^{commit}"))) + +(defalias 'magit-rev-verify-commit 'magit-commit-p) + +(defalias 'magit-rev-hash 'magit-commit-p) + +(defun magit-rev-equal (a b) + "Return t if there are no differences between the commits A and B." + (magit-git-success "diff" "--quiet" a b)) + +(defun magit-rev-eq (a b) + "Return t if A and B refer to the same commit." + (let ((a (magit-commit-p a)) + (b (magit-commit-p b))) + (and a b (equal a b)))) + +(defun magit-rev-ancestor-p (a b) + "Return non-nil if commit A is an ancestor of commit B." + (magit-git-success "merge-base" "--is-ancestor" a b)) + +(defun magit-rev-head-p (rev) + (or (equal rev "HEAD") + (and rev + (not (string-match-p "\\.\\." rev)) + (equal (magit-rev-parse rev) + (magit-rev-parse "HEAD"))))) + +(defun magit-rev-author-p (rev) + "Return t if the user is the author of REV. +More precisely return t if `user.name' is equal to the author +name of REV and/or `user.email' is equal to the author email +of REV." + (or (equal (magit-get "user.name") (magit-rev-format "%an" rev)) + (equal (magit-get "user.email") (magit-rev-format "%ae" rev)))) + +(defun magit-rev-name (rev &optional pattern not-anchored) + "Return a symbolic name for REV using `git-name-rev'. + +PATTERN can be used to limit the result to a matching ref. +Unless NOT-ANCHORED is non-nil, the beginning of the ref must +match PATTERN. + +An anchored lookup is done using the arguments +\"--exclude=*/ --exclude=*/HEAD\" in addition to +\"--refs=\", provided at least version v2.13 of Git is +used. Older versions did not support the \"--exclude\" argument. +When \"--exclude\" cannot be used and `git-name-rev' returns a +ref that should have been excluded, then that is discarded and +this function returns nil instead. This is unfortunate because +there might be other refs that do match. To fix that, update +Git." + (if (version< (magit-git-version) "2.13") + (when-let + ((ref (magit-git-string "name-rev" "--name-only" "--no-undefined" + (and pattern (concat "--refs=" pattern)) + rev))) + (if (and pattern + (string-match-p "\\`refs/[^/]+/\\*\\'" pattern)) + (let ((namespace (substring pattern 0 -1))) + (and (not (or (string-suffix-p "HEAD" ref) + (and (string-match-p namespace ref) + (not (magit-rev-verify + (concat namespace ref)))))) + ref)) + ref)) + (magit-git-string "name-rev" "--name-only" "--no-undefined" + (and pattern (concat "--refs=" pattern)) + (and pattern + (not not-anchored) + (list "--exclude=*/HEAD" + (concat "--exclude=*/" pattern))) + rev))) + +(defun magit-rev-branch (rev) + (--when-let (magit-rev-name rev "refs/heads/*") + (unless (string-match-p "[~^]" it) it))) + +(defun magit-get-shortname (rev) + (let* ((fn (apply-partially 'magit-rev-name rev)) + (name (or (funcall fn "refs/tags/*") + (funcall fn "refs/heads/*") + (funcall fn "refs/remotes/*")))) + (cond ((not name) + (magit-rev-parse "--short" rev)) + ((string-match "^\\(?:tags\\|remotes\\)/\\(.+\\)" name) + (if (magit-ref-ambiguous-p (match-string 1 name)) + name + (match-string 1 name))) + (t (magit-ref-maybe-qualify name))))) + +(defun magit-name-branch (rev &optional lax) + (or (magit-name-local-branch rev) + (magit-name-remote-branch rev) + (and lax (or (magit-name-local-branch rev t) + (magit-name-remote-branch rev t))))) + +(defun magit-name-local-branch (rev &optional lax) + (--when-let (magit-rev-name rev "refs/heads/*") + (and (or lax (not (string-match-p "[~^]" it))) it))) + +(defun magit-name-remote-branch (rev &optional lax) + (--when-let (magit-rev-name rev "refs/remotes/*") + (and (or lax (not (string-match-p "[~^]" it))) + (substring it 8)))) + +(defun magit-name-tag (rev &optional lax) + (--when-let (magit-rev-name rev "refs/tags/*") + (and (or lax (not (string-match-p "[~^]" it))) + (substring it 5)))) + +(defun magit-ref-abbrev (refname) + "Return an unambiguous abbreviation of REFNAME." + (magit-rev-parse "--verify" "--abbrev-ref" refname)) + +(defun magit-ref-fullname (refname) + "Return fully qualified refname for REFNAME. +If REFNAME is ambiguous, return nil." + (magit-rev-parse "--verify" "--symbolic-full-name" refname)) + +(defun magit-ref-ambiguous-p (refname) + (save-match-data + (if (string-match "\\`\\([^^~]+\\)\\(.*\\)" refname) + (not (magit-ref-fullname (match-string 1 refname))) + (error "%S has an unrecognized format" refname)))) + +(defun magit-ref-maybe-qualify (refname &optional prefix) + "If REFNAME is ambiguous, try to disambiguate it by prepend PREFIX to it. +Return an unambiguous refname, either REFNAME or that prefixed +with PREFIX, nil otherwise. If REFNAME has an offset suffix +such as \"~1\", then that is preserved. If optional PREFIX is +nil, then use \"heads/\". " + (if (magit-ref-ambiguous-p refname) + (let ((refname (concat (or prefix "heads/") refname))) + (and (not (magit-ref-ambiguous-p refname)) refname)) + refname)) + +(defun magit-ref-exists-p (ref) + (magit-git-success "show-ref" "--verify" ref)) + +(defun magit-ref-equal (a b) + "Return t if the refnames A and B are `equal'. +A symbolic-ref pointing to some ref, is `equal' to that ref, +as are two symbolic-refs pointing to the same ref. Refnames +may be abbreviated." + (let ((a (magit-ref-fullname a)) + (b (magit-ref-fullname b))) + (and a b (equal a b)))) + +(defun magit-ref-eq (a b) + "Return t if the refnames A and B are `eq'. +A symbolic-ref is `eq' to itself, but not to the ref it points +to, or to some other symbolic-ref that points to the same ref." + (let ((symbolic-a (magit-symbolic-ref-p a)) + (symbolic-b (magit-symbolic-ref-p b))) + (or (and symbolic-a + symbolic-b + (equal a b)) + (and (not symbolic-a) + (not symbolic-b) + (magit-ref-equal a b))))) + +(defun magit-headish () + "Return \"HEAD\" or if that doesn't exist the hash of the empty tree." + (if (magit-no-commit-p) + (magit-git-string "mktree") + "HEAD")) + +(defun magit-branch-at-point () + (magit-section-case + (branch (oref it value)) + (commit (or (magit--painted-branch-at-point) + (magit-name-branch (oref it value)))))) + +(defun magit--painted-branch-at-point (&optional type) + (or (and (not (eq type 'remote)) + (memq (get-text-property (point) 'font-lock-face) + (list 'magit-branch-local + 'magit-branch-current)) + (when-let ((branch (thing-at-point 'git-revision t))) + (cdr (magit-split-branch-name branch)))) + (and (not (eq type 'local)) + (memq (get-text-property (point) 'font-lock-face) + (list 'magit-branch-remote + 'magit-branch-remote-head)) + (thing-at-point 'git-revision t)))) + +(defun magit-local-branch-at-point () + (magit-section-case + (branch (let ((branch (magit-ref-maybe-qualify (oref it value)))) + (when (member branch (magit-list-local-branch-names)) + branch))) + (commit (or (magit--painted-branch-at-point 'local) + (magit-name-local-branch (oref it value)))))) + +(defun magit-remote-branch-at-point () + (magit-section-case + (branch (let ((branch (oref it value))) + (when (member branch (magit-list-remote-branch-names)) + branch))) + (commit (or (magit--painted-branch-at-point 'remote) + (magit-name-remote-branch (oref it value)))))) + +(defun magit-commit-at-point () + (or (magit-section-value-if 'commit) + (and (derived-mode-p 'magit-stash-mode + 'magit-merge-preview-mode + 'magit-revision-mode) + magit-buffer-revision))) + +(defun magit-branch-or-commit-at-point () + (or (and magit-buffer-file-name + magit-buffer-refname) + (magit-section-case + (branch (magit-ref-maybe-qualify (oref it value))) + (commit (or (magit--painted-branch-at-point) + (let ((rev (oref it value))) + (or (magit-name-branch rev) rev)))) + (tag (magit-ref-maybe-qualify (oref it value) "tags/")) + (pullreq (or (and (fboundp 'forge--pullreq-branch) + (magit-branch-p + (forge--pullreq-branch (oref it value)))) + (magit-ref-p (format "refs/pullreqs/%s" + (oref (oref it value) number)))))) + (thing-at-point 'git-revision t) + (and (derived-mode-p 'magit-stash-mode + 'magit-merge-preview-mode + 'magit-revision-mode) + magit-buffer-revision))) + +(defun magit-tag-at-point () + (magit-section-case + (tag (oref it value)) + (commit (magit-name-tag (oref it value))))) + +(defun magit-stash-at-point () + (magit-section-value-if 'stash)) + +(defun magit-remote-at-point () + (magit-section-case + (remote (oref it value)) + (branch (magit-section-parent-value it)))) + +(defun magit-module-at-point (&optional predicate) + (when (magit-section-match 'magit-module-section) + (let ((module (oref (magit-current-section) value))) + (and (or (not predicate) + (funcall predicate module)) + module)))) + +(defun magit-get-current-branch () + "Return the refname of the currently checked out branch. +Return nil if no branch is currently checked out." + (magit-git-string "symbolic-ref" "--short" "HEAD")) + +(defvar magit-get-previous-branch-timeout 0.5 + "Maximum time to spend in `magit-get-previous-branch'. +Given as a number of seconds.") + +(defun magit-get-previous-branch () + "Return the refname of the previously checked out branch. +Return nil if no branch can be found in the `HEAD' reflog +which is different from the current branch and still exists. +The amount of time spent searching is limited by +`magit-get-previous-branch-timeout'." + (let ((t0 (float-time)) + (current (magit-get-current-branch)) + (i 1) prev) + (while (if (> (- (float-time) t0) magit-get-previous-branch-timeout) + (setq prev nil) ;; Timed out. + (and (setq prev (magit-rev-verify (format "@{-%i}" i))) + (or (not (setq prev (magit-rev-branch prev))) + (equal prev current)))) + (cl-incf i)) + prev)) + +(defun magit-set-upstream-branch (branch upstream) + "Set UPSTREAM as the upstream of BRANCH. +If UPSTREAM is nil, then unset BRANCH's upstream. +Otherwise UPSTREAM has to be an existing branch." + (if upstream + (magit-call-git "branch" "--set-upstream-to" upstream branch) + (magit-call-git "branch" "--unset-upstream" branch))) + +(defun magit-get-upstream-ref (&optional branch) + "Return the upstream branch of BRANCH as a fully qualified ref. +It BRANCH is nil, then return the upstream of the current branch, +if any, nil otherwise. If the upstream is not configured, the +configured remote is an url, or the named branch does not exist, +then return nil. I.e. return an existing local or +remote-tracking branch ref." + (when-let ((branch (or branch (magit-get-current-branch)))) + (magit-ref-fullname (concat branch "@{upstream}")))) + +(defun magit-get-upstream-branch (&optional branch) + "Return the name of the upstream branch of BRANCH. +It BRANCH is nil, then return the upstream of the current branch +if any, nil otherwise. If the upstream is not configured, the +configured remote is an url, or the named branch does not exist, +then return nil. I.e. return the name of an existing local or +remote-tracking branch. The returned string is colorized +according to the branch type." + (when-let ((branch (or branch (magit-get-current-branch))) + (upstream (magit-ref-abbrev (concat branch "@{upstream}")))) + (magit--propertize-face + upstream (if (equal (magit-get "branch" branch "remote") ".") + 'magit-branch-local + 'magit-branch-remote)))) + +(defun magit-get-indirect-upstream-branch (branch &optional force) + (let ((remote (magit-get "branch" branch "remote"))) + (and remote (not (equal remote ".")) + ;; The user has opted in... + (or force + (--some (if (magit-git-success "check-ref-format" "--branch" it) + (equal it branch) + (string-match-p it branch)) + magit-branch-prefer-remote-upstream)) + ;; and local BRANCH tracks a remote branch... + (let ((upstream (magit-get-upstream-branch branch))) + ;; whose upstream... + (and upstream + ;; has the same name as BRANCH... + (equal (substring upstream (1+ (length remote))) branch) + ;; and can be fast-forwarded to BRANCH. + (magit-rev-ancestor-p upstream branch) + upstream))))) + +(defun magit-get-upstream-remote (&optional branch allow-unnamed) + (when-let ((branch (or branch (magit-get-current-branch))) + (remote (magit-get "branch" branch "remote"))) + (and (not (equal remote ".")) + (cond ((member remote (magit-list-remotes)) + (magit--propertize-face remote 'magit-branch-remote)) + ((and allow-unnamed + (string-match-p "\\(\\`.\\{0,2\\}/\\|[:@]\\)" remote)) + (magit--propertize-face remote 'bold)))))) + +(defun magit-get-unnamed-upstream (&optional branch) + (when-let ((branch (or branch (magit-get-current-branch))) + (remote (magit-get "branch" branch "remote")) + (merge (magit-get "branch" branch "merge"))) + (and (magit--unnamed-upstream-p remote merge) + (list (magit--propertize-face remote 'bold) + (magit--propertize-face merge 'magit-branch-remote))))) + +(defun magit--unnamed-upstream-p (remote merge) + (and remote (string-match-p "\\(\\`\\.\\{0,2\\}/\\|[:@]\\)" remote) + merge (string-prefix-p "refs/" merge))) + +(defun magit--valid-upstream-p (remote merge) + (and (or (equal remote ".") + (member remote (magit-list-remotes))) + (string-prefix-p "refs/" merge))) + +(defun magit-get-current-remote (&optional allow-unnamed) + (or (magit-get-upstream-remote nil allow-unnamed) + (when-let ((remotes (magit-list-remotes)) + (remote (if (= (length remotes) 1) + (car remotes) + (car (member "origin" remotes))))) + (magit--propertize-face remote 'magit-branch-remote)))) + +(defun magit-get-push-remote (&optional branch) + (when-let ((remote + (or (and (or branch (setq branch (magit-get-current-branch))) + (magit-get "branch" branch "pushRemote")) + (magit-get "remote.pushDefault")))) + (magit--propertize-face remote 'magit-branch-remote))) + +(defun magit-get-push-branch (&optional branch verify) + (when-let ((branch (or branch (setq branch (magit-get-current-branch)))) + (remote (magit-get-push-remote branch)) + (target (concat remote "/" branch))) + (and (or (not verify) + (magit-rev-verify target)) + (magit--propertize-face target 'magit-branch-remote)))) + +(defun magit-get-@{push}-branch (&optional branch) + (let ((ref (magit-rev-parse "--symbolic-full-name" + (concat branch "@{push}")))) + (when (and ref (string-prefix-p "refs/remotes/" ref)) + (substring ref 13)))) + +(defun magit-get-remote (&optional branch) + (when (or branch (setq branch (magit-get-current-branch))) + (let ((remote (magit-get "branch" branch "remote"))) + (unless (equal remote ".") + remote)))) + +(defun magit-get-some-remote (&optional branch) + (or (magit-get-remote branch) + (and (magit-branch-p "master") + (magit-get-remote "master")) + (let ((remotes (magit-list-remotes))) + (or (car (member "origin" remotes)) + (car remotes))))) + +(defun magit-branch-merged-p (branch &optional target) + "Return non-nil if BRANCH is merged into its upstream and TARGET. + +TARGET defaults to the current branch. If `HEAD' is detached and +TARGET is nil, then always return nil. As a special case, if +TARGET is t, then return non-nil if BRANCH is merged into any one +of the other local branches. + +If, and only if, BRANCH has an upstream, then only return non-nil +if BRANCH is merged into both TARGET (as described above) as well +as into its upstream." + (and (--if-let (and (magit-branch-p branch) + (magit-get-upstream-branch branch)) + (magit-git-success "merge-base" "--is-ancestor" branch it) + t) + (if (eq target t) + (delete (magit-name-local-branch branch) + (magit-list-containing-branches branch)) + (--when-let (or target (magit-get-current-branch)) + (magit-git-success "merge-base" "--is-ancestor" branch it))))) + +(defun magit-get-tracked (refname) + "Return the remote branch tracked by the remote-tracking branch REFNAME. +The returned value has the form (REMOTE . REF), where REMOTE is +the name of a remote and REF is the ref local to the remote." + (when-let ((ref (magit-ref-fullname refname))) + (save-match-data + (-some (lambda (line) + (and (string-match "\ +\\`remote\\.\\([^.]+\\)\\.fetch=\\+?\\([^:]+\\):\\(.+\\)" line) + (let ((rmt (match-string 1 line)) + (src (match-string 2 line)) + (dst (match-string 3 line))) + (and (string-match (format "\\`%s\\'" + (replace-regexp-in-string + "*" "\\(.+\\)" dst t t)) + ref) + (cons rmt (replace-regexp-in-string + "*" (match-string 1 ref) src)))))) + (magit-git-lines "config" "--local" "--list"))))) + +(defun magit-split-branch-name (branch) + (cond ((member branch (magit-list-local-branch-names)) + (cons "." branch)) + ((string-match "/" branch) + (or (-some (lambda (remote) + (and (string-match (format "\\`\\(%s\\)/\\(.+\\)\\'" remote) + branch) + (cons (match-string 1 branch) + (match-string 2 branch)))) + (magit-list-remotes)) + (error "Invalid branch name %s" branch))))) + +(defun magit-get-current-tag (&optional rev with-distance) + "Return the closest tag reachable from REV. + +If optional REV is nil, then default to `HEAD'. +If optional WITH-DISTANCE is non-nil then return (TAG COMMITS), +if it is `dirty' return (TAG COMMIT DIRTY). COMMITS is the number +of commits in `HEAD' but not in TAG and DIRTY is t if there are +uncommitted changes, nil otherwise." + (--when-let (magit-git-str "describe" "--long" "--tags" + (and (eq with-distance 'dirty) "--dirty") rev) + (save-match-data + (string-match + "\\(.+\\)-\\(?:0[0-9]*\\|\\([0-9]+\\)\\)-g[0-9a-z]+\\(-dirty\\)?$" it) + (if with-distance + `(,(match-string 1 it) + ,(string-to-number (or (match-string 2 it) "0")) + ,@(and (match-string 3 it) (list t))) + (match-string 1 it))))) + +(defun magit-get-next-tag (&optional rev with-distance) + "Return the closest tag from which REV is reachable. + +If optional REV is nil, then default to `HEAD'. +If no such tag can be found or if the distance is 0 (in which +case it is the current tag, not the next), return nil instead. +If optional WITH-DISTANCE is non-nil, then return (TAG COMMITS) +where COMMITS is the number of commits in TAG but not in REV." + (--when-let (magit-git-str "describe" "--contains" (or rev "HEAD")) + (save-match-data + (when (string-match "^[^^~]+" it) + (setq it (match-string 0 it)) + (unless (equal it (magit-get-current-tag rev)) + (if with-distance + (list it (car (magit-rev-diff-count it rev))) + it)))))) + +(defvar magit-list-refs-namespaces + '("refs/heads" "refs/remotes" "refs/tags" "refs/pull")) + +(defun magit-list-refs (&optional namespaces format sortby) + "Return list of references. + +When NAMESPACES is non-nil, list refs from these namespaces +rather than those from `magit-list-refs-namespaces'. + +FORMAT is passed to the `--format' flag of `git for-each-ref' +and defaults to \"%(refname)\". If the format is \"%(refname)\" +or \"%(refname:short)\", then drop the symbolic-ref \"HEAD\". + +SORTBY is a key or list of keys to pass to the `--sort' flag of +`git for-each-ref'. When nil, use `magit-list-refs-sortby'" + (unless format + (setq format "%(refname)")) + (let ((refs (magit-git-lines "for-each-ref" + (concat "--format=" format) + (--map (concat "--sort=" it) + (pcase (or sortby magit-list-refs-sortby) + ((and val (pred stringp)) (list val)) + ((and val (pred listp)) val))) + (or namespaces magit-list-refs-namespaces)))) + (if (member format '("%(refname)" "%(refname:short)")) + (--remove (string-match-p "\\(\\`\\|/\\)HEAD\\'" it) refs) + refs))) + +(defun magit-list-branches () + (magit-list-refs (list "refs/heads" "refs/remotes"))) + +(defun magit-list-local-branches () + (magit-list-refs "refs/heads")) + +(defun magit-list-remote-branches (&optional remote) + (magit-list-refs (concat "refs/remotes/" remote))) + +(defun magit-list-related-branches (relation &optional commit &rest args) + (--remove (string-match-p "\\(\\`(HEAD\\|HEAD -> \\)" it) + (--map (substring it 2) + (magit-git-lines "branch" args relation commit)))) + +(defun magit-list-containing-branches (&optional commit &rest args) + (magit-list-related-branches "--contains" commit args)) + +(defun magit-list-publishing-branches (&optional commit) + (--filter (magit-rev-ancestor-p commit it) + magit-published-branches)) + +(defun magit-list-merged-branches (&optional commit &rest args) + (magit-list-related-branches "--merged" commit args)) + +(defun magit-list-unmerged-branches (&optional commit &rest args) + (magit-list-related-branches "--no-merged" commit args)) + +(defun magit-list-unmerged-to-upstream-branches () + (--filter (when-let ((upstream (magit-get-upstream-branch it))) + (member it (magit-list-unmerged-branches upstream))) + (magit-list-local-branch-names))) + +(defun magit-list-branches-pointing-at (commit) + (let ((re (format "\\`%s refs/\\(heads\\|remotes\\)/\\(.*\\)\\'" + (magit-rev-verify commit)))) + (--keep (and (string-match re it) + (let ((name (match-string 2 it))) + (and (not (string-suffix-p "HEAD" name)) + name))) + (magit-git-lines "show-ref")))) + +(defun magit-list-refnames (&optional namespaces include-special) + (nconc (magit-list-refs namespaces "%(refname:short)") + (and include-special + (magit-list-special-refnames)))) + +(defvar magit-special-refnames + '("HEAD" "ORIG_HEAD" "FETCH_HEAD" "MERGE_HEAD" "CHERRY_PICK_HEAD")) + +(defun magit-list-special-refnames () + (let ((gitdir (magit-gitdir))) + (cl-mapcan (lambda (name) + (and (file-exists-p (expand-file-name name gitdir)) + (list name))) + magit-special-refnames))) + +(defun magit-list-branch-names () + (magit-list-refnames (list "refs/heads" "refs/remotes"))) + +(defun magit-list-local-branch-names () + (magit-list-refnames "refs/heads")) + +(defun magit-list-remote-branch-names (&optional remote relative) + (if (and remote relative) + (let ((regexp (format "^refs/remotes/%s/\\(.+\\)" remote))) + (--mapcat (when (string-match regexp it) + (list (match-string 1 it))) + (magit-list-remote-branches remote))) + (magit-list-refnames (concat "refs/remotes/" remote)))) + +(defun magit-format-refs (format &rest args) + (let ((lines (magit-git-lines + "for-each-ref" (concat "--format=" format) + (or args (list "refs/heads" "refs/remotes" "refs/tags"))))) + (if (string-match-p "\f" format) + (--map (split-string it "\f") lines) + lines))) + +(defun magit-list-remotes () + (magit-git-lines "remote")) + +(defun magit-list-tags () + (magit-git-lines "tag")) + +(defun magit-list-stashes (&optional format) + (magit-git-lines "stash" "list" (concat "--format=" (or format "%gd")))) + +(defun magit-list-active-notes-refs () + "Return notes refs according to `core.notesRef' and `notes.displayRef'." + (magit-git-lines "for-each-ref" "--format=%(refname)" + (or (magit-get "core.notesRef") "refs/notes/commits") + (magit-get-all "notes.displayRef"))) + +(defun magit-list-notes-refnames () + (--map (substring it 6) (magit-list-refnames "refs/notes"))) + +(defun magit-remote-list-tags (remote) + (--keep (and (not (string-match-p "\\^{}$" it)) + (substring it 51)) + (magit-git-lines "ls-remote" "--tags" remote))) + +(defun magit-remote-list-branches (remote) + (--keep (and (not (string-match-p "\\^{}$" it)) + (substring it 52)) + (magit-git-lines "ls-remote" "--heads" remote))) + +(defun magit-remote-list-refs (remote) + (--keep (and (not (string-match-p "\\^{}$" it)) + (substring it 41)) + (magit-git-lines "ls-remote" remote))) + +(defun magit-list-module-paths () + (--mapcat (and (string-match "^160000 [0-9a-z]\\{40\\} 0\t\\(.+\\)$" it) + (list (match-string 1 it))) + (magit-git-items "ls-files" "-z" "--stage"))) + +(defun magit-get-submodule-name (path) + "Return the name of the submodule at PATH. +PATH has to be relative to the super-repository." + (cadr (split-string + (car (or (magit-git-items + "config" "-z" + "-f" (expand-file-name ".gitmodules" (magit-toplevel)) + "--get-regexp" "^submodule\\..*\\.path$" + (concat "^" (regexp-quote (directory-file-name path)) "$")) + (error "No such submodule `%s'" path))) + "\n"))) + +(defun magit-list-worktrees () + (let (worktrees worktree) + (dolist (line (let ((magit-git-global-arguments + ;; KLUDGE At least in v2.8.3 this triggers a segfault. + (remove "--no-pager" magit-git-global-arguments))) + (magit-git-lines "worktree" "list" "--porcelain"))) + (cond ((string-prefix-p "worktree" line) + (push (setq worktree (list (substring line 9) nil nil nil)) + worktrees)) + ((string-equal line "bare") + (let* ((default-directory (car worktree)) + (wt (and (not (magit-get-boolean "core.bare")) + (magit-get "core.worktree")))) + (if (and wt (file-exists-p (expand-file-name wt))) + (progn (setf (nth 0 worktree) (expand-file-name wt)) + (setf (nth 2 worktree) (magit-rev-parse "HEAD")) + (setf (nth 3 worktree) (magit-get-current-branch))) + (setf (nth 1 worktree) t)))) + ((string-prefix-p "HEAD" line) + (setf (nth 2 worktree) (substring line 5))) + ((string-prefix-p "branch" line) + (setf (nth 3 worktree) (substring line 18))) + ((string-equal line "detached")))) + (nreverse worktrees))) + +(defun magit-symbolic-ref-p (name) + (magit-git-success "symbolic-ref" "--quiet" name)) + +(defun magit-ref-p (rev) + (or (car (member rev (magit-list-refs "refs/"))) + (car (member rev (magit-list-refnames "refs/"))))) + +(defun magit-branch-p (rev) + (or (car (member rev (magit-list-branches))) + (car (member rev (magit-list-branch-names))))) + +(defun magit-local-branch-p (rev) + (or (car (member rev (magit-list-local-branches))) + (car (member rev (magit-list-local-branch-names))))) + +(defun magit-remote-branch-p (rev) + (or (car (member rev (magit-list-remote-branches))) + (car (member rev (magit-list-remote-branch-names))))) + +(defun magit-branch-set-face (branch) + (magit--propertize-face branch (if (magit-local-branch-p branch) + 'magit-branch-local + 'magit-branch-remote))) + +(defun magit-tag-p (rev) + (car (member rev (magit-list-tags)))) + +(defun magit-remote-p (string) + (car (member string (magit-list-remotes)))) + +(defun magit-rev-diff-count (a b) + "Return the commits in A but not B and vice versa. +Return a list of two integers: (A>B B>A)." + (mapcar 'string-to-number + (split-string (magit-git-string "rev-list" + "--count" "--left-right" + (concat a "..." b)) + "\t"))) + +(defun magit-abbrev-length () + (--if-let (magit-get "core.abbrev") + (string-to-number it) + ;; Guess the length git will be using based on an example + ;; abbreviation. Actually HEAD's abbreviation might be an + ;; outlier, so use the shorter of the abbreviations for two + ;; commits. When a commit does not exist, then fall back + ;; to the default of 7. See #3034. + (min (--if-let (magit-rev-parse "--short" "HEAD") (length it) 7) + (--if-let (magit-rev-parse "--short" "HEAD~") (length it) 7)))) + +(defun magit-abbrev-arg (&optional arg) + (format "--%s=%d" (or arg "abbrev") (magit-abbrev-length))) + +(defun magit-rev-abbrev (rev) + (magit-rev-parse (magit-abbrev-arg "short") rev)) + +(defun magit-commit-children (commit &optional args) + (mapcar #'car + (--filter (member commit (cdr it)) + (--map (split-string it " ") + (magit-git-lines + "log" "--format=%H %P" + (or args (list "--branches" "--tags" "--remotes")) + "--not" commit))))) + +(defun magit-commit-parents (commit) + (--when-let (magit-git-string "rev-list" "-1" "--parents" commit) + (cdr (split-string it)))) + +(defun magit-patch-id (rev) + (with-temp-buffer + (magit-process-file + shell-file-name nil '(t nil) nil shell-command-switch + (let ((exec (shell-quote-argument magit-git-executable))) + (format "%s diff-tree -u %s | %s patch-id" exec rev exec))) + (car (split-string (buffer-string))))) + +(defun magit-rev-format (format &optional rev args) + (let ((str (magit-git-string "show" "--no-patch" + (concat "--format=" format) args + (if rev (concat rev "^{commit}") "HEAD") "--"))) + (unless (string-equal str "") + str))) + +(defun magit-rev-insert-format (format &optional rev args) + (magit-git-insert "show" "--no-patch" + (concat "--format=" format) args + (if rev (concat rev "^{commit}") "HEAD") "--")) + +(defun magit-format-rev-summary (rev) + (--when-let (magit-rev-format "%h %s" rev) + (string-match " " it) + (magit--put-face 0 (match-beginning 0) 'magit-hash it) + it)) + +(defvar magit-ref-namespaces + '(("\\`HEAD\\'" . magit-head) + ("\\`refs/tags/\\(.+\\)" . magit-tag) + ("\\`refs/heads/\\(.+\\)" . magit-branch-local) + ("\\`refs/remotes/\\(.+\\)" . magit-branch-remote) + ("\\`refs/bisect/\\(bad\\)" . magit-bisect-bad) + ("\\`refs/bisect/\\(skip.*\\)" . magit-bisect-skip) + ("\\`refs/bisect/\\(good.*\\)" . magit-bisect-good) + ("\\`refs/stash$" . magit-refname-stash) + ("\\`refs/wip/\\(.+\\)" . magit-refname-wip) + ("\\`refs/pullreqs/\\(.+\\)" . magit-refname-pullreq) + ("\\`\\(bad\\):" . magit-bisect-bad) + ("\\`\\(skip\\):" . magit-bisect-skip) + ("\\`\\(good\\):" . magit-bisect-good) + ("\\`\\(.+\\)" . magit-refname)) + "How refs are formatted for display. + +Each entry controls how a certain type of ref is displayed, and +has the form (REGEXP . FACE). REGEXP is a regular expression +used to match full refs. The first entry whose REGEXP matches +the reference is used. + +In log and revision buffers the first regexp submatch becomes the +\"label\" that represents the ref and is propertized with FONT. +In refs buffers the displayed text is controlled by other means +and this option only controls what face is used.") + +(defun magit-format-ref-labels (string) + (save-match-data + (let ((regexp "\\(, \\|tag: \\|HEAD -> \\)") + names) + (if (and (derived-mode-p 'magit-log-mode) + (member "--simplify-by-decoration" magit-buffer-log-args)) + (let ((branches (magit-list-local-branch-names)) + (re (format "^%s/.+" (regexp-opt (magit-list-remotes))))) + (setq names + (--map (cond ((string-equal it "HEAD") it) + ((string-prefix-p "refs/" it) it) + ((member it branches) (concat "refs/heads/" it)) + ((string-match re it) (concat "refs/remotes/" it)) + (t (concat "refs/" it))) + (split-string + (replace-regexp-in-string "tag: " "refs/tags/" string) + regexp t)))) + (setq names (split-string string regexp t))) + (let (state head upstream tags branches remotes other combined) + (dolist (ref names) + (let* ((face (cdr (--first (string-match (car it) ref) + magit-ref-namespaces))) + (name (magit--propertize-face + (or (match-string 1 ref) ref) face))) + (cl-case face + ((magit-bisect-bad magit-bisect-skip magit-bisect-good) + (setq state name)) + (magit-head + (setq head (magit--propertize-face "@" 'magit-head))) + (magit-tag (push name tags)) + (magit-branch-local (push name branches)) + (magit-branch-remote (push name remotes)) + (t (push name other))))) + (setq remotes + (-keep + (lambda (name) + (if (string-match "\\`\\([^/]*\\)/\\(.*\\)\\'" name) + (let ((r (match-string 1 name)) + (b (match-string 2 name))) + (and (not (equal b "HEAD")) + (if (equal (concat "refs/remotes/" name) + (magit-git-string + "symbolic-ref" + (format "refs/remotes/%s/HEAD" r))) + (magit--propertize-face + name 'magit-branch-remote-head) + name))) + name)) + remotes)) + (let* ((current (magit-get-current-branch)) + (target (magit-get-upstream-branch current))) + (dolist (name branches) + (let ((push (car (member (magit-get-push-branch name) remotes)))) + (when push + (setq remotes (delete push remotes)) + (string-match "^[^/]*/" push) + (setq push (substring push 0 (match-end 0)))) + (cond + ((equal name current) + (setq head + (concat push + (magit--propertize-face + name 'magit-branch-current)))) + ((equal name target) + (setq upstream + (concat push + (magit--propertize-face + name '(magit-branch-upstream + magit-branch-local))))) + (t + (push (concat push name) combined))))) + (when (and target (not upstream)) + (if (member target remotes) + (progn + (magit--add-face-text-property + 0 (length target) 'magit-branch-upstream nil target) + (setq upstream target) + (setq remotes (delete target remotes))) + (when-let ((target (car (member target combined)))) + (magit--add-face-text-property + 0 (length target) 'magit-branch-upstream nil target) + (setq upstream target) + (setq combined (delete target combined)))))) + (mapconcat #'identity + (-flatten `(,state + ,head + ,upstream + ,@(nreverse tags) + ,@(nreverse combined) + ,@(nreverse remotes) + ,@other)) + " "))))) + +(defun magit-object-type (object) + (magit-git-string "cat-file" "-t" object)) + +(defmacro magit-with-blob (commit file &rest body) + (declare (indent 2) + (debug (form form body))) + `(with-temp-buffer + (let ((buffer-file-name ,file)) + (save-excursion + (magit-git-insert "cat-file" "-p" + (concat ,commit ":" buffer-file-name))) + (decode-coding-inserted-region + (point-min) (point-max) buffer-file-name t nil nil t) + ,@body))) + +(defmacro magit-with-temp-index (tree arg &rest body) + (declare (indent 2) (debug (form form body))) + (let ((file (cl-gensym "file"))) + `(let ((magit--refresh-cache nil) + (,file (magit-convert-filename-for-git + (make-temp-name (magit-git-dir "index.magit."))))) + (unwind-protect + (magit-with-toplevel + (--when-let ,tree + (or (magit-git-success "read-tree" ,arg it + (concat "--index-output=" ,file)) + (error "Cannot read tree %s" it))) + (if (file-remote-p default-directory) + (let ((magit-tramp-process-environment + (cons (concat "GIT_INDEX_FILE=" ,file) + magit-tramp-process-environment))) + ,@body) + (let ((process-environment + (cons (concat "GIT_INDEX_FILE=" ,file) + process-environment))) + ,@body))) + (ignore-errors + (delete-file (concat (file-remote-p default-directory) ,file))))))) + +(defun magit-commit-tree (message &optional tree &rest parents) + (magit-git-string "commit-tree" "--no-gpg-sign" "-m" message + (--mapcat (list "-p" it) (delq nil parents)) + (or tree + (magit-git-string "write-tree") + (error "Cannot write tree")))) + +(defun magit-commit-worktree (message &optional arg &rest other-parents) + (magit-with-temp-index "HEAD" arg + (and (magit-update-files (magit-unstaged-files)) + (apply #'magit-commit-tree message nil "HEAD" other-parents)))) + +(defun magit-update-files (files) + (magit-git-success "update-index" "--add" "--remove" "--" files)) + +(defun magit-update-ref (ref message rev &optional stashish) + (let ((magit--refresh-cache nil)) + (or (if (not (version< (magit-git-version) "2.6.0")) + (zerop (magit-call-git "update-ref" "--create-reflog" + "-m" message ref rev + (or (magit-rev-verify ref) ""))) + ;; `--create-reflog' didn't exist before v2.6.0 + (let ((oldrev (magit-rev-verify ref)) + (logfile (magit-git-dir (concat "logs/" ref)))) + (unless (file-exists-p logfile) + (when oldrev + (magit-git-success "update-ref" "-d" ref oldrev)) + (make-directory (file-name-directory logfile) t) + (with-temp-file logfile) + (when (and oldrev (not stashish)) + (magit-git-success "update-ref" "-m" "enable reflog" + ref oldrev "")))) + (magit-git-success "update-ref" "-m" message ref rev + (or (magit-rev-verify ref) ""))) + (error "Cannot update %s with %s" ref rev)))) + +(defconst magit-range-re + (concat "\\`\\([^ \t]*[^.]\\)?" ; revA + "\\(\\.\\.\\.?\\)" ; range marker + "\\([^.][^ \t]*\\)?\\'")) ; revB + +(defun magit-split-range (range) + (and (string-match magit-range-re range) + (let ((beg (or (match-string 1 range) "HEAD")) + (end (or (match-string 3 range) "HEAD"))) + (cons (if (string-equal (match-string 2 range) "...") + (magit-git-string "merge-base" beg end) + beg) + end)))) + +(defun magit-hash-range (range) + (if (string-match magit-range-re range) + (concat (magit-rev-hash (match-string 1 range)) + (match-string 2 range) + (magit-rev-hash (match-string 3 range))) + (magit-rev-hash range))) + +(put 'git-revision 'thing-at-point 'magit-thingatpt--git-revision) +(defun magit-thingatpt--git-revision () + (--when-let + (let ((c "\s\n\t~^:?*[\\")) + (cl-letf (((get 'git-revision 'beginning-op) + (if (re-search-backward (format "[%s]" c) nil t) + (forward-char) + (goto-char (point-min)))) + ((get 'git-revision 'end-op) + (lambda () + (re-search-forward (format "\\=[^%s]*" c) nil t)))) + (bounds-of-thing-at-point 'git-revision))) + (let ((text (buffer-substring-no-properties (car it) (cdr it)))) + (and (magit-commit-p text) text)))) + +;;; Completion + +(defvar magit-revision-history nil) + +(defun magit-read-branch (prompt &optional secondary-default) + (magit-completing-read prompt (magit-list-branch-names) + nil t nil 'magit-revision-history + (or (magit-branch-at-point) + secondary-default + (magit-get-current-branch)))) + +(defun magit-read-branch-or-commit (prompt &optional secondary-default) + (or (magit-completing-read prompt (magit-list-refnames nil t) + nil nil nil 'magit-revision-history + (or (magit-branch-or-commit-at-point) + secondary-default + (magit-get-current-branch))) + (user-error "Nothing selected"))) + +(defun magit-read-range-or-commit (prompt &optional secondary-default) + (magit-read-range + prompt + (or (--when-let (magit-region-values '(commit branch) t) + (deactivate-mark) + (concat (car (last it)) ".." (car it))) + (magit-branch-or-commit-at-point) + secondary-default + (magit-get-current-branch)))) + +(defun magit-read-range (prompt &optional default) + (magit-completing-read-multiple prompt + (magit-list-refnames) + "\\.\\.\\.?" + default 'magit-revision-history)) + +(defun magit-read-remote-branch + (prompt &optional remote default local-branch require-match) + (let ((choice (magit-completing-read + prompt + (-union (and local-branch + (if remote + (concat remote "/" local-branch) + (--map (concat it "/" local-branch) + (magit-list-remotes)))) + (magit-list-remote-branch-names remote t)) + nil require-match nil 'magit-revision-history default))) + (if (or remote (string-match "\\`\\([^/]+\\)/\\(.+\\)" choice)) + choice + (user-error "`%s' doesn't have the form REMOTE/BRANCH" choice)))) + +(defun magit-read-refspec (prompt remote) + (magit-completing-read prompt + (prog2 (message "Determining available refs...") + (magit-remote-list-refs remote) + (message "Determining available refs...done")))) + +(defun magit-read-local-branch (prompt &optional secondary-default) + (magit-completing-read prompt (magit-list-local-branch-names) + nil t nil 'magit-revision-history + (or (magit-local-branch-at-point) + secondary-default + (magit-get-current-branch)))) + +(defun magit-read-local-branch-or-commit (prompt) + (let ((choices (nconc (magit-list-local-branch-names) + (magit-list-special-refnames))) + (commit (magit-commit-at-point))) + (when commit + (push commit choices)) + (or (magit-completing-read prompt choices + nil nil nil 'magit-revision-history + (or (magit-local-branch-at-point) commit)) + (user-error "Nothing selected")))) + +(defun magit-read-local-branch-or-ref (prompt &optional secondary-default) + (magit-completing-read prompt (nconc (magit-list-local-branch-names) + (magit-list-refs "refs/")) + nil t nil 'magit-revision-history + (or (magit-local-branch-at-point) + secondary-default + (magit-get-current-branch)))) + +(defun magit-read-other-branch + (prompt &optional exclude secondary-default no-require-match) + (let* ((current (magit-get-current-branch)) + (atpoint (magit-branch-at-point)) + (exclude (or exclude current)) + (default (or (and (not (equal atpoint exclude)) atpoint) + (and (not (equal current exclude)) current) + secondary-default + (magit-get-previous-branch)))) + (magit-completing-read prompt (delete exclude (magit-list-branch-names)) + nil (not no-require-match) + nil 'magit-revision-history default))) + +(defun magit-read-other-branch-or-commit + (prompt &optional exclude secondary-default) + (let* ((current (magit-get-current-branch)) + (atpoint (magit-branch-or-commit-at-point)) + (exclude (or exclude current)) + (default (or (and (not (equal atpoint exclude)) + (not (and (not current) + (magit-rev-equal atpoint "HEAD"))) + atpoint) + (and (not (equal current exclude)) current) + secondary-default + (magit-get-previous-branch)))) + (or (magit-completing-read prompt (delete exclude (magit-list-refnames)) + nil nil nil 'magit-revision-history default) + (user-error "Nothing selected")))) + +(defun magit-read-other-local-branch + (prompt &optional exclude secondary-default no-require-match) + (let* ((current (magit-get-current-branch)) + (atpoint (magit-local-branch-at-point)) + (exclude (or exclude current)) + (default (or (and (not (equal atpoint exclude)) atpoint) + (and (not (equal current exclude)) current) + secondary-default + (magit-get-previous-branch)))) + (magit-completing-read prompt + (delete exclude (magit-list-local-branch-names)) + nil (not no-require-match) + nil 'magit-revision-history default))) + +(defun magit-read-branch-prefer-other (prompt) + (let* ((current (magit-get-current-branch)) + (commit (magit-commit-at-point)) + (atrev (and commit (magit-list-branches-pointing-at commit))) + (atpoint (magit--painted-branch-at-point))) + (magit-completing-read prompt (magit-list-branch-names) + nil t nil 'magit-revision-history + (or (magit-section-value-if 'branch) + atpoint + (and (not (cdr atrev)) (car atrev)) + (--first (not (equal it current)) atrev) + (magit-get-previous-branch) + (car atrev))))) + +(defun magit-read-upstream-branch (&optional branch prompt) + "Read the upstream for BRANCH using PROMPT. +If optional BRANCH is nil, then read the upstream for the +current branch, or raise an error if no branch is checked +out. Only existing branches can be selected." + (unless branch + (setq branch (or (magit-get-current-branch) + (error "Need a branch to set its upstream")))) + (let ((branches (delete branch (magit-list-branch-names)))) + (magit-completing-read + (or prompt (format "Change upstream of %s to" branch)) + branches nil t nil 'magit-revision-history + (or (let ((r (car (member (magit-remote-branch-at-point) branches))) + (l (car (member (magit-local-branch-at-point) branches)))) + (if magit-prefer-remote-upstream (or r l) (or l r))) + (let ((r (car (member "origin/master" branches))) + (l (car (member "master" branches)))) + (if magit-prefer-remote-upstream (or r l) (or l r))) + (car (member (magit-get-previous-branch) branches)))))) + +(defun magit-read-starting-point (prompt &optional branch default) + (or (magit-completing-read + (concat prompt + (and branch + (if (bound-and-true-p ivy-mode) + ;; Ivy-mode strips faces from prompt. + (format " `%s'" branch) + (concat " " (magit--propertize-face + branch 'magit-branch-local)))) + " starting at") + (nconc (list "HEAD") + (magit-list-refnames) + (directory-files (magit-git-dir) nil "_HEAD\\'")) + nil nil nil 'magit-revision-history + (or default (magit--default-starting-point))) + (user-error "Nothing selected"))) + +(defun magit--default-starting-point () + (or (let ((r (magit-remote-branch-at-point)) + (l (magit-local-branch-at-point))) + (if magit-prefer-remote-upstream (or r l) (or l r))) + (magit-commit-at-point) + (magit-stash-at-point) + (magit-get-current-branch))) + +(defun magit-read-tag (prompt &optional require-match) + (magit-completing-read prompt (magit-list-tags) nil + require-match nil 'magit-revision-history + (magit-tag-at-point))) + +(defun magit-read-stash (prompt) + (let ((stashes (magit-list-stashes))) + (magit-completing-read prompt stashes nil t nil nil + (magit-stash-at-point) + (car stashes)))) + +(defun magit-read-remote (prompt &optional default use-only) + (let ((remotes (magit-list-remotes))) + (if (and use-only (= (length remotes) 1)) + (car remotes) + (magit-completing-read prompt remotes + nil t nil nil + (or default + (magit-remote-at-point) + (magit-get-remote)))))) + +(defun magit-read-remote-or-url (prompt &optional default) + (magit-completing-read prompt + (nconc (magit-list-remotes) + (list "https://" "git://" "git@")) + nil nil nil nil + (or default + (magit-remote-at-point) + (magit-get-remote)))) + +(defun magit-read-module-path (prompt &optional predicate) + (magit-completing-read prompt (magit-list-module-paths) + predicate t nil nil + (magit-module-at-point predicate))) + +(defun magit-module-confirm (verb &optional predicate) + (let (modules) + (if current-prefix-arg + (progn + (setq modules (magit-list-module-paths)) + (when predicate + (setq modules (-filter predicate modules))) + (unless modules + (if predicate + (user-error "No modules satisfying %s available" predicate) + (user-error "No modules available")))) + (setq modules (magit-region-values 'magit-module-section)) + (when modules + (when predicate + (setq modules (-filter predicate modules))) + (unless modules + (user-error "No modules satisfying %s selected" predicate)))) + (if (> (length modules) 1) + (magit-confirm t nil (format "%s %%i modules" verb) nil modules) + (list (magit-read-module-path (format "%s module" verb) predicate))))) + +;;; _ +(provide 'magit-git) +;;; magit-git.el ends here diff --git a/elpa/magit-20191122.2040/magit-git.elc b/elpa/magit-20191122.2040/magit-git.elc new file mode 100644 index 0000000000000000000000000000000000000000..2d6234362a9d3da3b209ba886cb20d3ce609b974 GIT binary patch literal 91005 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 J0qXqX#(#w1{v`ka literal 0 HcmV?d00001 diff --git a/elpa/magit-20191122.2040/magit-gitignore.el b/elpa/magit-20191122.2040/magit-gitignore.el new file mode 100644 index 00000000..21c0239d --- /dev/null +++ b/elpa/magit-20191122.2040/magit-gitignore.el @@ -0,0 +1,197 @@ +;;; magit-gitignore.el --- intentionally untracked files -*- lexical-binding: t -*- + +;; Copyright (C) 2008-2019 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; This library implements gitignore commands. + +;;; Code: + +(eval-when-compile + (require 'subr-x)) + +(require 'magit) + +;;; Transient + +;;;###autoload (autoload 'magit-gitignore "magit-gitignore" nil t) +(define-transient-command magit-gitignore () + "Instruct Git to ignore a file or pattern." + :man-page "gitignore" + ["Gitignore" + ("t" "shared at toplevel (.gitignore)" + magit-gitignore-in-topdir) + ("s" "shared in subdirectory (path/to/.gitignore)" + magit-gitignore-in-subdir) + ("p" "privately (.git/info/exclude)" + magit-gitignore-in-gitdir) + ("g" magit-gitignore-on-system + :if (lambda () (magit-get "core.excludesfile")) + :description (lambda () + (format "privately for all repositories (%s)" + (magit-get "core.excludesfile"))))] + ["Skip worktree" + (7 "w" "do skip worktree" magit-skip-worktree) + (7 "W" "do not skip worktree" magit-no-skip-worktree)] + ["Assume unchanged" + (7 "u" "do assume unchanged" magit-assume-unchanged) + (7 "U" "do not assume unchanged" magit-no-assume-unchanged)]) + +;;; Gitignore Commands + +;;;###autoload +(defun magit-gitignore-in-topdir (rule) + "Add the Git ignore RULE to the top-level \".gitignore\" file. +Since this file is tracked, it is shared with other clones of the +repository. Also stage the file." + (interactive (list (magit-gitignore-read-pattern))) + (magit-with-toplevel + (magit--gitignore rule ".gitignore") + (magit-run-git "add" ".gitignore"))) + +;;;###autoload +(defun magit-gitignore-in-subdir (rule directory) + "Add the Git ignore RULE to a \".gitignore\" file. +Prompted the user for a directory and add the rule to the +\".gitignore\" file in that directory. Since such files are +tracked, they are shared with other clones of the repository. +Also stage the file." + (interactive (list (magit-gitignore-read-pattern) + (read-directory-name "Limit rule to files in: "))) + (magit-with-toplevel + (let ((file (expand-file-name ".gitignore" directory))) + (magit--gitignore rule file) + (magit-run-git "add" file)))) + +;;;###autoload +(defun magit-gitignore-in-gitdir (rule) + "Add the Git ignore RULE to \"$GIT_DIR/info/exclude\". +Rules in that file only affects this clone of the repository." + (interactive (list (magit-gitignore-read-pattern))) + (magit--gitignore rule (magit-git-dir "info/exclude")) + (magit-refresh)) + +;;;###autoload +(defun magit-gitignore-on-system (rule) + "Add the Git ignore RULE to the file specified by `core.excludesFile'. +Rules that are defined in that file affect all local repositories." + (interactive (list (magit-gitignore-read-pattern))) + (magit--gitignore rule + (or (magit-get "core.excludesFile") + (error "Variable `core.excludesFile' isn't set"))) + (magit-refresh)) + +(defun magit--gitignore (rule file) + (when-let ((directory (file-name-directory file))) + (make-directory directory t)) + (with-temp-buffer + (when (file-exists-p file) + (insert-file-contents file)) + (goto-char (point-max)) + (unless (bolp) + (insert "\n")) + (insert (replace-regexp-in-string "\\(\\\\*\\)" "\\1\\1" rule)) + (insert "\n") + (write-region nil nil file))) + +(defun magit-gitignore-read-pattern () + (let* ((default (magit-current-file)) + (base (car magit-buffer-diff-files)) + (base (and base (file-directory-p base) base)) + (choices + (delete-dups + (--mapcat + (cons (concat "/" it) + (when-let ((ext (file-name-extension it))) + (list (concat "/" (file-name-directory it) "*." ext) + (concat "*." ext)))) + (sort (nconc + (magit-untracked-files nil base) + ;; The untracked section of the status buffer lists + ;; directories containing only untracked files. + ;; Add those as candidates. + (-filter #'directory-name-p + (magit-list-files + "--other" "--exclude-standard" "--directory" + "--no-empty-directory" "--" base))) + #'string-lessp))))) + (when default + (setq default (concat "/" default)) + (unless (member default choices) + (setq default (concat "*." (file-name-extension default))) + (unless (member default choices) + (setq default nil)))) + (magit-completing-read "File or pattern to ignore" + choices nil nil nil nil default))) + +;;; Skip Worktree Commands + +;;;###autoload +(defun magit-skip-worktree (file) + "Call \"git update-index --skip-worktree -- FILE\"." + (interactive + (list (magit-read-file-choice "Skip worktree for" + (magit-with-toplevel + (cl-set-difference + (magit-list-files) + (magit-skip-worktree-files)))))) + (magit-with-toplevel + (magit-run-git "update-index" "--skip-worktree" "--" file))) + +;;;###autoload +(defun magit-no-skip-worktree (file) + "Call \"git update-index --no-skip-worktree -- FILE\"." + (interactive + (list (magit-read-file-choice "Do not skip worktree for" + (magit-with-toplevel + (magit-skip-worktree-files))))) + (magit-with-toplevel + (magit-run-git "update-index" "--no-skip-worktree" "--" file))) + +;;; Assume Unchanged Commands + +;;;###autoload +(defun magit-assume-unchanged (file) + "Call \"git update-index --assume-unchanged -- FILE\"." + (interactive + (list (magit-read-file-choice "Assume file to be unchanged" + (magit-with-toplevel + (cl-set-difference + (magit-list-files) + (magit-assume-unchanged-files)))))) + (magit-with-toplevel + (magit-run-git "update-index" "--assume-unchanged" "--" file))) + +;;;###autoload +(defun magit-no-assume-unchanged (file) + "Call \"git update-index --no-assume-unchanged -- FILE\"." + (interactive + (list (magit-read-file-choice "Do not assume file to be unchanged" + (magit-with-toplevel + (magit-assume-unchanged-files))))) + (magit-with-toplevel + (magit-run-git "update-index" "--no-assume-unchanged" "--" file))) + +;;; _ +(provide 'magit-gitignore) +;;; magit-gitignore.el ends here diff --git a/elpa/magit-20191122.2040/magit-gitignore.elc b/elpa/magit-20191122.2040/magit-gitignore.elc new file mode 100644 index 0000000000000000000000000000000000000000..75e57b3fa2d9ad19a18ee0679b59feee9bd03969 GIT binary patch literal 7378 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 +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; Emacs' major modes can facilitate navigation in their buffers by +;; supporting Imenu. In such major modes, launching Imenu (M-x imenu) +;; makes Emacs display a list of items (e.g., function definitions in +;; a programming major mode). Selecting an item from this list moves +;; point to this item. + +;; magit-imenu.el adds Imenu support to every major mode in Magit. + +;;; Code: + +(eval-when-compile + (require 'subr-x)) + +(require 'magit) +(require 'git-rebase) + +;;; Core + +(defun magit-imenu--index-function (entry-types menu-types) + "Return an alist of imenu entries in current buffer. + +ENTRY-TYPES is a list of section types to be selected through +`imenu'. + +MENU-TYPES is a list of section types containing elements of +ENTRY-TYPES. Elements of MENU-TYPES are are used to categories +elements of ENTRY-TYPES. + +This function is used as a helper for functions set as +`imenu-create-index-function'." + (let ((entries (make-hash-table :test 'equal))) + (goto-char (point-max)) + (while (magit-section--backward-find + (lambda () + (let* ((section (magit-current-section)) + (type (oref section type)) + (parent (oref section parent)) + (parent-type (oref parent type))) + (and (-contains-p entry-types type) + (-contains-p menu-types parent-type))))) + (let* ((section (magit-current-section)) + (name (buffer-substring-no-properties + (line-beginning-position) + (line-end-position))) + (parent (oref section parent)) + (parent-title (buffer-substring-no-properties + (oref parent start) + (1- (oref parent content))))) + (puthash parent-title + (cons (cons name (point)) + (gethash parent-title entries (list))) + entries))) + (mapcar (lambda (menu-title) + (cons menu-title (gethash menu-title entries))) + (hash-table-keys entries)))) + +;;; Log mode + +;;;###autoload +(defun magit-imenu--log-prev-index-position-function () + "Move point to previous line in current buffer. +This function is used as a value for +`imenu-prev-index-position-function'." + (magit-section--backward-find + (lambda () + (-contains-p '(commit stash) + (oref (magit-current-section) type))))) + +;;;###autoload +(defun magit-imenu--log-extract-index-name-function () + "Return imenu name for line at point. +This function is used as a value for +`imenu-extract-index-name-function'. Point should be at the +beginning of the line." + (save-match-data + (looking-at "\\([^ ]+\\)[ *|]+\\(.+\\)$") + (format "%s: %s" + (match-string-no-properties 1) + (match-string-no-properties 2)))) + +;;; Diff mode + +;;;###autoload +(defun magit-imenu--diff-prev-index-position-function () + "Move point to previous file line in current buffer. +This function is used as a value for +`imenu-prev-index-position-function'." + (magit-section--backward-find + (lambda () + (let ((section (magit-current-section))) + (and (magit-file-section-p section) + (not (equal (oref (oref section parent) type) + 'diffstat))))))) + +;;;###autoload +(defun magit-imenu--diff-extract-index-name-function () + "Return imenu name for line at point. +This function is used as a value for +`imenu-extract-index-name-function'. Point should be at the +beginning of the line." + (buffer-substring-no-properties (line-beginning-position) + (line-end-position))) + +;;; Status mode + +;;;###autoload +(defun magit-imenu--status-create-index-function () + "Return an alist of all imenu entries in current buffer. +This function is used as a value for +`imenu-create-index-function'." + (magit-imenu--index-function + '(file commit stash) + '(unpushed unstaged unpulled untracked staged stashes))) + +;;;; Refs mode + +;;;###autoload +(defun magit-imenu--refs-create-index-function () + "Return an alist of all imenu entries in current buffer. +This function is used as a value for +`imenu-create-index-function'." + (magit-imenu--index-function + '(branch commit tag) + '(local remote tags))) + +;;;; Cherry mode + +;;;###autoload +(defun magit-imenu--cherry-create-index-function () + "Return an alist of all imenu entries in current buffer. +This function is used as a value for +`imenu-create-index-function'." + (magit-imenu--index-function + '(commit) + '(cherries))) + +;;;; Submodule list mode + +;;;###autoload +(defun magit-imenu--submodule-prev-index-position-function () + "Move point to previous line in magit-submodule-list buffer. +This function is used as a value for +`imenu-prev-index-position-function'." + (unless (bobp) + (forward-line -1))) + +;;;###autoload +(defun magit-imenu--submodule-extract-index-name-function () + "Return imenu name for line at point. +This function is used as a value for +`imenu-extract-index-name-function'. Point should be at the +beginning of the line." + (elt (tabulated-list-get-entry) 0)) + +;;;; Repolist mode + +;;;###autoload +(defun magit-imenu--repolist-prev-index-position-function () + "Move point to previous line in magit-repolist buffer. +This function is used as a value for +`imenu-prev-index-position-function'." + (unless (bobp) + (forward-line -1))) + +;;;###autoload +(defun magit-imenu--repolist-extract-index-name-function () + "Return imenu name for line at point. +This function is used as a value for +`imenu-extract-index-name-function'. Point should be at the +beginning of the line." + (let ((entry (tabulated-list-get-entry))) + (format "%s (%s)" + (elt entry 0) + (elt entry (1- (length entry)))))) + +;;;; Process mode + +;;;###autoload +(defun magit-imenu--process-prev-index-position-function () + "Move point to previous process in magit-process buffer. +This function is used as a value for +`imenu-prev-index-position-function'." + (magit-section--backward-find + (lambda () + (eq (oref (magit-current-section) type) 'process)))) + +;;;###autoload +(defun magit-imenu--process-extract-index-name-function () + "Return imenu name for line at point. +This function is used as a value for +`imenu-extract-index-name-function'. Point should be at the +beginning of the line." + (buffer-substring-no-properties (line-beginning-position) + (line-end-position))) + +;;;; Rebase mode + +;;;###autoload +(defun magit-imenu--rebase-prev-index-position-function () + "Move point to previous commit in git-rebase buffer. +This function is used as a value for +`imenu-prev-index-position-function'." + (catch 'found + (while (not (bobp)) + (git-rebase-backward-line) + (when (git-rebase-line-p) + (throw 'found t))))) + +;;;###autoload +(defun magit-imenu--rebase-extract-index-name-function () + "Return imenu name for line at point. +This function is used as a value for +`imenu-extract-index-name-function'. Point should be at the +beginning of the line." + (buffer-substring-no-properties (line-beginning-position) + (line-end-position))) + +;;; _ +(provide 'magit-imenu) +;;; magit-imenu.el ends here diff --git a/elpa/magit-20191122.2040/magit-imenu.elc b/elpa/magit-20191122.2040/magit-imenu.elc new file mode 100644 index 0000000000000000000000000000000000000000..3b6d7f0237e1cc59d46870631d8f0482d83ac560 GIT binary patch literal 6830 zcmdT}ZBN@)6o!`4E+6-0+P>^GfSPPIvab^dil(ha(NwLis=_8sBvT#x23sV)o?mF0 z_T%@QYdbNNq@cd6R5J1Fz2`pXdCtr2UjNztH!CYEjlI1++E>#!oJe0^gc0?pu9woO zOwv$AB%EzqKY0^o0lAY2sW=O#;XiJM$LV%MKRgV=l*Sl^@>HhepGEF8^vG9Unk8X$ zoIb?UB+bb6ed*I|7HfA~?7lOGuP{cWGV)ZExp+Cx#>NirM8@NT{ijdK3*5x@GMM;K zPwz%PrHVW^qLHMDa?edtE+r-DCX-Mmlm&QE*u}hn;Di3L0U!FW(P*?rXPGoSpm`Iws$6-b|j6{yyR1QhB8ymmayMkWHEKefBBHc*{ z(AAj2sf==x5xfCx0jZZK2`*`rkH<0r6#W;6ul_U+|9sg$AUM;d>eEzu>}tx+Vtkq@ zhB%cI+=VBzAW`{o(0HvUcz|)9_h0<}{$Wbbf*OROU|g2M%(@ZVME&^_stxO6^?ZP8 zFo4~j$z#O}Yt+V~+JazK!O%P^)`A7dd{)&K@-VQR#de*Bu;P z91f1&z_!fwd+YZG;E84FzhaZwVfR;X$0q#22UeF)9MUiJZVhZ<>QjECFN;rmxA6q? z9q>b8udcm*g5S>C`d9erZai7PyD<=sa|h##yBJ@v4H!ef4x5Qt*t32gmwH57;LP6Q z3A_6^W!rJsu-~5Buix+Socw;r+`5f(X1lj3S81h*cVDwd(sa^5=JIMwIiXnVS?r zmaU0%#KknAV_E!0A)^|5ZbG8l17z$PL?wm^RC-c6rF?xzUAz(vB34A9f~SYi`t2r< zp~sz(ychsZ#tEx7|N1vFjQwZEACF%dM!PvAh@-W!N!!%v?Y4&;63fq>mD1t7nT6=I(Bl zON#t~tgeC5tRv7~ED{`n3YiIW*Q#{3vq)#U*yAAce~HZx z$Ky|?HqDAvPO9CnIp`xFSvv69niMQP&K1HIKhHeQD!v%J3(YZBGl9o-O_qU}MM%6L zs5U#VM&X#98?Q#~t1HP7uv!d0l5>^yKUM-{=@bNq_GSd{RuQgVEpwam-irA;8D&BJ zxHx_>5%To%x^o`97%c{ChSjn%v!x|_K0UPZD9+OWb#xwK%42;J=M%JpxWj?^1ZU+F z{NUBJT?5kYeCa@<=K9DmjuJQW0`#Uj&jPeIwI<3#4VuWQ$|T{|Igp&5S%uRtlx)0hEwzDY1RLP~_H0s}}@^b`I-IrEv>vcr9tTcPDq?VXZ zy=;U+m5TF0mm4M1JS$U!VWEbtN?2j<-1u-l2jt2zeHBj9r)*Ftw!*PzwBUZ&Poip~{0b4uNIO{Z5yEU}1Z zXv;mB>g}~6XjL~pXS6EkyaLfUM&aP5=9-PDuF!N1Z2we#T-#kJ)_$=R)-`Tv94d%f z!`bb0sswp+8_o*$EA#o2SGnEZEHsLRZCqK!U_*GmlRVoK{v64**u1_XTg7)PMRe3V zacC5Z{c$u4*!^7Nq|3XdOlt1X^md{t)>f)Lrm@Pg88~0)e3wwy8np*{_bk@C+iwUR lS=Bi>mR%LRH +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; This library implements support for looking at Git logs, including +;; special logs like cherry-logs, as well as for selecting a commit +;; from a log. + +;;; Code: + +(require 'magit-core) +(require 'magit-diff) + +(declare-function magit-blob-visit "magit-files" (blob-or-file line)) +(declare-function magit-insert-head-branch-header "magit-status" + (&optional branch)) +(declare-function magit-insert-upstream-branch-header "magit-status" + (&optional branch pull keyword)) +(declare-function magit-read-file-from-rev "magit-files" + (rev prompt &optional default)) +(declare-function magit-show-commit "magit-diff" + (arg1 &optional arg2 arg3 arg4)) +(declare-function magit-reflog-format-subject "magit-reflog" (subject)) +(defvar magit-refs-focus-column-width) +(defvar magit-refs-margin) +(defvar magit-refs-show-commit-count) +(defvar magit-buffer-margin) +(defvar magit-status-margin) +(defvar magit-status-sections-hook) + +(require 'ansi-color) +(require 'crm) +(require 'which-func) + +(eval-when-compile + (require 'subr-x)) + +;;; Options +;;;; Log Mode + +(defgroup magit-log nil + "Inspect and manipulate Git history." + :link '(info-link "(magit)Logging") + :group 'magit-modes) + +(defcustom magit-log-mode-hook nil + "Hook run after entering Magit-Log mode." + :group 'magit-log + :type 'hook) + +(defcustom magit-log-remove-graph-args '("--follow" "--grep" "-G" "-S" "-L") + "The log arguments that cause the `--graph' argument to be dropped." + :package-version '(magit . "2.3.0") + :group 'magit-log + :type '(repeat (string :tag "Argument")) + :options '("--follow" "--grep" "-G" "-S" "-L")) + +(defcustom magit-log-revision-headers-format "\ +%+b +Author: %aN <%aE> +Committer: %cN <%cE>" + "Additional format string used with the `++header' argument." + :package-version '(magit . "2.3.0") + :group 'magit-log + :type 'string) + +(defcustom magit-log-auto-more nil + "Insert more log entries automatically when moving past the last entry. +Only considered when moving past the last entry with +`magit-goto-*-section' commands." + :group 'magit-log + :type 'boolean) + +(defcustom magit-log-margin '(t age magit-log-margin-width t 18) + "Format of the margin in `magit-log-mode' buffers. + +The value has the form (INIT STYLE WIDTH AUTHOR AUTHOR-WIDTH). + +If INIT is non-nil, then the margin is shown initially. +STYLE controls how to format the author or committer date. + It can be one of `age' (to show the age of the commit), + `age-abbreviated' (to abbreviate the time unit to a character), + or a string (suitable for `format-time-string') to show the + actual date. Option `magit-log-margin-show-committer-date' + controls which date is being displayed. +WIDTH controls the width of the margin. This exists for forward + compatibility and currently the value should not be changed. +AUTHOR controls whether the name of the author is also shown by + default. +AUTHOR-WIDTH has to be an integer. When the name of the author + is shown, then this specifies how much space is used to do so." + :package-version '(magit . "2.9.0") + :group 'magit-log + :group 'magit-margin + :type magit-log-margin--custom-type + :initialize 'magit-custom-initialize-reset + :set (apply-partially #'magit-margin-set-variable 'magit-log-mode)) + +(defcustom magit-log-margin-show-committer-date nil + "Whether to show the committer date in the margin. + +This option only controls whether the committer date is displayed +instead of the author date. Whether some date is displayed in +the margin and whether the margin is displayed at all is +controlled by other options." + :package-version '(magit . "2.91.0") + :group 'magit-log + :group 'magit-margin + :type 'boolean) + +(defcustom magit-log-show-refname-after-summary nil + "Whether to show refnames after commit summaries. +This is useful if you use really long branch names." + :package-version '(magit . "2.2.0") + :group 'magit-log + :type 'boolean) + +(defcustom magit-log-highlight-keywords t + "Whether to highlight bracketed keywords in commit summaries." + :package-version '(magit . "2.12.0") + :group 'magit-log + :type 'boolean) + +(defcustom magit-log-header-line-function 'magit-log-header-line-sentence + "Function used to generate text shown in header line of log buffers." + :package-version '(magit . "2.12.0") + :group 'magit-log + :type '(choice (function-item magit-log-header-line-arguments) + (function-item magit-log-header-line-sentence) + function)) + +(defcustom magit-log-trace-definition-function 'magit-which-function + "Function used to determine the function at point. +This is used by the command `magit-log-trace-definition'. +You should prefer `magit-which-function' over `which-function' +because the latter may make use of Imenu's outdated cache." + :package-version '(magit . "2.91.0") + :group 'magit-log + :type '(choice (function-item magit-which-function) + (function-item which-function) + (function-item add-log-current-defun) + function)) + +(defface magit-log-graph + '((((class color) (background light)) :foreground "grey30") + (((class color) (background dark)) :foreground "grey80")) + "Face for the graph part of the log output." + :group 'magit-faces) + +(defface magit-log-author + '((((class color) (background light)) + :foreground "firebrick" + :slant normal + :weight normal) + (((class color) (background dark)) + :foreground "tomato" + :slant normal + :weight normal)) + "Face for the author part of the log output." + :group 'magit-faces) + +(defface magit-log-date + '((((class color) (background light)) + :foreground "grey30" + :slant normal + :weight normal) + (((class color) (background dark)) + :foreground "grey80" + :slant normal + :weight normal)) + "Face for the date part of the log output." + :group 'magit-faces) + +(defface magit-header-line-log-select + '((t :inherit bold)) + "Face for the `header-line' in `magit-log-select-mode'." + :group 'magit-faces) + +;;;; File Log + +(defcustom magit-log-buffer-file-locked t + "Whether `magit-log-buffer-file-quick' uses a dedicated buffer." + :package-version '(magit . "2.7.0") + :group 'magit-commands + :group 'magit-log + :type 'boolean) + +;;;; Select Mode + +(defcustom magit-log-select-show-usage 'both + "Whether to show usage information when selecting a commit from a log. +The message can be shown in the `echo-area' or the `header-line', or in +`both' places. If the value isn't one of these symbols, then it should +be nil, in which case no usage information is shown." + :package-version '(magit . "2.1.0") + :group 'magit-log + :type '(choice (const :tag "in echo-area" echo-area) + (const :tag "in header-line" header-line) + (const :tag "in both places" both) + (const :tag "nowhere"))) + +(defcustom magit-log-select-margin + (list (nth 0 magit-log-margin) + (nth 1 magit-log-margin) + 'magit-log-margin-width t + (nth 4 magit-log-margin)) + "Format of the margin in `magit-log-select-mode' buffers. + +The value has the form (INIT STYLE WIDTH AUTHOR AUTHOR-WIDTH). + +If INIT is non-nil, then the margin is shown initially. +STYLE controls how to format the author or committer date. + It can be one of `age' (to show the age of the commit), + `age-abbreviated' (to abbreviate the time unit to a character), + or a string (suitable for `format-time-string') to show the + actual date. Option `magit-log-margin-show-committer-date' + controls which date is being displayed. +WIDTH controls the width of the margin. This exists for forward + compatibility and currently the value should not be changed. +AUTHOR controls whether the name of the author is also shown by + default. +AUTHOR-WIDTH has to be an integer. When the name of the author + is shown, then this specifies how much space is used to do so." + :package-version '(magit . "2.9.0") + :group 'magit-log + :group 'magit-margin + :type magit-log-margin--custom-type + :initialize 'magit-custom-initialize-reset + :set-after '(magit-log-margin) + :set (apply-partially #'magit-margin-set-variable 'magit-log-select-mode)) + +;;;; Cherry Mode + +(defcustom magit-cherry-sections-hook + '(magit-insert-cherry-headers + magit-insert-cherry-commits) + "Hook run to insert sections into the cherry buffer." + :package-version '(magit . "2.1.0") + :group 'magit-log + :type 'hook) + +(defcustom magit-cherry-margin + (list (nth 0 magit-log-margin) + (nth 1 magit-log-margin) + 'magit-log-margin-width t + (nth 4 magit-log-margin)) + "Format of the margin in `magit-cherry-mode' buffers. + +The value has the form (INIT STYLE WIDTH AUTHOR AUTHOR-WIDTH). + +If INIT is non-nil, then the margin is shown initially. +STYLE controls how to format the author or committer date. + It can be one of `age' (to show the age of the commit), + `age-abbreviated' (to abbreviate the time unit to a character), + or a string (suitable for `format-time-string') to show the + actual date. Option `magit-log-margin-show-committer-date' + controls which date is being displayed. +WIDTH controls the width of the margin. This exists for forward + compatibility and currently the value should not be changed. +AUTHOR controls whether the name of the author is also shown by + default. +AUTHOR-WIDTH has to be an integer. When the name of the author + is shown, then this specifies how much space is used to do so." + :package-version '(magit . "2.9.0") + :group 'magit-log + :group 'magit-margin + :type magit-log-margin--custom-type + :initialize 'magit-custom-initialize-reset + :set-after '(magit-log-margin) + :set (apply-partially #'magit-margin-set-variable 'magit-cherry-mode)) + +;;;; Log Sections + +(defcustom magit-log-section-commit-count 10 + "How many recent commits to show in certain log sections. +How many recent commits `magit-insert-recent-commits' and +`magit-insert-unpulled-from-upstream-or-recent' (provided +the upstream isn't ahead of the current branch) show." + :package-version '(magit . "2.1.0") + :group 'magit-status + :type 'number) + +;;; Arguments +;;;; Prefix Classes + +(defclass magit-log-prefix (transient-prefix) + ((history-key :initform 'magit-log) + (major-mode :initform 'magit-log-mode))) + +(defclass magit-log-refresh-prefix (magit-log-prefix) + ((history-key :initform 'magit-log) + (major-mode :initform nil))) + +;;;; Prefix Methods + +(cl-defmethod transient-init-value ((obj magit-log-prefix)) + (pcase-let ((`(,args ,files) + (magit-log--get-value 'magit-log-mode + magit-prefix-use-buffer-arguments))) + (unless (eq current-transient-command 'magit-dispatch) + (when-let ((file (magit-file-relative-name))) + (setq files (list file)))) + (oset obj value (if files `(("--" ,@files) ,args) args)))) + +(cl-defmethod transient-init-value ((obj magit-log-refresh-prefix)) + (oset obj value (if magit-buffer-log-files + `(("--" ,@magit-buffer-log-files) + ,magit-buffer-log-args) + magit-buffer-log-args))) + +(cl-defmethod transient-set-value ((obj magit-log-prefix)) + (magit-log--set-value obj)) + +(cl-defmethod transient-save-value ((obj magit-log-prefix)) + (magit-log--set-value obj 'save)) + +;;;; Argument Access + +(defun magit-log-arguments (&optional mode) + "Return the current log arguments." + (if (memq current-transient-command '(magit-log magit-log-refresh)) + (pcase-let ((`(,args ,alist) + (-separate #'atom (transient-get-value)))) + (list args (cdr (assoc "--" alist)))) + (magit-log--get-value (or mode 'magit-log-mode)))) + +(defun magit-log--get-value (mode &optional use-buffer-args) + (unless use-buffer-args + (setq use-buffer-args magit-direct-use-buffer-arguments)) + (let (args files) + (cond + ((and (memq use-buffer-args '(always selected current)) + (eq major-mode mode)) + (setq args magit-buffer-log-args) + (setq files magit-buffer-log-files)) + ((and (memq use-buffer-args '(always selected)) + (when-let ((buffer (magit-get-mode-buffer + mode nil + (or (eq use-buffer-args 'selected) 'all)))) + (setq args (buffer-local-value 'magit-buffer-log-args buffer)) + (setq files (buffer-local-value 'magit-buffer-log-files buffer)) + t))) + ((plist-member (symbol-plist mode) 'magit-log-current-arguments) + (setq args (get mode 'magit-log-current-arguments))) + ((when-let ((elt (assq (intern (format "magit-log:%s" mode)) + transient-values))) + (setq args (cdr elt)) + t)) + (t + (setq args (get mode 'magit-log-default-arguments)))) + (list args files))) + +(defun magit-log--set-value (obj &optional save) + (pcase-let* ((obj (oref obj prototype)) + (mode (or (oref obj major-mode) major-mode)) + (key (intern (format "magit-log:%s" mode))) + (`(,args ,alist) + (-separate #'atom (transient-get-value))) + (files (cdr (assoc "--" alist)))) + (put mode 'magit-log-current-arguments args) + (when save + (setf (alist-get key transient-values) args) + (transient-save-values)) + (transient--history-push obj) + (setq magit-buffer-log-args args) + (unless (derived-mode-p 'magit-log-select-mode) + (setq magit-buffer-log-files files)) + (magit-refresh))) + +;;; Commands +;;;; Prefix Commands + +;;;###autoload (autoload 'magit-log "magit-log" nil t) +(define-transient-command magit-log () + "Show a commit or reference log." + :man-page "git-log" + :class 'magit-log-prefix + ;; The grouping in git-log(1) appears to be guided by implementation + ;; details, so our logical grouping only follows it to an extend. + ;; Arguments that are "misplaced" here: + ;; 1. From "Commit Formatting". + ;; 2. From "Common Diff Options". + ;; 3. From unnamed first group. + ;; 4. Implemented by Magit. + ["Commit limiting" + (magit-log:-n) + (magit:--author) + (7 "=s" "Limit to commits since" "--since=" transient-read-date) + (7 "=u" "Limit to commits until" "--until=" transient-read-date) + (magit-log:--grep) + (7 "-I" "Invert search pattern" "--invert-grep") + (magit-log:-G) ;2 + (magit-log:-S) ;2 + (magit-log:-L) ;2 + (7 "=m" "Omit merges" "--no-merges") + (7 "=p" "First parent" "--first-parent")] + ["History simplification" + ( "-D" "Simplify by decoration" "--simplify-by-decoration") + (magit:--) + ( "-f" "Follow renames when showing single-file log" "--follow") ;3 + (6 "/s" "Only commits changing given paths" "--sparse") + (7 "/d" "Only selected commits plus meaningful history" "--dense") + (7 "/a" "Only commits existing directly on ancestry path" "--ancestry-path") + (6 "/f" "Do not prune history" "--full-history") + (7 "/m" "Prune some history" "--simplify-merges")] + ["Commit ordering" + (magit-log:--*-order) + ("-r" "Reverse order" "--reverse")] + ["Formatting" + ("-g" "Show graph" "--graph") ;1 + ("-c" "Show graph in color" "--color") ;2 + ("-d" "Show refnames" "--decorate") ;3 + ("=S" "Show signatures" "--show-signature") ;1 + ("-h" "Show header" "++header") ;4 + ("-p" "Show diffs" ("-p" "--patch")) ;2 + ("-s" "Show diffstats" "--stat")] ;2 + [["Log" + ("l" "current" magit-log-current) + ("o" "other" magit-log-other) + ("h" "HEAD" magit-log-head)] + ["" + ("L" "local branches" magit-log-branches) + (7 "B" "matching branches" magit-log-matching-branches) + (7 "T" "matching tags" magit-log-matching-tags) + ("b" "all branches" magit-log-all-branches) + ("a" "all references" magit-log-all) + (7 "m" "merged" magit-log-merged)] + ["Reflog" + ("r" "current" magit-reflog-current) + ("O" "other" magit-reflog-other) + ("H" "HEAD" magit-reflog-head)] + [:if-non-nil magit-wip-mode + :description "Wiplog" + ("i" "index" magit-wip-log-index) + ("w" "worktree" magit-wip-log-worktree)]]) + +;;;###autoload (autoload 'magit-log-refresh "magit-log" nil t) +(define-transient-command magit-log-refresh () + "Change the arguments used for the log(s) in the current buffer." + :man-page "git-log" + :class 'magit-log-refresh-prefix + [:if-mode magit-log-mode + :class transient-subgroups + ["Commit limiting" + (magit-log:-n) + (magit:--author) + (magit-log:--grep) + (7 "-I" "Invert search pattern" "--invert-grep") + (magit-log:-G) + (magit-log:-S) + (magit-log:-L)] + ["History simplification" + ( "-D" "Simplify by decoration" "--simplify-by-decoration") + (magit:--) + ( "-f" "Follow renames when showing single-file log" "--follow") ;3 + (6 "/s" "Only commits changing given paths" "--sparse") + (7 "/d" "Only selected commits plus meaningful history" "--dense") + (7 "/a" "Only commits existing directly on ancestry path" "--ancestry-path") + (6 "/f" "Do not prune history" "--full-history") + (7 "/m" "Prune some history" "--simplify-merges")] + ["Commit ordering" + (magit-log:--*-order) + ("-r" "Reverse order" "--reverse")] + ["Formatting" + ("-g" "Show graph" "--graph") + ("-c" "Show graph in color" "--color") + ("-d" "Show refnames" "--decorate") + ("=S" "Show signatures" "--show-signature") + ("-h" "Show header" "++header") + ("-p" "Show diffs" ("-p" "--patch")) + ("-s" "Show diffstats" "--stat")]] + [:if-not-mode magit-log-mode + :description "Arguments" + (magit-log:-n) + (magit-log:--*-order) + ("-g" "Show graph" "--graph") + ("-c" "Show graph in color" "--color") + ("-d" "Show refnames" "--decorate")] + [["Refresh" + ("g" "buffer" magit-log-refresh) + ("s" "buffer and set defaults" transient-set :transient nil) + ("w" "buffer and save defaults" transient-save :transient nil)] + ["Margin" + ("L" "toggle visibility" magit-toggle-margin) + ("l" "cycle style" magit-cycle-margin-style) + ("d" "toggle details" magit-toggle-margin-details) + ("x" "toggle shortstat" magit-toggle-log-margin-style)] + [:if-mode magit-log-mode + :description "Toggle" + ("b" "buffer lock" magit-toggle-buffer-lock)]] + (interactive) + (cond + ((not (eq current-transient-command 'magit-log-refresh)) + (pcase major-mode + (`magit-reflog-mode + (user-error "Cannot change log arguments in reflog buffers")) + (`magit-cherry-mode + (user-error "Cannot change log arguments in cherry buffers"))) + (transient-setup 'magit-log-refresh)) + (t + (pcase-let ((`(,args ,files) (magit-log-arguments))) + (setq magit-buffer-log-args args) + (unless (derived-mode-p 'magit-log-select-mode) + (setq magit-buffer-log-files files))) + (magit-refresh)))) + +;;;; Infix Commands + +(define-infix-argument magit-log:-n () + :description "Limit number of commits" + :class 'transient-option + ;; For historic reasons (and because it easy to guess what "-n" + ;; stands for) this is the only argument where we do not use the + ;; long argument ("--max-count"). + :shortarg "-n" + :argument "-n" + :reader 'transient-read-number-N+) + +(define-infix-argument magit:--author () + :description "Limit to author" + :class 'transient-option + :key "-A" + :argument "--author=" + :reader 'magit-transient-read-person) + +(define-infix-argument magit-log:--*-order () + :description "Order commits by" + :class 'transient-switches + :key "-o" + :argument-format "--%s-order" + :argument-regexp "\\(--\\(topo\\|author-date\\|date\\)-order\\)" + :choices '("topo" "author-date" "date")) + +(define-infix-argument magit-log:--grep () + :description "Search messages" + :class 'transient-option + :key "-F" + :argument "--grep=") + +(define-infix-argument magit-log:-G () + :description "Search changes" + :class 'transient-option + :argument "-G") + +(define-infix-argument magit-log:-S () + :description "Search occurrences" + :class 'transient-option + :argument "-S") + +(define-infix-argument magit-log:-L () + :description "Trace line evolution" + :class 'transient-option + :argument "-L" + :reader 'magit-read-file-trace) + +(defun magit-read-file-trace (&rest _ignored) + (let ((file (magit-read-file-from-rev "HEAD" "File")) + (trace (magit-read-string "Trace"))) + (concat trace ":" file))) + +;;;; Setup Commands + +(defvar magit-log-read-revs-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map crm-local-completion-map) + (define-key map "\s" 'self-insert-command) + map)) + +(defun magit-log-read-revs (&optional use-current) + (or (and use-current (--when-let (magit-get-current-branch) (list it))) + (let ((collection (magit-list-refnames nil t))) + (split-string + (magit-completing-read-multiple "Log rev,s" collection + "\\(\\.\\.\\.?\\|[, ]\\)" + (or (magit-branch-or-commit-at-point) + (unless use-current + (magit-get-previous-branch))) + 'magit-revision-history + magit-log-read-revs-map) + "[, ]" t)))) + +(defun magit-log-read-pattern (option) + "Read a string from the user to pass as parameter to OPTION." + (magit-read-string (format "Type a pattern to pass to %s" option))) + +;;;###autoload +(defun magit-log-current (revs &optional args files) + "Show log for the current branch. +When `HEAD' is detached or with a prefix argument show log for +one or more revs read from the minibuffer." + (interactive (cons (magit-log-read-revs t) + (magit-log-arguments))) + (magit-log-setup-buffer revs args files)) + +;;;###autoload +(defun magit-log-other (revs &optional args files) + "Show log for one or more revs read from the minibuffer. +The user can input any revision or revisions separated by a +space, or even ranges, but only branches and tags, and a +representation of the commit at point, are available as +completion candidates." + (interactive (cons (magit-log-read-revs) + (magit-log-arguments))) + (magit-log-setup-buffer revs args files)) + +;;;###autoload +(defun magit-log-head (&optional args files) + "Show log for `HEAD'." + (interactive (magit-log-arguments)) + (magit-log-setup-buffer (list "HEAD") args files)) + +;;;###autoload +(defun magit-log-branches (&optional args files) + "Show log for all local branches and `HEAD'." + (interactive (magit-log-arguments)) + (magit-log-setup-buffer (if (magit-get-current-branch) + (list "--branches") + (list "HEAD" "--branches")) + args files)) + +;;;###autoload +(defun magit-log-matching-branches (pattern &optional args files) + "Show log for all branches matching PATTERN and `HEAD'." + (interactive (cons (magit-log-read-pattern "--branches") (magit-log-arguments))) + (magit-log-setup-buffer + (list "HEAD" (format "--branches=%s" pattern)) + args files)) + +;;;###autoload +(defun magit-log-matching-tags (pattern &optional args files) + "Show log for all tags matching PATTERN and `HEAD'." + (interactive (cons (magit-log-read-pattern "--tags") (magit-log-arguments))) + (magit-log-setup-buffer + (list "HEAD" (format "--tags=%s" pattern)) + args files)) + +;;;###autoload +(defun magit-log-all-branches (&optional args files) + "Show log for all local and remote branches and `HEAD'." + (interactive (magit-log-arguments)) + (magit-log-setup-buffer (if (magit-get-current-branch) + (list "--branches" "--remotes") + (list "HEAD" "--branches" "--remotes")) + args files)) + +;;;###autoload +(defun magit-log-all (&optional args files) + "Show log for all references and `HEAD'." + (interactive (magit-log-arguments)) + (magit-log-setup-buffer (if (magit-get-current-branch) + (list "--all") + (list "HEAD" "--all")) + args files)) + +;;;###autoload +(defun magit-log-buffer-file (&optional follow beg end) + "Show log for the blob or file visited in the current buffer. +With a prefix argument or when `--follow' is an active log +argument, then follow renames. When the region is active, +restrict the log to the lines that the region touches." + (interactive + (cons current-prefix-arg + (and (region-active-p) + (magit-file-relative-name) + (save-restriction + (widen) + (list (line-number-at-pos (region-beginning)) + (line-number-at-pos + (let ((end (region-end))) + (if (char-after end) + end + ;; Ensure that we don't get the line number + ;; of a trailing newline. + (1- end))))))))) + (require 'magit) + (if-let ((file (magit-file-relative-name))) + (magit-log-setup-buffer + (list (or magit-buffer-refname + (magit-get-current-branch) + "HEAD")) + (let ((args (car (magit-log-arguments)))) + (when (and follow (not (member "--follow" args))) + (push "--follow" args)) + (when (and (file-regular-p + (expand-file-name file (magit-toplevel))) + beg end) + (setq args (cons (format "-L%s,%s:%s" beg end file) + (cl-delete "-L" args :test + 'string-prefix-p))) + (setq file nil)) + args) + (and file (list file)) + magit-log-buffer-file-locked) + (user-error "Buffer isn't visiting a file"))) + +;;;###autoload +(defun magit-log-trace-definition (file fn rev) + "Show log for the definition at point." + (interactive (list (or (magit-file-relative-name) + (user-error "Buffer isn't visiting a file")) + (funcall magit-log-trace-definition-function) + (or magit-buffer-refname + (magit-get-current-branch) + "HEAD"))) + (require 'magit) + (magit-log-setup-buffer + (list rev) + (cons (format "-L:%s%s:%s" + (regexp-quote fn) + (if (derived-mode-p 'lisp-mode 'emacs-lisp-mode) + ;; Git doesn't treat "-" the same way as + ;; "_", leading to false-positives such as + ;; "foo-suffix" being considered a match + ;; for "foo". Wing it. + "\\( \\|$\\)" + ;; We could use "\\b" here, but since Git + ;; already does something equivalent, that + ;; isn't necessary. + "") + file) + (cl-delete "-L" (car (magit-log-arguments)) + :test 'string-prefix-p)) + nil magit-log-buffer-file-locked)) + +(defun magit-diff-trace-definition () + "Show log for the definition at point in a diff." + (interactive) + (pcase-let ((`(,buf ,pos) (magit-diff-visit-file--noselect))) + (magit--with-temp-position buf pos + (call-interactively #'magit-log-trace-definition)))) + +;;;###autoload +(defun magit-log-merged (commit branch &optional args files) + "Show log for the merge of COMMIT into BRANCH. + +More precisely, find merge commit M that brought COMMIT into +BRANCH, and show the log of the range \"M^1..M\". If COMMIT is +directly on BRANCH, then show approximately twenty surrounding +commits instead. + +This command requires git-when-merged, which is available from +https://github.com/mhagger/git-when-merged." + (interactive + (append (let ((commit (magit-read-branch-or-commit "Commit"))) + (list commit + (magit-read-other-branch "Merged into" commit))) + (magit-log-arguments))) + (unless (executable-find "git-when-merged") + (user-error "This command requires git-when-merged (%s)" + "https://github.com/mhagger/git-when-merged")) + (let (exit m) + (with-temp-buffer + (save-excursion + (setq exit (magit-process-file + magit-git-executable nil t nil + "when-merged" "-c" + "--abbrev" (number-to-string (magit-abbrev-length)) + commit branch))) + (setq m (buffer-substring-no-properties (point) (line-end-position)))) + (if (zerop exit) + (magit-log-setup-buffer (list (format "%s^1..%s" m m)) + args files nil commit) + (setq m (string-trim-left (substring m (string-match " " m)))) + (if (equal m "Commit is directly on this branch.") + (let* ((from (concat commit "~10")) + (to (- (car (magit-rev-diff-count branch commit)) 10)) + (to (if (<= to 0) + branch + (format "%s~%s" branch to)))) + (unless (magit-rev-verify-commit from) + (setq from (magit-git-string "rev-list" "--max-parents=0" + commit))) + (magit-log-setup-buffer (list (concat from ".." to)) + (cons "--first-parent" args) + files nil commit)) + (user-error "Could not find when %s was merged into %s: %s" + commit branch m))))) + +;;;; Limit Commands + +(defun magit-log-toggle-commit-limit () + "Toggle the number of commits the current log buffer is limited to. +If the number of commits is currently limited, then remove that +limit. Otherwise set it to 256." + (interactive) + (magit-log-set-commit-limit (lambda (&rest _) nil))) + +(defun magit-log-double-commit-limit () + "Double the number of commits the current log buffer is limited to." + (interactive) + (magit-log-set-commit-limit '*)) + +(defun magit-log-half-commit-limit () + "Half the number of commits the current log buffer is limited to." + (interactive) + (magit-log-set-commit-limit '/)) + +(defun magit-log-set-commit-limit (fn) + (let* ((val magit-buffer-log-args) + (arg (--first (string-match "^-n\\([0-9]+\\)?$" it) val)) + (num (and arg (string-to-number (match-string 1 arg)))) + (num (if num (funcall fn num 2) 256))) + (setq val (delete arg val)) + (setq magit-buffer-log-args + (if (and num (> num 0)) + (cons (format "-n%i" num) val) + val))) + (magit-refresh)) + +(defun magit-log-get-commit-limit () + (--when-let (--first (string-match "^-n\\([0-9]+\\)?$" it) + magit-buffer-log-args) + (string-to-number (match-string 1 it)))) + +;;;; Mode Commands + +(defun magit-log-bury-buffer (&optional arg) + "Bury the current buffer or the revision buffer in the same frame. +Like `magit-mode-bury-buffer' (which see) but with a negative +prefix argument instead bury the revision buffer, provided it +is displayed in the current frame." + (interactive "p") + (if (< arg 0) + (let* ((buf (magit-get-mode-buffer 'magit-revision-mode)) + (win (and buf (get-buffer-window buf (selected-frame))))) + (if win + (with-selected-window win + (with-current-buffer buf + (magit-mode-bury-buffer (> (abs arg) 1)))) + (user-error "No revision buffer in this frame"))) + (magit-mode-bury-buffer (> arg 1)))) + +;;;###autoload +(defun magit-log-move-to-parent (&optional n) + "Move to the Nth parent of the current commit." + (interactive "p") + (when (derived-mode-p 'magit-log-mode) + (when (magit-section-match 'commit) + (let* ((section (magit-current-section)) + (parent-rev (format "%s^%s" (oref section value) (or n 1)))) + (if-let ((parent-hash (magit-rev-parse "--short" parent-rev))) + (if-let ((parent (--first (equal (oref it value) + parent-hash) + (magit-section-siblings section 'next)))) + (magit-section-goto parent) + (user-error + (substitute-command-keys + (concat "Parent " parent-hash " not found. Try typing " + "\\[magit-log-double-commit-limit] first")))) + (user-error "Parent %s does not exist" parent-rev)))))) + +;;; Log Mode + +(defvar magit-log-disable-graph-hack-args + '("-G" "--grep" "--author") + "Arguments which disable the graph speedup hack.") + +(defvar magit-log-mode-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map magit-mode-map) + (define-key map "\C-c\C-b" 'magit-go-backward) + (define-key map "\C-c\C-f" 'magit-go-forward) + (define-key map "\C-c\C-n" 'magit-log-move-to-parent) + (define-key map "=" 'magit-log-toggle-commit-limit) + (define-key map "+" 'magit-log-double-commit-limit) + (define-key map "-" 'magit-log-half-commit-limit) + (define-key map "q" 'magit-log-bury-buffer) + map) + "Keymap for `magit-log-mode'.") + +(define-derived-mode magit-log-mode magit-mode "Magit Log" + "Mode for looking at Git log. + +This mode is documented in info node `(magit)Log Buffer'. + +\\\ +Type \\[magit-refresh] to refresh the current buffer. +Type \\[magit-visit-thing] or \\[magit-diff-show-or-scroll-up] \ +to visit the commit at point. + +Type \\[magit-branch] to see available branch commands. +Type \\[magit-merge] to merge the branch or commit at point. +Type \\[magit-cherry-pick] to apply the commit at point. +Type \\[magit-reset] to reset `HEAD' to the commit at point. + +\\{magit-log-mode-map}" + :group 'magit-log + (hack-dir-local-variables-non-file-buffer) + (setq imenu-prev-index-position-function + 'magit-imenu--log-prev-index-position-function) + (setq imenu-extract-index-name-function + 'magit-imenu--log-extract-index-name-function)) + +(put 'magit-log-mode 'magit-log-default-arguments + '("--graph" "-n256" "--decorate")) + +(defun magit-log-setup-buffer (revs args files &optional locked focus) + (require 'magit) + (with-current-buffer + (magit-setup-buffer #'magit-log-mode locked + (magit-buffer-revisions revs) + (magit-buffer-log-args args) + (magit-buffer-log-files files)) + (when (if focus + (magit-log-goto-commit-section focus) + (magit-log-goto-same-commit)) + (magit-section-update-highlight)) + (current-buffer))) + +(defun magit-log-refresh-buffer () + (let ((revs magit-buffer-revisions) + (args magit-buffer-log-args) + (files magit-buffer-log-files)) + (magit-set-header-line-format + (funcall magit-log-header-line-function revs args files)) + (if (= (length files) 1) + (unless (magit-file-tracked-p (car files)) + (setq args (cons "--full-history" args))) + (setq args (remove "--follow" args))) + (when (--any-p (string-match-p + (concat "^" (regexp-opt magit-log-remove-graph-args)) it) + args) + (setq args (remove "--graph" args))) + (unless (member "--graph" args) + (setq args (remove "--color" args))) + (when-let ((limit (magit-log-get-commit-limit)) + (limit (* 2 limit)) ; increase odds for complete graph + (count (and (= (length revs) 1) + (> limit 1024) ; otherwise it's fast enough + (setq revs (car revs)) + (not (string-match-p "\\.\\." revs)) + (not (member revs '("--all" "--branches"))) + (-none-p (lambda (arg) + (--any-p (string-prefix-p it arg) + magit-log-disable-graph-hack-args)) + args) + (magit-git-string "rev-list" "--count" + "--first-parent" args revs)))) + (setq revs (if (< (string-to-number count) limit) + revs + (format "%s~%s..%s" revs limit revs)))) + (magit-insert-section (logbuf) + (magit-insert-log revs args files)))) + +(cl-defmethod magit-buffer-value (&context (major-mode magit-log-mode)) + (append magit-buffer-revisions + (if (and magit-buffer-revisions magit-buffer-log-files) + (cons "--" magit-buffer-log-files) + magit-buffer-log-files))) + +(defun magit-log-header-line-arguments (revs args files) + "Return string describing some of the used arguments." + (mapconcat (lambda (arg) + (if (string-match-p " " arg) + (prin1 arg) + arg)) + `("git" "log" ,@args ,@revs "--" ,@files) + " ")) + +(defun magit-log-header-line-sentence (revs args files) + "Return string containing all arguments." + (concat "Commits in " + (mapconcat #'identity revs " ") + (and (member "--reverse" args) + " in reverse") + (and files (concat " touching " + (mapconcat 'identity files " "))) + (--some (and (string-prefix-p "-L" it) + (concat " " it)) + args))) + +(defun magit-insert-log (revs &optional args files) + "Insert a log section. +Do not add this to a hook variable." + (let ((magit-git-global-arguments + (remove "--literal-pathspecs" magit-git-global-arguments))) + (magit-git-wash (apply-partially #'magit-log-wash-log 'log) + "log" + (format "--format=%s%%h%%x00%s%%x00%s%%x00%%aN%%x00%s%%x00%%s%s" + (if (and (member "--left-right" args) + (not (member "--graph" args))) + "%m " + "") + (if (member "--decorate" args) "%D" "") + (if (member "--show-signature" args) + (progn (setq args (remove "--show-signature" args)) "%G?") + "") + (if magit-log-margin-show-committer-date "%ct" "%at") + (if (member "++header" args) + (if (member "--graph" (setq args (remove "++header" args))) + (concat "\n" magit-log-revision-headers-format "\n") + (concat "\n" magit-log-revision-headers-format "\n")) + "")) + (progn + (--when-let (--first (string-match "^\\+\\+order=\\(.+\\)$" it) args) + (setq args (cons (format "--%s-order" (match-string 1 it)) + (remove it args)))) + (when (member "--decorate" args) + (setq args (cons "--decorate=full" (remove "--decorate" args)))) + (when (member "--reverse" args) + (setq args (remove "--graph" args))) + args) + "--use-mailmap" "--no-prefix" revs "--" files))) + +(defvar magit-commit-section-map + (let ((map (make-sparse-keymap))) + (define-key map [remap magit-visit-thing] 'magit-show-commit) + (define-key map "a" 'magit-cherry-apply) + map) + "Keymap for `commit' sections.") + +(defvar magit-module-commit-section-map + (let ((map (make-sparse-keymap))) + (define-key map [remap magit-visit-thing] 'magit-show-commit) + map) + "Keymap for `module-commit' sections.") + +(defconst magit-log-heading-re + (concat "^" + "\\(?4:[-_/|\\*o<>. ]*\\)" ; graph + "\\(?1:[0-9a-fA-F]+\\)?\0" ; sha1 + "\\(?3:[^\0\n]+\\)?\0" ; refs + "\\(?7:[BGUXYREN]\\)?\0" ; gpg + "\\(?5:[^\0\n]*\\)\0" ; author + ;; Note: Date is optional because, prior to Git v2.19.0, + ;; `git rebase -i --root` corrupts the root's author date. + "\\(?6:[^\0\n]*\\)\0" ; date + "\\(?2:.*\\)$")) ; msg + +(defconst magit-log-cherry-re + (concat "^" + "\\(?8:[-+]\\) " ; cherry + "\\(?1:[0-9a-fA-F]+\\) " ; sha1 + "\\(?2:.*\\)$")) ; msg + +(defconst magit-log-module-re + (concat "^" + "\\(?:\\(?11:[<>]\\) \\)?" ; side + "\\(?1:[0-9a-fA-F]+\\) " ; sha1 + "\\(?2:.*\\)$")) ; msg + +(defconst magit-log-bisect-vis-re + (concat "^" + "\\(?4:[-_/|\\*o<>. ]*\\)" ; graph + "\\(?1:[0-9a-fA-F]+\\)?\0" ; sha1 + "\\(?3:[^\0\n]+\\)?\0" ; refs + "\\(?2:.*\\)$")) ; msg + +(defconst magit-log-bisect-log-re + (concat "^# " + "\\(?3:bad:\\|skip:\\|good:\\) " ; "refs" + "\\[\\(?1:[^]\n]+\\)\\] " ; sha1 + "\\(?2:.*\\)$")) ; msg + +(defconst magit-log-reflog-re + (concat "^" + "\\(?1:[^\0\n]+\\)\0" ; sha1 + "\\(?5:[^\0\n]*\\)\0" ; author + "\\(?:\\(?:[^@\n]+@{\\(?6:[^}\n]+\\)}\0" ; date + "\\(?10:merge \\|autosave \\|restart \\|[^:\n]+: \\)?" ; refsub + "\\(?2:.*\\)?\\)\\|\0\\)$")) ; msg + +(defconst magit-reflog-subject-re + (concat "\\(?1:[^ ]+\\) ?" ; command + "\\(?2:\\(?: ?-[^ ]+\\)+\\)?" ; option + "\\(?: ?(\\(?3:[^)]+\\))\\)?")) ; type + +(defconst magit-log-stash-re + (concat "^" + "\\(?1:[^\0\n]+\\)\0" ; "sha1" + "\\(?5:[^\0\n]*\\)\0" ; author + "\\(?6:[^\0\n]+\\)\0" ; date + "\\(?2:.*\\)$")) ; msg + +(defvar magit-log-count nil) + +(defvar magit-log-format-message-function 'magit-log-propertize-keywords) + +(defun magit-log-wash-log (style args) + (setq args (-flatten args)) + (when (and (member "--graph" args) + (member "--color" args)) + (let ((ansi-color-apply-face-function + (lambda (beg end face) + (put-text-property beg end 'font-lock-face + (or face 'magit-log-graph))))) + (ansi-color-apply-on-region (point-min) (point-max)))) + (when (eq style 'cherry) + (reverse-region (point-min) (point-max))) + (let ((magit-log-count 0)) + (magit-wash-sequence (apply-partially 'magit-log-wash-rev style + (magit-abbrev-length))) + (if (derived-mode-p 'magit-log-mode 'magit-reflog-mode) + (when (eq magit-log-count (magit-log-get-commit-limit)) + (magit-insert-section (longer) + (insert-text-button + (substitute-command-keys + (format "Type \\<%s>\\[%s] to show more history" + 'magit-log-mode-map + 'magit-log-double-commit-limit)) + 'action (lambda (_button) + (magit-log-double-commit-limit)) + 'follow-link t + 'mouse-face 'magit-section-highlight))) + (insert ?\n)))) + +(cl-defun magit-log-wash-rev (style abbrev) + (when (derived-mode-p 'magit-log-mode 'magit-reflog-mode) + (cl-incf magit-log-count)) + (looking-at (pcase style + (`log magit-log-heading-re) + (`cherry magit-log-cherry-re) + (`module magit-log-module-re) + (`reflog magit-log-reflog-re) + (`stash magit-log-stash-re) + (`bisect-vis magit-log-bisect-vis-re) + (`bisect-log magit-log-bisect-log-re))) + (magit-bind-match-strings + (hash msg refs graph author date gpg cherry _ refsub side) nil + (setq msg (substring-no-properties msg)) + (when refs + (setq refs (substring-no-properties refs))) + (let ((align (or (eq style 'cherry) + (not (member "--stat" magit-buffer-log-args)))) + (non-graph-re (if (eq style 'bisect-vis) + magit-log-bisect-vis-re + magit-log-heading-re))) + (magit-delete-line) + ;; If the reflog entries have been pruned, the output of `git + ;; reflog show' includes a partial line that refers to the hash + ;; of the youngest expired reflog entry. + (when (and (eq style 'reflog) (not date)) + (cl-return-from magit-log-wash-rev t)) + (magit-insert-section section (commit hash) + (pcase style + (`stash (oset section type 'stash)) + (`module (oset section type 'module-commit)) + (`bisect-log (setq hash (magit-rev-parse "--short" hash)))) + (when cherry + (when (and (derived-mode-p 'magit-refs-mode) + magit-refs-show-commit-count) + (insert (make-string (1- magit-refs-focus-column-width) ?\s))) + (insert (propertize cherry 'font-lock-face + (if (string= cherry "-") + 'magit-cherry-equivalent + 'magit-cherry-unmatched))) + (insert ?\s)) + (when side + (insert (propertize side 'font-lock-face + (if (string= side "<") + 'magit-cherry-equivalent + 'magit-cherry-unmatched))) + (insert ?\s)) + (when align + (insert (propertize hash 'font-lock-face 'magit-hash) ?\s)) + (when graph + (insert graph)) + (unless align + (insert (propertize hash 'font-lock-face 'magit-hash) ?\s)) + (when (and refs (not magit-log-show-refname-after-summary)) + (insert (magit-format-ref-labels refs) ?\s)) + (when (eq style 'reflog) + (insert (format "%-2s " (1- magit-log-count))) + (when refsub + (insert (magit-reflog-format-subject + (substring refsub 0 (if (string-match-p ":" refsub) -2 -1)))))) + (when msg + (when gpg + (setq msg (propertize msg 'font-lock-face + (pcase (aref gpg 0) + (?G 'magit-signature-good) + (?B 'magit-signature-bad) + (?U 'magit-signature-untrusted) + (?X 'magit-signature-expired) + (?Y 'magit-signature-expired-key) + (?R 'magit-signature-revoked) + (?E 'magit-signature-error))))) + (insert (funcall magit-log-format-message-function hash msg))) + (when (and refs magit-log-show-refname-after-summary) + (insert ?\s) + (insert (magit-format-ref-labels refs))) + (insert ?\n) + (when (memq style '(log reflog stash)) + (goto-char (line-beginning-position)) + (when (and refsub + (string-match "\\`\\([^ ]\\) \\+\\(..\\)\\(..\\)" date)) + (setq date (+ (string-to-number (match-string 1 date)) + (* (string-to-number (match-string 2 date)) 60 60) + (* (string-to-number (match-string 3 date)) 60)))) + (save-excursion + (backward-char) + (magit-log-format-margin hash author date))) + (when (and (eq style 'cherry) + (magit-buffer-margin-p)) + (save-excursion + (backward-char) + (apply #'magit-log-format-margin hash + (split-string (magit-rev-format "%aN%x00%ct" hash) "\0")))) + (when (and graph + (not (eobp)) + (not (looking-at non-graph-re))) + (when (looking-at "") + (magit-insert-heading) + (delete-char 1) + (magit-insert-section (commit-header) + (forward-line) + (magit-insert-heading) + (re-search-forward "") + (backward-delete-char 1) + (forward-char) + (insert ?\n)) + (delete-char 1)) + (if (looking-at "^\\(---\\|\n\s\\|\ndiff\\)") + (let ((limit (save-excursion + (and (re-search-forward non-graph-re nil t) + (match-beginning 0))))) + (unless (oref magit-insert-section--current content) + (magit-insert-heading)) + (delete-char (if (looking-at "\n") 1 4)) + (magit-diff-wash-diffs (list "--stat") limit)) + (when align + (setq align (make-string (1+ abbrev) ? ))) + (when (and (not (eobp)) (not (looking-at non-graph-re))) + (when align + (setq align (make-string (1+ abbrev) ? ))) + (while (and (not (eobp)) (not (looking-at non-graph-re))) + (when align + (save-excursion (insert align))) + (magit-make-margin-overlay) + (forward-line)) + ;; When `--format' is used and its value isn't one of the + ;; predefined formats, then `git-log' does not insert a + ;; separator line. + (save-excursion + (forward-line -1) + (looking-at "[-_/|\\*o<>. ]*")) + (setq graph (match-string 0)) + (unless (string-match-p "[/\\]" graph) + (insert graph ?\n)))))))) + t) + +(defun magit-log-propertize-keywords (_rev msg) + (let ((start 0)) + (when (string-match "^\\(squash\\|fixup\\)! " msg start) + (setq start (match-end 0)) + (magit--put-face (match-beginning 0) (match-end 0) + 'magit-keyword-squash msg)) + (while (string-match "\\[[^[]*\\]" msg start) + (setq start (match-end 0)) + (when magit-log-highlight-keywords + (magit--put-face (match-beginning 0) (match-end 0) + 'magit-keyword msg)))) + msg) + +(defun magit-log-maybe-show-more-commits (section) + "When point is at the end of a log buffer, insert more commits. + +Log buffers end with a button \"Type + to show more history\". +When the use of a section movement command puts point on that +button, then automatically show more commits, without the user +having to press \"+\". + +This function is called by `magit-section-movement-hook' and +exists mostly for backward compatibility reasons." + (when (and (eq (oref section type) 'longer) + magit-log-auto-more) + (magit-log-double-commit-limit) + (forward-line -1) + (magit-section-forward))) + +(defvar magit--update-revision-buffer nil) + +(defun magit-log-maybe-update-revision-buffer (&optional _) + "When moving in a log or cherry buffer, update the revision buffer. +If there is no revision buffer in the same frame, then do nothing." + (when (derived-mode-p 'magit-log-mode 'magit-cherry-mode 'magit-reflog-mode) + (magit--maybe-update-revision-buffer))) + +(defun magit--maybe-update-revision-buffer () + (when-let ((commit (magit-section-value-if 'commit)) + (buffer (magit-get-mode-buffer 'magit-revision-mode nil t))) + (if magit--update-revision-buffer + (setq magit--update-revision-buffer (list commit buffer)) + (setq magit--update-revision-buffer (list commit buffer)) + (run-with-idle-timer + magit-update-other-window-delay nil + (let ((args (with-current-buffer buffer + (let ((magit-direct-use-buffer-arguments 'selected)) + (magit-show-commit--arguments))))) + (lambda () + (pcase-let ((`(,rev ,buf) magit--update-revision-buffer)) + (setq magit--update-revision-buffer nil) + (when (buffer-live-p buf) + (let ((magit-display-buffer-noselect t)) + (apply #'magit-show-commit rev args)))) + (setq magit--update-revision-buffer nil))))))) + +(defvar magit--update-blob-buffer nil) + +(defun magit-log-maybe-update-blob-buffer (&optional _) + "When moving in a log or cherry buffer, update the blob buffer. +If there is no blob buffer in the same frame, then do nothing." + (when (derived-mode-p 'magit-log-mode 'magit-cherry-mode 'magit-reflog-mode) + (magit--maybe-update-blob-buffer))) + +(defun magit--maybe-update-blob-buffer () + (when-let ((commit (magit-section-value-if 'commit)) + (buffer (--first (with-current-buffer it + (eq revert-buffer-function + 'magit-revert-rev-file-buffer)) + (mapcar #'window-buffer (window-list))))) + (if magit--update-blob-buffer + (setq magit--update-blob-buffer (list commit buffer)) + (setq magit--update-blob-buffer (list commit buffer)) + (run-with-idle-timer + magit-update-other-window-delay nil + (lambda () + (pcase-let ((`(,rev ,buf) magit--update-blob-buffer)) + (setq magit--update-blob-buffer nil) + (when (buffer-live-p buf) + (with-selected-window (get-buffer-window buf) + (with-current-buffer buf + (save-excursion + (magit-blob-visit (list (magit-rev-parse rev) + (magit-file-relative-name + magit-buffer-file-name)) + (line-number-at-pos)))))))))))) + +(defun magit-log-goto-commit-section (rev) + (let ((abbrev (magit-rev-format "%h" rev))) + (when-let ((section (--first (equal (oref it value) abbrev) + (oref magit-root-section children)))) + (goto-char (oref section start))))) + +(defun magit-log-goto-same-commit () + (when (and magit-previous-section + (magit-section-match '(commit branch) + magit-previous-section)) + (magit-log-goto-commit-section (oref magit-previous-section value)))) + +;;; Log Margin + +(defvar-local magit-log-margin-show-shortstat nil) + +(defun magit-toggle-log-margin-style () + "Toggle between the regular and the shortstat margin style. +The shortstat style is experimental and rather slow." + (interactive) + (setq magit-log-margin-show-shortstat + (not magit-log-margin-show-shortstat)) + (magit-set-buffer-margin nil t)) + +(defun magit-log-format-margin (rev author date) + (when (magit-margin-option) + (if magit-log-margin-show-shortstat + (magit-log-format-shortstat-margin rev) + (magit-log-format-author-margin author date)))) + +(defun magit-log-format-author-margin (author date &optional previous-line) + (pcase-let ((`(,_ ,style ,width ,details ,details-width) + (or magit-buffer-margin + (symbol-value (magit-margin-option))))) + (magit-make-margin-overlay + (concat (and details + (concat (magit--propertize-face + (truncate-string-to-width + (or author "") + details-width + nil ?\s (make-string 1 magit-ellipsis)) + 'magit-log-author) + " ")) + (magit--propertize-face + (if (stringp style) + (format-time-string + style + (seconds-to-time (string-to-number date))) + (pcase-let* ((abbr (eq style 'age-abbreviated)) + (`(,cnt ,unit) (magit--age date abbr))) + (format (format (if abbr "%%2i%%-%ic" "%%2i %%-%is") + (- width (if details (1+ details-width) 0))) + cnt unit))) + 'magit-log-date)) + previous-line))) + +(defun magit-log-format-shortstat-margin (rev) + (magit-make-margin-overlay + (if-let ((line (and rev (magit-git-string + "show" "--format=" "--shortstat" rev)))) + (if (string-match "\ +\\([0-9]+\\) files? changed, \ +\\(?:\\([0-9]+\\) insertions?(\\+)\\)?\ +\\(?:\\(?:, \\)?\\([0-9]+\\) deletions?(-)\\)?\\'" line) + (magit-bind-match-strings (files add del) line + (format + "%5s %5s%4s" + (if add + (magit--propertize-face (format "%s+" add) + 'magit-diffstat-added) + "") + (if del + (magit--propertize-face (format "%s-" del) + 'magit-diffstat-removed) + "") + files)) + "") + ""))) + +(defun magit-log-margin-width (style details details-width) + (if magit-log-margin-show-shortstat + 16 + (+ (if details (1+ details-width) 0) + (if (stringp style) + (length (format-time-string style)) + (+ 2 ; two digits + 1 ; trailing space + (if (eq style 'age-abbreviated) + 1 ; single character + (+ 1 ; gap after digits + (apply #'max (--map (max (length (nth 1 it)) + (length (nth 2 it))) + magit--age-spec))))))))) + +;;; Select Mode + +(defvar magit-log-select-mode-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map magit-log-mode-map) + (define-key map "\C-c\C-b" 'undefined) + (define-key map "\C-c\C-f" 'undefined) + (define-key map "." 'magit-log-select-pick) + (define-key map "e" 'magit-log-select-pick) + (define-key map "\C-c\C-c" 'magit-log-select-pick) + (define-key map "q" 'magit-log-select-quit) + (define-key map "\C-c\C-k" 'magit-log-select-quit) + map) + "Keymap for `magit-log-select-mode'.") + +(put 'magit-log-select-pick :advertised-binding [?\C-c ?\C-c]) +(put 'magit-log-select-quit :advertised-binding [?\C-c ?\C-k]) + +(define-derived-mode magit-log-select-mode magit-log-mode "Magit Select" + "Mode for selecting a commit from history. + +This mode is documented in info node `(magit)Select from Log'. + +\\\ +Type \\[magit-refresh] to refresh the current buffer. +Type \\[magit-visit-thing] or \\[magit-diff-show-or-scroll-up] \ +to visit the commit at point. + +\\\ +Type \\[magit-log-select-pick] to select the commit at point. +Type \\[magit-log-select-quit] to abort without selecting a commit." + :group 'magit-log + (hack-dir-local-variables-non-file-buffer)) + +(put 'magit-log-select-mode 'magit-log-default-arguments + '("--graph" "-n256" "--decorate")) + +(defun magit-log-select-setup-buffer (revs args) + (magit-setup-buffer #'magit-log-select-mode nil + (magit-buffer-revisions revs) + (magit-buffer-log-args args))) + +(defun magit-log-select-refresh-buffer () + (magit-insert-section (logbuf) + (magit-insert-log magit-buffer-revisions + magit-buffer-log-args))) + +(cl-defmethod magit-buffer-value (&context (major-mode magit-log-select-mode)) + magit-buffer-revisions) + +(defvar-local magit-log-select-pick-function nil) +(defvar-local magit-log-select-quit-function nil) + +(defun magit-log-select (pick &optional msg quit branch args initial) + (declare (indent defun)) + (unless initial + (setq initial (magit-commit-at-point))) + (magit-log-select-setup-buffer + (or branch (magit-get-current-branch) "HEAD") + (append args + (car (magit-log--get-value 'magit-log-select-mode + magit-direct-use-buffer-arguments)))) + (when initial + (magit-log-goto-commit-section initial)) + (setq magit-log-select-pick-function pick) + (setq magit-log-select-quit-function quit) + (when magit-log-select-show-usage + (let ((pick (propertize (substitute-command-keys + "\\[magit-log-select-pick]") + 'font-lock-face + 'magit-header-line-key)) + (quit (propertize (substitute-command-keys + "\\[magit-log-select-quit]") + 'font-lock-face + 'magit-header-line-key))) + (setq msg (format-spec + (if msg + (if (string-suffix-p "," msg) + (concat msg " or %q to abort") + msg) + "Type %p to select commit at point, or %q to abort") + `((?p . ,pick) + (?q . ,quit))))) + (magit--add-face-text-property + 0 (length msg) 'magit-header-line-log-select t msg) + (when (memq magit-log-select-show-usage '(both header-line)) + (magit-set-header-line-format msg)) + (when (memq magit-log-select-show-usage '(both echo-area)) + (message "%s" (substring-no-properties msg))))) + +(defun magit-log-select-pick () + "Select the commit at point and act on it. +Call `magit-log-select-pick-function' with the selected +commit as argument." + (interactive) + (let ((fun magit-log-select-pick-function) + (rev (magit-commit-at-point))) + (magit-mode-bury-buffer 'kill) + (funcall fun rev))) + +(defun magit-log-select-quit () + "Abort selecting a commit, don't act on any commit." + (interactive) + (magit-mode-bury-buffer 'kill) + (when magit-log-select-quit-function + (funcall magit-log-select-quit-function))) + +;;; Cherry Mode + +(defvar magit-cherry-mode-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map magit-mode-map) + (define-key map "q" 'magit-log-bury-buffer) + (define-key map "L" 'magit-margin-settings) + map) + "Keymap for `magit-cherry-mode'.") + +(define-derived-mode magit-cherry-mode magit-mode "Magit Cherry" + "Mode for looking at commits not merged upstream. + +\\\ +Type \\[magit-refresh] to refresh the current buffer. +Type \\[magit-visit-thing] or \\[magit-diff-show-or-scroll-up] \ +to visit the commit at point. + +Type \\[magit-cherry-pick] to apply the commit at point. + +\\{magit-cherry-mode-map}" + :group 'magit-log + (hack-dir-local-variables-non-file-buffer) + (setq imenu-create-index-function + 'magit-imenu--cherry-create-index-function)) + +(defun magit-cherry-setup-buffer (head upstream) + (magit-setup-buffer #'magit-cherry-mode nil + (magit-buffer-refname head) + (magit-buffer-upstream upstream) + (magit-buffer-range (concat upstream ".." head)))) + +(defun magit-cherry-refresh-buffer () + (magit-insert-section (cherry) + (magit-run-section-hook 'magit-cherry-sections-hook))) + +(cl-defmethod magit-buffer-value (&context (major-mode magit-cherry-mode)) + magit-buffer-range) + +;;;###autoload +(defun magit-cherry (head upstream) + "Show commits in a branch that are not merged in the upstream branch." + (interactive + (let ((head (magit-read-branch "Cherry head"))) + (list head (magit-read-other-branch "Cherry upstream" head + (magit-get-upstream-branch head))))) + (require 'magit) + (magit-cherry-setup-buffer head upstream)) + +(defun magit-insert-cherry-headers () + "Insert headers appropriate for `magit-cherry-mode' buffers." + (let ((branch (propertize magit-buffer-refname + 'font-lock-face 'magit-branch-local)) + (upstream (propertize magit-buffer-upstream 'font-lock-face + (if (magit-local-branch-p magit-buffer-upstream) + 'magit-branch-local + 'magit-branch-remote)))) + (magit-insert-head-branch-header branch) + (magit-insert-upstream-branch-header branch upstream "Upstream: ") + (insert ?\n))) + +(defun magit-insert-cherry-commits () + "Insert commit sections into a `magit-cherry-mode' buffer." + (magit-insert-section (cherries) + (magit-insert-heading "Cherry commits:") + (magit-git-wash (apply-partially 'magit-log-wash-log 'cherry) + "cherry" "-v" "--abbrev" + magit-buffer-upstream + magit-buffer-refname))) + +;;; Log Sections +;;;; Standard Log Sections + +(defvar magit-unpulled-section-map + (let ((map (make-sparse-keymap))) + (define-key map [remap magit-visit-thing] 'magit-diff-dwim) + map) + "Keymap for `unpulled' sections.") + +(magit-define-section-jumper magit-jump-to-unpulled-from-upstream + "Unpulled from @{upstream}" unpulled "..@{upstream}") + +(defun magit-insert-unpulled-from-upstream () + "Insert commits that haven't been pulled from the upstream yet." + (when-let ((upstream (magit-get-upstream-branch))) + (magit-insert-section (unpulled "..@{upstream}" t) + (magit-insert-heading + (format (propertize "Unpulled from %s." + 'font-lock-face 'magit-section-heading) + upstream)) + (magit-insert-log "..@{upstream}" magit-buffer-log-args) + (magit-log-insert-child-count)))) + +(magit-define-section-jumper magit-jump-to-unpulled-from-pushremote + "Unpulled from " unpulled + (concat ".." (magit-get-push-branch))) + +(defun magit-insert-unpulled-from-pushremote () + "Insert commits that haven't been pulled from the push-remote yet." + (--when-let (magit-get-push-branch) + (unless (and (equal (magit-rev-name it) + (magit-rev-name "@{upstream}")) + (or (memq 'magit-insert-unpulled-from-upstream + magit-status-sections-hook) + (memq 'magit-insert-unpulled-from-upstream-or-recent + magit-status-sections-hook))) + (magit-insert-section (unpulled (concat ".." it) t) + (magit-insert-heading + (format (propertize "Unpulled from %s." + 'font-lock-face 'magit-section-heading) + (propertize it 'font-lock-face 'magit-branch-remote))) + (magit-insert-log (concat ".." it) magit-buffer-log-args) + (magit-log-insert-child-count))))) + +(defvar magit-unpushed-section-map + (let ((map (make-sparse-keymap))) + (define-key map [remap magit-visit-thing] 'magit-diff-dwim) + map) + "Keymap for `unpushed' sections.") + +(magit-define-section-jumper magit-jump-to-unpushed-to-upstream + "Unpushed to @{upstream}" unpushed "@{upstream}..") + +(defun magit-insert-unpushed-to-upstream-or-recent () + "Insert section showing unpushed or other recent commits. +If an upstream is configured for the current branch and it is +behind of the current branch, then show the commits that have +not yet been pushed into the upstream branch. If no upstream is +configured or if the upstream is not behind of the current branch, +then show the last `magit-log-section-commit-count' commits." + (let ((upstream (magit-get-upstream-branch))) + (if (or (not upstream) + (magit-rev-ancestor-p "HEAD" upstream)) + (magit-insert-recent-commits 'unpushed "@{upstream}..") + (magit-insert-unpushed-to-upstream)))) + +(defun magit-insert-unpushed-to-upstream () + "Insert commits that haven't been pushed to the upstream yet." + (when (magit-git-success "rev-parse" "@{upstream}") + (magit-insert-section (unpushed "@{upstream}..") + (magit-insert-heading + (format (propertize "Unmerged into %s." + 'font-lock-face 'magit-section-heading) + (magit-get-upstream-branch))) + (magit-insert-log "@{upstream}.." magit-buffer-log-args) + (magit-log-insert-child-count)))) + +(defun magit-insert-recent-commits (&optional type value) + "Insert section showing recent commits. +Show the last `magit-log-section-commit-count' commits." + (let* ((start (format "HEAD~%s" magit-log-section-commit-count)) + (range (and (magit-rev-verify start) + (concat start "..HEAD")))) + (magit-insert-section ((eval (or type 'recent)) + (or value range) + t) + (magit-insert-heading "Recent commits") + (magit-insert-log range + (cons (format "-n%d" magit-log-section-commit-count) + (--remove (string-prefix-p "-n" it) + magit-buffer-log-args)))))) + +(magit-define-section-jumper magit-jump-to-unpushed-to-pushremote + "Unpushed to " unpushed + (concat (magit-get-push-branch) "..")) + +(defun magit-insert-unpushed-to-pushremote () + "Insert commits that haven't been pushed to the push-remote yet." + (--when-let (magit-get-push-branch) + (unless (and (equal (magit-rev-name it) + (magit-rev-name "@{upstream}")) + (or (memq 'magit-insert-unpushed-to-upstream + magit-status-sections-hook) + (memq 'magit-insert-unpushed-to-upstream-or-recent + magit-status-sections-hook))) + (magit-insert-section (unpushed (concat it "..") t) + (magit-insert-heading + (format (propertize "Unpushed to %s." + 'font-lock-face 'magit-section-heading) + (propertize it 'font-lock-face 'magit-branch-remote))) + (magit-insert-log (concat it "..") magit-buffer-log-args) + (magit-log-insert-child-count))))) + +(defun magit-log-insert-child-count () + (when magit-section-show-child-count + (let ((count (length (oref magit-insert-section--current children)))) + (when (> count 0) + (when (= count (magit-log-get-commit-limit)) + (setq count (format "%s+" count))) + (save-excursion + (goto-char (- (oref magit-insert-section--current content) 2)) + (insert (format " (%s)" count)) + (delete-char 1)))))) + +;;;; Auxiliary Log Sections + +(defun magit-insert-unpulled-cherries () + "Insert section showing unpulled commits. +Like `magit-insert-unpulled-from-upstream' but prefix each commit +which has not been applied yet (i.e. a commit with a patch-id +not shared with any local commit) with \"+\", and all others with +\"-\"." + (when (magit-git-success "rev-parse" "@{upstream}") + (magit-insert-section (unpulled "..@{upstream}") + (magit-insert-heading "Unpulled commits:") + (magit-git-wash (apply-partially 'magit-log-wash-log 'cherry) + "cherry" "-v" (magit-abbrev-arg) + (magit-get-current-branch) "@{upstream}")))) + +(defun magit-insert-unpushed-cherries () + "Insert section showing unpushed commits. +Like `magit-insert-unpushed-to-upstream' but prefix each commit +which has not been applied to upstream yet (i.e. a commit with +a patch-id not shared with any upstream commit) with \"+\", and +all others with \"-\"." + (when (magit-git-success "rev-parse" "@{upstream}") + (magit-insert-section (unpushed "@{upstream}..") + (magit-insert-heading "Unpushed commits:") + (magit-git-wash (apply-partially 'magit-log-wash-log 'cherry) + "cherry" "-v" (magit-abbrev-arg) "@{upstream}")))) + +;;; _ +(provide 'magit-log) +;;; magit-log.el ends here diff --git a/elpa/magit-20191122.2040/magit-log.elc b/elpa/magit-20191122.2040/magit-log.elc new file mode 100644 index 0000000000000000000000000000000000000000..06c32f7a0a519093af4710c50617da82221afea8 GIT binary patch literal 98207 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 HbI1OF{N0sT literal 0 HcmV?d00001 diff --git a/elpa/magit-20191122.2040/magit-margin.el b/elpa/magit-20191122.2040/magit-margin.el new file mode 100644 index 00000000..b3137c68 --- /dev/null +++ b/elpa/magit-20191122.2040/magit-margin.el @@ -0,0 +1,241 @@ +;;; magit-margin.el --- margins in Magit buffers -*- lexical-binding: t -*- + +;; Copyright (C) 2010-2019 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; This library implements support for showing additional information +;; in the margins of Magit buffers. Currently this is only used for +;; commits, for which the committer date or age, and optionally the +;; author name are shown. + +;;; Code: + +(require 'dash) + +(eval-when-compile + (require 'subr-x)) + +(require 'magit-section) +(require 'magit-transient) +(require 'magit-mode) + +(defgroup magit-margin nil + "Information Magit displays in the margin. + +You can change the STYLE and AUTHOR-WIDTH of all `magit-*-margin' +options to the same values by customizing `magit-log-margin' +*before* `magit' is loaded. If you do that, then the respective +values for the other options will default to what you have set +for that variable. Likewise if you set `magit-log-margin's INIT +to nil, then that is used in the default of all other options. But +setting it to t, i.e. re-enforcing the default for that option, +does not carry to other options." + :link '(info-link "(magit)Log Margin") + :group 'magit-log) + +(defvar-local magit-buffer-margin nil) +(put 'magit-buffer-margin 'permanent-local t) + +(defvar-local magit-set-buffer-margin-refresh nil) + +(defvar magit--age-spec) + +;;; Commands + +(define-transient-command magit-margin-settings () + "Change what information is displayed in the margin." + :info-manual "(magit) Log Margin" + ["Margin" + ("L" "Toggle visibility" magit-toggle-margin) + ("l" "Cycle style" magit-cycle-margin-style) + ("d" "Toggle details" magit-toggle-margin-details) + ("v" "Change verbosity" magit-refs-set-show-commit-count + :if-derived magit-refs-mode)]) + +(defun magit-toggle-margin () + "Show or hide the Magit margin." + (interactive) + (unless (magit-margin-option) + (user-error "Magit margin isn't supported in this buffer")) + (setcar magit-buffer-margin (not (magit-buffer-margin-p))) + (magit-set-buffer-margin)) + +(defun magit-cycle-margin-style () + "Cycle style used for the Magit margin." + (interactive) + (unless (magit-margin-option) + (user-error "Magit margin isn't supported in this buffer")) + ;; This is only suitable for commit margins (there are not others). + (setf (cadr magit-buffer-margin) + (pcase (cadr magit-buffer-margin) + (`age 'age-abbreviated) + (`age-abbreviated + (let ((default (cadr (symbol-value (magit-margin-option))))) + (if (stringp default) default "%Y-%m-%d %H:%M "))) + (_ 'age))) + (magit-set-buffer-margin nil t)) + +(defun magit-toggle-margin-details () + "Show or hide details in the Magit margin." + (interactive) + (unless (magit-margin-option) + (user-error "Magit margin isn't supported in this buffer")) + (setf (nth 3 magit-buffer-margin) + (not (nth 3 magit-buffer-margin))) + (magit-set-buffer-margin nil t)) + +;;; Core + +(defun magit-buffer-margin-p () + (car magit-buffer-margin)) + +(defun magit-margin-option () + (pcase major-mode + (`magit-cherry-mode 'magit-cherry-margin) + (`magit-log-mode 'magit-log-margin) + (`magit-log-select-mode 'magit-log-select-margin) + (`magit-reflog-mode 'magit-reflog-margin) + (`magit-refs-mode 'magit-refs-margin) + (`magit-stashes-mode 'magit-stashes-margin) + (`magit-status-mode 'magit-status-margin) + (`forge-notifications-mode 'magit-status-margin))) + +(defun magit-set-buffer-margin (&optional reset refresh) + (when-let ((option (magit-margin-option))) + (let* ((default (symbol-value option)) + (default-width (nth 2 default))) + (when (or reset (not magit-buffer-margin)) + (setq magit-buffer-margin (copy-sequence default))) + (pcase-let ((`(,enable ,style ,_width ,details ,details-width) + magit-buffer-margin)) + (when (functionp default-width) + (setf (nth 2 magit-buffer-margin) + (funcall default-width style details details-width))) + (dolist (window (get-buffer-window-list nil nil 0)) + (with-selected-window window + (magit-set-window-margin window) + (if enable + (add-hook 'window-configuration-change-hook + 'magit-set-window-margin nil t) + (remove-hook 'window-configuration-change-hook + 'magit-set-window-margin t)))) + (when (and enable (or refresh magit-set-buffer-margin-refresh)) + (magit-refresh-buffer)))))) + +(defun magit-set-window-margin (&optional window) + (when (or window (setq window (get-buffer-window))) + (with-selected-window window + (set-window-margins + nil (car (window-margins)) + (and (magit-buffer-margin-p) + (nth 2 magit-buffer-margin)))))) + +(defun magit-make-margin-overlay (&optional string previous-line) + (if previous-line + (save-excursion + (forward-line -1) + (magit-make-margin-overlay string)) + ;; Don't put the overlay on the complete line to work around #1880. + (let ((o (make-overlay (1+ (line-beginning-position)) + (line-end-position) + nil t))) + (overlay-put o 'evaporate t) + (overlay-put o 'before-string + (propertize "o" 'display + (list (list 'margin 'right-margin) + (or string " "))))))) + +(defun magit-maybe-make-margin-overlay () + (when (or (magit-section-match + '(unpulled unpushed recent stashes local cherries) + magit-insert-section--current) + (and (eq major-mode 'magit-refs-mode) + (magit-section-match + '(remote commit tags) + magit-insert-section--current))) + (magit-make-margin-overlay nil t))) + +;;; Custom Support + +(defun magit-margin-set-variable (mode symbol value) + (set-default symbol value) + (message "Updating margins in %s buffers..." mode) + (dolist (buffer (buffer-list)) + (with-current-buffer buffer + (when (eq major-mode mode) + (magit-set-buffer-margin t) + (magit-refresh)))) + (message "Updating margins in %s buffers...done" mode)) + +(defconst magit-log-margin--custom-type + '(list (boolean :tag "Show margin initially") + (choice :tag "Show committer" + (string :tag "date using time-format" "%Y-%m-%d %H:%M ") + (const :tag "date's age" age) + (const :tag "date's age (abbreviated)" age-abbreviated)) + (const :tag "Calculate width using magit-log-margin-width" + magit-log-margin-width) + (boolean :tag "Show author name by default") + (integer :tag "Show author name using width"))) + +;;; Time Utilities + +(defvar magit--age-spec + `((?Y "year" "years" ,(round (* 60 60 24 365.2425))) + (?M "month" "months" ,(round (* 60 60 24 30.436875))) + (?w "week" "weeks" ,(* 60 60 24 7)) + (?d "day" "days" ,(* 60 60 24)) + (?h "hour" "hours" ,(* 60 60)) + (?m "minute" "minutes" 60) + (?s "second" "seconds" 1)) + "Time units used when formatting relative commit ages. + +The value is a list of time units, beginning with the longest. +Each element has the form (CHAR UNIT UNITS SECONDS). UNIT is the +time unit, UNITS is the plural of that unit. CHAR is a character +abbreviation. And SECONDS is the number of seconds in one UNIT. + +This is defined as a variable to make it possible to use time +units for a language other than English. It is not defined +as an option, because most other parts of Magit are always in +English.") + +(defun magit--age (date &optional abbreviate) + (cl-labels ((fn (age spec) + (pcase-let ((`(,char ,unit ,units ,weight) (car spec))) + (let ((cnt (round (/ age weight 1.0)))) + (if (or (not (cdr spec)) + (>= (/ age weight) 1)) + (list cnt (cond (abbreviate char) + ((= cnt 1) unit) + (t units))) + (fn age (cdr spec))))))) + (fn (abs (- (float-time) + (if (stringp date) + (string-to-number date) + date))) + magit--age-spec))) + +;;; _ +(provide 'magit-margin) +;;; magit-margin.el ends here diff --git a/elpa/magit-20191122.2040/magit-margin.elc b/elpa/magit-20191122.2040/magit-margin.elc new file mode 100644 index 0000000000000000000000000000000000000000..f6ed55f6760da67033e782b7173d15fa04eca42c GIT binary patch literal 8237 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 literal 0 HcmV?d00001 diff --git a/elpa/magit-20191122.2040/magit-merge.el b/elpa/magit-20191122.2040/magit-merge.el new file mode 100644 index 00000000..415d0733 --- /dev/null +++ b/elpa/magit-20191122.2040/magit-merge.el @@ -0,0 +1,302 @@ +;;; magit-merge.el --- merge functionality -*- lexical-binding: t -*- + +;; Copyright (C) 2010-2019 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; This library implements merge commands. + +;;; Code: + +(eval-when-compile + (require 'subr-x)) + +(require 'magit) +(require 'magit-diff) + +(declare-function magit-git-push "magit-push" (branch target args)) + +;;; Commands + +;;;###autoload (autoload 'magit-merge "magit" nil t) +(define-transient-command magit-merge () + "Merge branches." + :man-page "git-merge" + :incompatible '(("--ff-only" "--no-ff")) + ["Arguments" + :if-not magit-merge-in-progress-p + ("-f" "Fast-forward only" "--ff-only") + ("-n" "No fast-forward" "--no-ff") + (magit-merge:--strategy) + (5 magit-diff:--diff-algorithm :argument "--Xdiff-algorithm=") + (5 magit:--gpg-sign)] + ["Actions" + :if-not magit-merge-in-progress-p + [("m" "Merge" magit-merge-plain) + ("e" "Merge and edit message" magit-merge-editmsg) + ("n" "Merge but don't commit" magit-merge-nocommit) + ("a" "Absorb" magit-merge-absorb)] + [("p" "Preview merge" magit-merge-preview) + "" + ("s" "Squash merge" magit-merge-squash) + ("i" "Merge into" magit-merge-into)]] + ["Actions" + :if magit-merge-in-progress-p + ("m" "Commit merge" magit-commit-create) + ("a" "Abort merge" magit-merge-abort)]) + +(defun magit-merge-arguments () + (transient-args 'magit-merge)) + +(define-infix-argument magit-merge:--strategy () + :description "Strategy" + :class 'transient-option + ;; key for merge: "-s" + ;; key for cherry-pick and revert: "=s" + ;; shortarg for merge: "-s" + ;; shortarg for cherry-pick and revert: none + :key "-s" + :argument "--strategy=" + :choices '("resolve" "recursive" "octopus" "ours" "subtree")) + +;;;###autoload +(defun magit-merge-plain (rev &optional args nocommit) + "Merge commit REV into the current branch; using default message. + +Unless there are conflicts or a prefix argument is used create a +merge commit using a generic commit message and without letting +the user inspect the result. With a prefix argument pretend the +merge failed to give the user the opportunity to inspect the +merge. + +\(git merge --no-edit|--no-commit [ARGS] REV)" + (interactive (list (magit-read-other-branch-or-commit "Merge") + (magit-merge-arguments) + current-prefix-arg)) + (magit-merge-assert) + (magit-run-git-async "merge" (if nocommit "--no-commit" "--no-edit") args rev)) + +;;;###autoload +(defun magit-merge-editmsg (rev &optional args) + "Merge commit REV into the current branch; and edit message. +Perform the merge and prepare a commit message but let the user +edit it. +\n(git merge --edit --no-ff [ARGS] REV)" + (interactive (list (magit-read-other-branch-or-commit "Merge") + (magit-merge-arguments))) + (magit-merge-assert) + (cl-pushnew "--no-ff" args :test #'equal) + (apply #'magit-run-git-with-editor "merge" "--edit" + (append (delete "--ff-only" args) + (list rev)))) + +;;;###autoload +(defun magit-merge-nocommit (rev &optional args) + "Merge commit REV into the current branch; pretending it failed. +Pretend the merge failed to give the user the opportunity to +inspect the merge and change the commit message. +\n(git merge --no-commit --no-ff [ARGS] REV)" + (interactive (list (magit-read-other-branch-or-commit "Merge") + (magit-merge-arguments))) + (magit-merge-assert) + (cl-pushnew "--no-ff" args :test #'equal) + (magit-run-git-async "merge" "--no-commit" args rev)) + +;;;###autoload +(defun magit-merge-into (branch &optional args) + "Merge the current branch into BRANCH and remove the former. + +Before merging, force push the source branch to its push-remote, +provided the respective remote branch already exists, ensuring +that the respective pull-request (if any) won't get stuck on some +obsolete version of the commits that are being merged. Finally +if `forge-branch-pullreq' was used to create the merged branch, +branch, then also remove the respective remote branch." + (interactive + (list (magit-read-other-local-branch + (format "Merge `%s' into" (magit-get-current-branch)) + nil + (when-let ((upstream (magit-get-upstream-branch)) + (upstream (cdr (magit-split-branch-name upstream)))) + (and (magit-branch-p upstream) upstream))) + (magit-merge-arguments))) + (let ((current (magit-get-current-branch))) + (when (zerop (magit-call-git "checkout" branch)) + (magit--merge-absorb current args)))) + +;;;###autoload +(defun magit-merge-absorb (branch &optional args) + "Merge BRANCH into the current branch and remove the former. + +Before merging, force push the source branch to its push-remote, +provided the respective remote branch already exists, ensuring +that the respective pull-request (if any) won't get stuck on some +obsolete version of the commits that are being merged. Finally +if `forge-branch-pullreq' was used to create the merged branch, +then also remove the respective remote branch." + (interactive (list (magit-read-other-local-branch "Absorb branch") + (magit-merge-arguments))) + (magit--merge-absorb branch args)) + +(defun magit--merge-absorb (branch args) + (when (equal branch "master") + (unless (yes-or-no-p + "Do you really want to merge `master' into another branch? ") + (user-error "Abort"))) + (if-let ((target (magit-get-push-branch branch t))) + (progn + (magit-git-push branch target (list "--force-with-lease")) + (set-process-sentinel + magit-this-process + (lambda (process event) + (when (memq (process-status process) '(exit signal)) + (if (not (zerop (process-exit-status process))) + (magit-process-sentinel process event) + (process-put process 'inhibit-refresh t) + (magit-process-sentinel process event) + (magit--merge-absorb-1 branch args)))))) + (magit--merge-absorb-1 branch args))) + +(defun magit--merge-absorb-1 (branch args) + (if-let ((pr (magit-get "branch" branch "pullRequest"))) + (magit-run-git-async + "merge" args "-m" + (format "Merge branch '%s'%s [%s]" + branch + (let ((current (magit-get-current-branch))) + (if (equal current "master") "" (format " into %s" current))) + pr) + branch) + (magit-run-git-async "merge" args "--no-edit" branch)) + (set-process-sentinel + magit-this-process + (lambda (process event) + (when (memq (process-status process) '(exit signal)) + (if (> (process-exit-status process) 0) + (magit-process-sentinel process event) + (process-put process 'inhibit-refresh t) + (magit-process-sentinel process event) + (magit-branch-maybe-delete-pr-remote branch) + (magit-branch-unset-pushRemote branch) + (magit-run-git "branch" "-D" branch)))))) + +;;;###autoload +(defun magit-merge-squash (rev) + "Squash commit REV into the current branch; don't create a commit. +\n(git merge --squash REV)" + (interactive (list (magit-read-other-branch-or-commit "Squash"))) + (magit-merge-assert) + (magit-run-git-async "merge" "--squash" rev)) + +;;;###autoload +(defun magit-merge-preview (rev) + "Preview result of merging REV into the current branch." + (interactive (list (magit-read-other-branch-or-commit "Preview merge"))) + (magit-merge-preview-setup-buffer rev)) + +;;;###autoload +(defun magit-merge-abort () + "Abort the current merge operation. +\n(git merge --abort)" + (interactive) + (unless (file-exists-p (magit-git-dir "MERGE_HEAD")) + (user-error "No merge in progress")) + (magit-confirm 'abort-merge) + (magit-run-git-async "merge" "--abort")) + +(defun magit-checkout-stage (file arg) + "During a conflict checkout and stage side, or restore conflict." + (interactive + (let ((file (magit-completing-read "Checkout file" + (magit-tracked-files) nil nil nil + 'magit-read-file-hist + (magit-current-file)))) + (cond ((member file (magit-unmerged-files)) + (list file (magit-checkout-read-stage file))) + ((yes-or-no-p (format "Restore conflicts in %s? " file)) + (list file "--merge")) + (t + (user-error "Quit"))))) + (pcase (cons arg (cddr (car (magit-file-status file)))) + ((or `("--ours" ?D ,_) + `("--theirs" ,_ ?D)) + (magit-run-git "rm" "--" file)) + (_ (if (equal arg "--merge") + ;; This fails if the file was deleted on one + ;; side. And we cannot do anything about it. + (magit-run-git "checkout" "--merge" "--" file) + (magit-call-git "checkout" arg "--" file) + (magit-run-git "add" "-u" "--" file))))) + +;;; Utilities + +(defun magit-merge-in-progress-p () + (file-exists-p (magit-git-dir "MERGE_HEAD"))) + +(defun magit--merge-range (&optional head) + (unless head + (setq head (magit-get-shortname + (car (magit-file-lines (magit-git-dir "MERGE_HEAD")))))) + (and head + (concat (magit-git-string "merge-base" "--octopus" "HEAD" head) + ".." head))) + +(defun magit-merge-assert () + (or (not (magit-anything-modified-p t)) + (magit-confirm 'merge-dirty + "Merging with dirty worktree is risky. Continue"))) + +(defun magit-checkout-read-stage (file) + (magit-read-char-case (format "For %s checkout: " file) t + (?o "[o]ur stage" "--ours") + (?t "[t]heir stage" "--theirs") + (?c "[c]onflict" "--merge"))) + +;;; Sections + +(defvar magit-unmerged-section-map + (let ((map (make-sparse-keymap))) + (define-key map [remap magit-visit-thing] 'magit-diff-dwim) + map) + "Keymap for `unmerged' sections.") + +(defun magit-insert-merge-log () + "Insert section for the on-going merge. +Display the heads that are being merged. +If no merge is in progress, do nothing." + (when (magit-merge-in-progress-p) + (let* ((heads (mapcar #'magit-get-shortname + (magit-file-lines (magit-git-dir "MERGE_HEAD")))) + (range (magit--merge-range (car heads)))) + (magit-insert-section (unmerged range) + (magit-insert-heading + (format "Merging %s:" (mapconcat #'identity heads ", "))) + (magit-insert-log + range + (let ((args magit-buffer-log-args)) + (unless (member "--decorate=full" magit-buffer-log-args) + (push "--decorate=full" args)) + args)))))) + +;;; _ +(provide 'magit-merge) +;;; magit-merge.el ends here diff --git a/elpa/magit-20191122.2040/magit-merge.elc b/elpa/magit-20191122.2040/magit-merge.elc new file mode 100644 index 0000000000000000000000000000000000000000..b2dcb3d4acdd05a543855345b1d12aac87f1d160 GIT binary patch literal 13563 zcmeHO`*YjIcGknD9c6mkPH(5v$8A@TA5v>*hzCJgj(e@hO0L^D$+Z*T&X}4SB0&i? z2`~U@N1gV6@AsYE1p$gwoVrbasb(mFyNi9CJ?A^$IlFpv^40NQtgWqWJ$m#=9p~do zI!XreCC${yIPRC~T~d^3o+&@t52WUOI=xWwXr%JVG##h^9#2tS?r%xucNb}?hUi7j z%A{0-%PbzJeKpAY<+Mn%^YQ^|i*l;s!5|r^Y83C`zW?w_AA=lyWcgI}^K2TU@oYMD z4^Wc1M=y_`JyZRQxQP2xO!0vXA7=wq=BgiO>MT*CJZ=nPmQt!DE=FlmsObe7`hgx7 zBKW8uPT*sIwzjr*&n~Bl+s_Aya(Y3#jgPn8^F2QB!{a7^201G5;cy`)2aUL z4$|T9RQY>byMtsHkJ7kQ_odz)C&hW9c3!s|y-G*ZBF@S*$);|ZOlK3*mArtyRF;nT zIYp;Srp6iJ6YSKc=%FCQr?XfXp|INvWG!gq@q@R$0H5$)YoWQxwa*E+RLD3`xRW5P1|$Bjqlc>&-X zH-+^t&C18z@(<`5y`E3b-7-DT_V)Hp)e@B`ujquR_6KUjk`Bd=7gWWrTU2GdxKUy@ zD72PP6Q(;E0ghLSU;0ay_NQo5$$*Fj^@Ulj7=TU2<@xnPT+uCK=`gcFp53S47?0EG ziXpOGS6@Fyyts^`vobHvR`eN5<*H5n$vv1X4)$%4yi1e!5EkHj#h5@Ww!tzSXTcO3 z8%*74K*7r&W^s9OZQrFdxn4r)V!wJ90MPl08MBHqTCV!nX@1=~{R9p+)_z5~k3}<9 ztX=Dc+bg~TM#Hi$7dUM?>!l0;$YW7( z-mQXL_SW&s-`wswJwJ*z@Fh^j^H%upYM^xUvwuta(;9%L8DN*};Yt}KIH(o6_zyY56GthH+&im7RGD8nejxziyXJ^wQNgP<27w&EC zJPF$mm9|Z-;OfQ6D^T!h4kDZ=^i+T|Db14}fxv^WD{9efRG~Gf^7q*Y$jw(kK4W}9 z&WEG4KP^>Ws8|^SRV@Pn0b+rH($=KnEwK#)&1RHXohMmRAW|?hGtNQ01p^K;r%^JU zVoF<_EP5<3^>QMLhyut2)7)3;4-%eSnFVGwP2hU)vYEgzX0W5M`f~_SL?FGg`+PEi zjn1-k3SODl2huM?47_Sc`{3Qee~kXm#38R9$F7Gk@h{U5b;Q{R(<`= z@i)((Kl^U)?^f8WcC;|nZuC$ycUYz6&uxDLCK~+F8m$#i{;&8H-e|S%7}Kr0?6`!? zERif`nM*DgmzP;zIR>sYbJg>=JeKQnPSt_h-MORo6{*Vum*A zWC%9V%wQBD!Of{Yu2wZSFA(q0Q5&l6)X{8?gQqHh%YYtx4-bBZ9xoD({jG140t9$0 zTdtLnZJ;3&s&l-kgJ)XzDh=5Z`jSo;l|YIO_g5dV`>QvdJ%RjS+dE#cu zJ(zk;Ygpp&1)A6(fu$l`sv-oakJq;P)9tpe=#L3};Am*g`P>E@h^Q6M!S5Q=?1L_4dtp zL~FQI$&YC{MIJ55${AB?@P{#oSM$}$Y&1guKg<&3+IG_+CV#o7-b+w)4xUy{XZ^Pb z|B)>lCtEq97O`2I?8}EW)ugY-2*k#-gr*^CJbGK-9?Z%fY-!m%;FuXwi^$;BP4=-6adGA~(vk8c55|3?vx~80rz%Y!DM;_RuDs4$4 z(OCELU5(sf$Ffzk#VeTV|J&vNnqB?^_NeWm?v6G#7R+wJf;z^6I^BmWEQn0>8YabtT^yto`G;Sv2)sPC|||a@m2V} z#Nb_uLQFphVd-9b6Op;+9h*$K=ikOx$)4kH73j7;X?;TQ@Z0hm@aFq>MX3G(dhvtJ zMP!@e*oHY}#Fr&_9n!N&;i$``BsT{InJDLJu8_Y5Fca~C>xdMA=^`lgM!%s^1NJEF z-iY+K%8_WzO^Sk~@rcjRw^BcSfLZbKpbP%Hx$<44*uc%r7= zR>Kx5AEz9xq6mvgZeD0=Wd&=)qeX&?v}4n^8a=-c7kjrcBwlYNIbsbGb z?=rDdGb zH)h<7Wp%xW zZIiYDr!y&c6VhFqe={c-09*vqHYu?f9_svjGs(2fA!&zZTJOB}JKcq}0=7`R(Wcol zV+_U-eo*R2_YS#O4}H)MA1>#(+s9fl%qR?OR;Gls$k46v!BM0TkjtrvPWmZCE1V}o zlWQbu;sxg8R%hEx$2AEFx1OVe76|eLoPa(sch7LtkQ7KynJqsEx}A?-w_T)+IA1(ZDA(8Au(3cNtT)bHrtW?V$SnH zQf#oq>mT%Th*Ciu41&Uc4N|!O=O-_|Jo(q(og6)F(gK_c>qX#}2b`ZAZd+(%f;mOL zPUfk7Sko}CrZJ@{gjQ`y6d>)SuQBXAIY3|}v9s8f&R*j#i4NT)o`45OdZt8F{(xC+ zC>k96Jk@P<>5FGyoiLHROrdOdboFxcLNgMwIiTg{_LHNd&++7~9}<3hLFlioKM}G= zOEjJkRsPz>5sRhSdkOJuv*0mb9j&d;8^qE;zN0RDRQX44S?g08x8LinArVNwYDW3W zv?8+8+oEM}$n*}I(nI6Z2BoYjq#@XGHje2GSM?Ldm280l%T^!#qyNQRQ=`JFjgkd+u= z_))NS(=cW`UA!AzSpx-eWf`Or%U7~~^JZglp`P~*<{9cq1+f-G7@3zKZ8b__g&+xj zVO5wo_bAZGH#{+9z$t(!l6_%Au~1to8H^q8F?fT}kyQ2FrRI@Sy6ys%m_!J#14B`~vLelq+w}T;fOnsF)*$Ge_?ywEQPTUbg zca;-8c-RS-BP!RgxKa_C7M#wR+`DDu7%2!+Qs#dxdV<#7jcq2HebOMyXFMNK(Kbqh zzc7pZBGuiJF&X4+w1KByu8GcmKhvi@ zWGu^1kejFOE4&7UBy0NsHvo{9Qyo7rvGqKaM>nwyTTL8;3tfV&euqqqdk;gGGcX;c z5lEpK+uKjDae_qBqysfrI2^fghkCH_`^Nr~k>k9&nAUPvvZxUPPJ80cL$oW7ZSM1s z7b7jvMa13KLT7&;>TYv`UOPCDqplS@U{3NH4tx8zn0xdoS0;;=6*iFu zDPY7l(AIH|YfC9~a#F>T*2RiSa6vfulyo3x&)8e(viEuMmWRp;r@BR2zP&^i_!yTn z(`=St1$rlOW~H+vgob7Nw@iI&lnZkgv}2Y6`}eI~i@45?IK4mPLM6|+TiLW!NbHCR zuTDfS}Dz{*XrWIzOEi z$fm=^KTxlyr$nymYyZ@oj0=Z&ee9l}GH0Uc7O(0c_Vv6-Jp@bUGZjOQ?pZj;LDbi* zRS-m9ox**eIobBw2cZe!gFyXraygDCoVt2r5#&A+C;AfEzNUij;$jhGObeGUFC6l= z759ZnEKx8}35rZCN@F7OFC|V;%f!WH26lkE1F#f+<84)zXv27ymarPp#Zyxx_vi-i z(=iqVpqHa&&-4Axo*el4o_dDR49C}Ig0eE6B;dB^c}^u2&E4O6nj-BSckiO1e>^Vfg%m%kxz_AfAtkQ5rW9Ad5^5=>zi1T^SC zB=qU@@f~mTS5NTA$8XICKnlAgg&p6Xor^ki3S1`NL9dJ72bZhHf>Xa_ge*XxBM-VR$}4X7YB*W+-GXPn-fn}6Vo$Lz#=Bf5oYqg!Vk+SB#t zMd4>`6THFfy>6?QAr|nUJ9v3s5eW&^5P-9Z8-{dTMLjm4b>?{1+Bm9N{ zQH=lrMFGSsGVD?gL01;f*Pysnk#hryf-u~Xl-@rWC$7)8(9fKTArRL$zo(az1ebN^ zjLI0Rt;bDnx#XmQXt6RM4T`+FY;E63aSbTNVHsiTEXA4DWn%=sVaGRUw%D(|TBS$T zKDKd*8}Ci}6&imm@o3N^i~g!V0&l1Sa*Lyfl$a_|^@B1T@bmA#JXDCsky$S;1!&>* zgg4?A+Pio(OVlAe9>9144iO=hb z?hKS+gzIvBIdRZ(vGQgLt|n`~$(}4B7U}5iHsZD~q76ok#vGZm +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; This library implements the abstract major-mode `magit-mode' from +;; which almost all other Magit major-modes derive. The code in here +;; is mostly concerned with creating and refreshing Magit buffers. + +;;; Code: + +(require 'cl-lib) +(require 'dash) + +(eval-when-compile + (require 'subr-x)) + +(require 'transient) + +(require 'magit-section) +(require 'magit-git) + +;; For `magit-display-buffer-fullcolumn-most-v1' from `git-commit' +(defvar git-commit-mode) +;; For `magit-refresh' +(defvar magit-post-commit-hook-commands) +(defvar magit-post-stage-hook-commands) +(defvar magit-post-unstage-hook-commands) +;; For `magit-refresh' and `magit-refresh-all' +(declare-function magit-auto-revert-buffers "magit-autorevert" ()) +;; For `magit-refresh-buffer' +(declare-function magit-process-unset-mode-line-error-status "magit-process" ()) +;; For `magit-mode-setup-internal' +(declare-function magit-status-goto-initial-section "magit-status" ()) +;; For `magit-mode' from `bookmark' +(defvar bookmark-make-record-function) +;; For `magit-mode' from third-party `symbol-overlay' +(defvar symbol-overlay-inhibit-map) + +(require 'format-spec) +(require 'help-mode) + +;;; Options + +(defcustom magit-mode-hook + '(magit-load-config-extensions) + "Hook run when entering a mode derived from Magit mode." + :package-version '(magit . "2.91.0") + :group 'magit-modes + :type 'hook + :options '(magit-load-config-extensions + bug-reference-mode)) + +(defcustom magit-setup-buffer-hook + '(magit-maybe-save-repository-buffers + magit-set-buffer-margin) + "Hook run by `magit-setup-buffer'. + +This is run right after displaying the buffer and right before +generating or updating its content. `magit-mode-hook' and other, +more specific, `magit-mode-*-hook's on the other hand are run +right before displaying the buffer. Usually one of these hooks +should be used instead of this one." + :package-version '(magit . "2.3.0") + :group 'magit-modes + :type 'hook + :options '(magit-maybe-save-repository-buffers + magit-set-buffer-margin)) + +(defcustom magit-pre-refresh-hook '(magit-maybe-save-repository-buffers) + "Hook run before refreshing in `magit-refresh'. + +This hook, or `magit-post-refresh-hook', should be used +for functions that are not tied to a particular buffer. + +To run a function with a particular buffer current, use +`magit-refresh-buffer-hook' and use `derived-mode-p' +inside your function." + :package-version '(magit . "2.4.0") + :group 'magit-refresh + :type 'hook + :options '(magit-maybe-save-repository-buffers)) + +(defcustom magit-post-refresh-hook nil + "Hook run after refreshing in `magit-refresh'. + +This hook, or `magit-pre-refresh-hook', should be used +for functions that are not tied to a particular buffer. + +To run a function with a particular buffer current, use +`magit-refresh-buffer-hook' and use `derived-mode-p' +inside your function." + :package-version '(magit . "2.4.0") + :group 'magit-refresh + :type 'hook) + +(defcustom magit-display-buffer-function 'magit-display-buffer-traditional + "The function used display a Magit buffer. + +All Magit buffers (buffers whose major-modes derive from +`magit-mode') are displayed using `magit-display-buffer', +which in turn uses the function specified here." + :package-version '(magit . "2.3.0") + :group 'magit-buffers + :type '(radio (function-item magit-display-buffer-traditional) + (function-item magit-display-buffer-same-window-except-diff-v1) + (function-item magit-display-buffer-fullframe-status-v1) + (function-item magit-display-buffer-fullframe-status-topleft-v1) + (function-item magit-display-buffer-fullcolumn-most-v1) + (function-item display-buffer) + (function :tag "Function"))) + +(defcustom magit-pre-display-buffer-hook '(magit-save-window-configuration) + "Hook run by `magit-display-buffer' before displaying the buffer." + :package-version '(magit . "2.3.0") + :group 'magit-buffers + :type 'hook + :get 'magit-hook-custom-get + :options '(magit-save-window-configuration)) + +(defcustom magit-post-display-buffer-hook '(magit-maybe-set-dedicated) + "Hook run by `magit-display-buffer' after displaying the buffer." + :package-version '(magit . "2.3.0") + :group 'magit-buffers + :type 'hook + :get 'magit-hook-custom-get + :options '(magit-maybe-set-dedicated)) + +(defcustom magit-generate-buffer-name-function + 'magit-generate-buffer-name-default-function + "The function used to generate the name for a Magit buffer." + :package-version '(magit . "2.3.0") + :group 'magit-buffers + :type '(radio (function-item magit-generate-buffer-name-default-function) + (function :tag "Function"))) + +(defcustom magit-buffer-name-format "%x%M%v: %t%x" + "The format string used to name Magit buffers. + +The following %-sequences are supported: + +`%m' The name of the major-mode, but with the `-mode' suffix + removed. + +`%M' Like \"%m\" but abbreviate `magit-status-mode' as `magit'. + +`%v' The value the buffer is locked to, in parentheses, or an + empty string if the buffer is not locked to a value. + +`%V' Like \"%v\", but the string is prefixed with a space, unless + it is an empty string. + +`%t' The top-level directory of the working tree of the + repository, or if `magit-uniquify-buffer-names' is non-nil + an abbreviation of that. + +`%x' If `magit-uniquify-buffer-names' is nil \"*\", otherwise the + empty string. Due to limitations of the `uniquify' package, + buffer names must end with the path. + +`%T' Obsolete, use \"%t%x\" instead. Like \"%t\", but append an + asterisk if and only if `magit-uniquify-buffer-names' is nil. + +The value should always contain \"%m\" or \"%M\", \"%v\" or +\"%V\", and \"%t\" (or the obsolete \"%T\"). + +If `magit-uniquify-buffer-names' is non-nil, then the value must +end with \"%t\" or \"%t%x\" (or the obsolete \"%T\"). See issue +#2841. + +This is used by `magit-generate-buffer-name-default-function'. +If another `magit-generate-buffer-name-function' is used, then +it may not respect this option, or on the contrary it may +support additional %-sequences." + :package-version '(magit . "2.12.0") + :group 'magit-buffers + :type 'string) + +(defcustom magit-uniquify-buffer-names t + "Whether to uniquify the names of Magit buffers." + :package-version '(magit . "2.3.0") + :group 'magit-buffers + :type 'boolean) + +(defcustom magit-bury-buffer-function 'magit-restore-window-configuration + "The function used to bury or kill the current Magit buffer." + :package-version '(magit . "2.3.0") + :group 'magit-buffers + :type '(radio (function-item quit-window) + (function-item magit-mode-quit-window) + (function-item magit-restore-window-configuration) + (function :tag "Function"))) + +(defcustom magit-prefix-use-buffer-arguments 'selected + "Whether certain prefix commands reuse arguments active in relevant buffer. + +This affects the transient prefix commands `magit-diff', +`magit-log' and `magit-show-refs'. + +Valid values are: + +`always': Always use the set of arguments that is currently + active in the respective buffer, provided that buffer exists + of course. +`selected' or t: Use the set of arguments from the respective + buffer, but only if it is displayed in a window of the current + frame. This is the default. +`current': Use the set of arguments from the respective buffer, + but only if it is the current buffer. +`never': Never use the set of arguments from the respective + buffer. + +For more information see info node `(magit)Transient Arguments +and Buffer Arguments'." + :package-version '(magit . "2.91.0") + :group 'magit-buffers + :group 'magit-commands + :type '(choice (const :tag "always use args from buffer" always) + (const :tag "use args from buffer if it is current" current) + (const :tag "never use args from buffer" never))) + +(defcustom magit-direct-use-buffer-arguments 'selected + "Whether certain commands reuse arguments active in relevant buffer. + +This affects certain commands such as `magit-show-commit' that +are suffixes of the diff or log transient prefix commands, but +only if they are invoked directly, i.e. *not* as a suffix. + +Valid values are: + +`always': Always use the set of arguments that is currently + active in the respective buffer, provided that buffer exists + of course. +`selected' or t: Use the set of arguments from the respective + buffer, but only if it is displayed in a window of the current + frame. This is the default. +`current': Use the set of arguments from the respective buffer, + but only if it is the current buffer. +`never': Never use the set of arguments from the respective + buffer. + +For more information see info node `(magit)Transient Arguments +and Buffer Arguments'." + :package-version '(magit . "2.91.0") + :group 'magit-buffers + :group 'magit-commands + :type '(choice (const :tag "always use args from buffer" always) + (const :tag "use args from buffer if it is current" current) + (const :tag "never use args from buffer" never))) + +(defcustom magit-region-highlight-hook + '(magit-section-update-region magit-diff-update-hunk-region) + "Functions used to highlight the region. + +Each function is run with the current section as only argument +until one of them returns non-nil. If all functions return nil, +then fall back to regular region highlighting." + :package-version '(magit . "2.1.0") + :group 'magit-refresh + :type 'hook + :options '(magit-section-update-region magit-diff-update-hunk-region)) + +(defcustom magit-create-buffer-hook nil + "Normal hook run after creating a new `magit-mode' buffer." + :package-version '(magit . "2.90.0") + :group 'magit-refresh + :type 'hook) + +(defcustom magit-refresh-buffer-hook nil + "Normal hook for `magit-refresh-buffer' to run after refreshing." + :package-version '(magit . "2.1.0") + :group 'magit-refresh + :type 'hook) + +(defcustom magit-refresh-status-buffer t + "Whether the status buffer is refreshed after running git. + +When this is non-nil, then the status buffer is automatically +refreshed after running git for side-effects, in addition to the +current Magit buffer, which is always refreshed automatically. + +Only set this to nil after exhausting all other options to +improve performance." + :package-version '(magit . "2.4.0") + :group 'magit-refresh + :group 'magit-status + :type 'boolean) + +(defcustom magit-refresh-verbose nil + "Whether to revert Magit buffers verbosely." + :package-version '(magit . "2.1.0") + :group 'magit-refresh + :type 'boolean) + +(defcustom magit-save-repository-buffers t + "Whether to save file-visiting buffers when appropriate. + +If non-nil, then all modified file-visiting buffers belonging +to the current repository may be saved before running Magit +commands and before creating or refreshing Magit buffers. +If `dontask', then this is done without user intervention, for +any other non-nil value the user has to confirm each save. + +The default is t to avoid surprises, but `dontask' is the +recommended value." + :group 'magit-essentials + :group 'magit-buffers + :type '(choice (const :tag "Never" nil) + (const :tag "Ask" t) + (const :tag "Save without asking" dontask))) + +(defcustom magit-keep-region-overlay nil + "Whether to keep the region overlay when there is a valid selection. + +By default Magit removes the regular region overlay if, and only +if, that region constitutes a valid selection as understood by +Magit commands. Otherwise it does not remove that overlay, and +the region looks like it would in other buffers. + +There are two types of such valid selections: hunk-internal +regions and regions that select two or more sibling sections. +In such cases Magit removes the region overlay and instead +highlights a slightly larger range. All text (for hunk-internal +regions) or the headings of all sections (for sibling selections) +that are inside that range (not just inside the region) are acted +on by commands such as the staging command. This buffer range +begins at the beginning of the line on which the region begins +and ends at the end of the line on which the region ends. + +Because Magit acts on this larger range and not the region, it is +actually quite important to visualize that larger range. If we +don't do that, then one might think that these commands act on +the region instead. If you want to *also* visualize the region, +then set this option to t. But please note that when the region +does *not* constitute a valid selection, then the region is +*always* visualized as usual, and that it is usually under such +circumstances that you want to use a non-magit command to act on +the region. + +Besides keeping the region overlay, setting this option to t also +causes all face properties, except for `:foreground', to be +ignored for the faces used to highlight headings of selected +sections. This avoids the worst conflicts that result from +displaying the region and the selection overlays at the same +time. We are not interested in dealing with other conflicts. +In fact we *already* provide a way to avoid all of these +conflicts: *not* changing the value of this option. + +It should be clear by now that we consider it a mistake to set +this to display the region when the Magit selection is also +visualized, but since it has been requested a few times and +because it doesn't cost much to offer this option we do so. +However that might change. If the existence of this option +starts complicating other things, then it will be removed." + :package-version '(magit . "2.3.0") + :group 'magit-miscellaneous + :type 'boolean) + +(defcustom magit-disable-line-numbers t + "In Magit buffers, whether to disable modes that display line numbers. + +Some users who turn on `global-disable-line-numbers-mode' (or +`global-nlinum-mode' or `global-linum-mode') expect line numbers +to be displayed everywhere except in Magit buffers. Other users do +not expect Magit buffers to be treated differently. At least in +theory users in the first group should not use the global mode, +but that ship has sailed, thus this option." + :package-version '(magit . "2.91.0") + :group 'magit-miscellaneous + :type 'boolean) + +;;; Key Bindings + +(defvar magit-mode-map + (let ((map (make-keymap))) + (suppress-keymap map t) + (cond ((featurep 'jkl) + (define-key map [return] 'magit-visit-thing) + (define-key map [C-return] 'magit-dired-jump) + (define-key map [tab] 'magit-section-toggle) + (define-key map [C-tab] 'magit-section-cycle) + (define-key map [M-tab] 'magit-section-cycle-diffs) + (define-key map [S-tab] 'magit-section-cycle-global) + (define-key map (kbd "M-o") 'magit-section-up) + (define-key map (kbd "i") 'magit-section-backward) + (define-key map (kbd "k") 'magit-section-forward) + (define-key map (kbd "M-i") 'magit-section-backward-sibling) + (define-key map (kbd "M-k") 'magit-section-forward-sibling) + (define-key map (kbd "p") 'magit-push) + (define-key map (kbd ",") 'magit-delete-thing) + (define-key map (kbd ";") 'magit-file-untrack) + (define-key map (kbd "C-c C-i") 'magit-gitignore)) + (t + (define-key map [C-return] 'magit-visit-thing) + (define-key map (kbd "C-m") 'magit-visit-thing) + (define-key map (kbd "C-M-i") 'magit-dired-jump) + (define-key map (kbd "C-i") 'magit-section-toggle) + (define-key map [C-tab] 'magit-section-cycle) + (define-key map [M-tab] 'magit-section-cycle-diffs) + ;; [backtab] is the most portable binding for Shift+Tab. + (define-key map [backtab] 'magit-section-cycle-global) + (define-key map (kbd "^") 'magit-section-up) + (define-key map (kbd "p") 'magit-section-backward) + (define-key map (kbd "n") 'magit-section-forward) + (define-key map (kbd "M-p") 'magit-section-backward-sibling) + (define-key map (kbd "M-n") 'magit-section-forward-sibling) + (define-key map (kbd "P") 'magit-push) + (define-key map (kbd "k") 'magit-delete-thing) + (define-key map (kbd "K") 'magit-file-untrack) + (define-key map (kbd "i") 'magit-gitignore) + (define-key map (kbd "I") 'magit-gitignore))) + (define-key map (kbd "SPC") 'magit-diff-show-or-scroll-up) + (define-key map (kbd "DEL") 'magit-diff-show-or-scroll-down) + (define-key map "+" 'magit-diff-more-context) + (define-key map "-" 'magit-diff-less-context) + (define-key map "0" 'magit-diff-default-context) + (define-key map "1" 'magit-section-show-level-1) + (define-key map "2" 'magit-section-show-level-2) + (define-key map "3" 'magit-section-show-level-3) + (define-key map "4" 'magit-section-show-level-4) + (define-key map (kbd "M-1") 'magit-section-show-level-1-all) + (define-key map (kbd "M-2") 'magit-section-show-level-2-all) + (define-key map (kbd "M-3") 'magit-section-show-level-3-all) + (define-key map (kbd "M-4") 'magit-section-show-level-4-all) + (define-key map "$" 'magit-process-buffer) + (define-key map "%" 'magit-worktree) + (define-key map "a" 'magit-cherry-apply) + (define-key map "A" 'magit-cherry-pick) + (define-key map "b" 'magit-branch) + (define-key map "B" 'magit-bisect) + (define-key map "c" 'magit-commit) + (define-key map "C" 'magit-clone) + (define-key map "d" 'magit-diff) + (define-key map "D" 'magit-diff-refresh) + (define-key map "e" 'magit-ediff-dwim) + (define-key map "E" 'magit-ediff) + (define-key map "f" 'magit-fetch) + (define-key map "F" 'magit-pull) + (define-key map "g" 'magit-refresh) + (define-key map "G" 'magit-refresh-all) + (define-key map "h" 'magit-dispatch) + (define-key map "?" 'magit-dispatch) + (define-key map "l" 'magit-log) + (define-key map "L" 'magit-log-refresh) + (define-key map "m" 'magit-merge) + (define-key map "M" 'magit-remote) + (define-key map "o" 'magit-submodule) + (define-key map "O" 'magit-subtree) + (define-key map "q" 'magit-mode-bury-buffer) + (define-key map "r" 'magit-rebase) + (define-key map "R" 'magit-file-rename) + (define-key map "t" 'magit-tag) + (define-key map "T" 'magit-notes) + (define-key map "s" 'magit-stage-file) + (define-key map "S" 'magit-stage-modified) + (define-key map "u" 'magit-unstage-file) + (define-key map "U" 'magit-unstage-all) + (define-key map "v" 'magit-revert-no-commit) + (define-key map "V" 'magit-revert) + (define-key map "w" 'magit-am) + (define-key map "W" 'magit-patch) + (define-key map "x" 'magit-reset-quickly) + (define-key map "X" 'magit-reset) + (define-key map "y" 'magit-show-refs) + (define-key map "Y" 'magit-cherry) + (define-key map "z" 'magit-stash) + (define-key map "Z" 'magit-stash) + (define-key map ":" 'magit-git-command) + (define-key map "!" 'magit-run) + (define-key map (kbd "C-c C-c") 'magit-dispatch) + (define-key map (kbd "C-c C-e") 'magit-edit-thing) + (define-key map (kbd "C-c C-o") 'magit-browse-thing) + (define-key map (kbd "C-c C-w") 'magit-browse-thing) + (define-key map (kbd "C-x a") 'magit-add-change-log-entry) + (define-key map (kbd "C-x 4 a") 'magit-add-change-log-entry-other-window) + (define-key map (kbd "C-w") 'magit-copy-section-value) + (define-key map (kbd "M-w") 'magit-copy-buffer-revision) + (define-key map [remap previous-line] 'magit-previous-line) + (define-key map [remap next-line] 'magit-next-line) + (define-key map [remap evil-previous-line] 'evil-previous-visual-line) + (define-key map [remap evil-next-line] 'evil-next-visual-line) + map) + "Parent keymap for all keymaps of modes derived from `magit-mode'.") + +(defun magit-delete-thing () + "This is a placeholder command. +Where applicable, section-specific keymaps bind another command +which deletes the thing at point." + (interactive) + (user-error "There is no thing at point that could be deleted")) + +(defun magit-visit-thing () + "This is a placeholder command. +Where applicable, section-specific keymaps bind another command +which visits the thing at point." + (interactive) + (if (eq current-transient-command 'magit-dispatch) + (call-interactively (key-binding (this-command-keys))) + (user-error "There is no thing at point that could be visited"))) + +(defun magit-edit-thing () + "This is a placeholder command. +Where applicable, section-specific keymaps bind another command +which lets you edit the thing at point, likely in another buffer." + (interactive) + (if (eq current-transient-command 'magit-dispatch) + (call-interactively (key-binding (this-command-keys))) + (user-error "There is no thing at point that could be edited"))) + +(defun magit-browse-thing () + "This is a placeholder command. +Where applicable, section-specific keymaps bind another command +which visits the thing at point using `browse-url'." + (interactive) + (user-error "There is no thing at point that could be browsed")) + +(defvar bug-reference-map) +(with-eval-after-load 'bug-reference + (define-key bug-reference-map [remap magit-visit-thing] + 'bug-reference-push-button)) + +(easy-menu-define magit-mode-menu magit-mode-map + "Magit menu" + '("Magit" + ["Refresh" magit-refresh t] + ["Refresh all" magit-refresh-all t] + "---" + ["Stage" magit-stage t] + ["Stage modified" magit-stage-modified t] + ["Unstage" magit-unstage t] + ["Reset index" magit-reset-index t] + ["Commit" magit-commit t] + ["Add log entry" magit-commit-add-log t] + ["Tag" magit-tag-create t] + "---" + ["Diff working tree" magit-diff-working-tree t] + ["Diff" magit-diff t] + ("Log" + ["Log" magit-log-other t] + ["Reflog" magit-reflog-other t] + ["Extended..." magit-log t]) + "---" + ["Cherry pick" magit-cherry-pick t] + ["Revert commit" magit-revert t] + "---" + ["Ignore globally" magit-gitignore-globally t] + ["Ignore locally" magit-gitignore-locally t] + ["Discard" magit-discard t] + ["Reset head and index" magit-reset-mixed t] + ["Stash" magit-stash-both t] + ["Snapshot" magit-snapshot-both t] + "---" + ["Branch..." magit-checkout t] + ["Merge" magit-merge t] + ["Ediff resolve" magit-ediff-resolve t] + ["Rebase..." magit-rebase t] + "---" + ["Push" magit-push t] + ["Pull" magit-pull-branch t] + ["Remote update" magit-fetch-all t] + ("Submodule" + ["Submodule update" magit-submodule-update t] + ["Submodule update and init" magit-submodule-setup t] + ["Submodule init" magit-submodule-init t] + ["Submodule sync" magit-submodule-sync t]) + "---" + ("Extensions") + "---" + ["Display Git output" magit-process-buffer t] + ["Quit Magit" magit-mode-bury-buffer t])) + +;;; Mode + +(defun magit-load-config-extensions () + "Load Magit extensions that are defined at the Git config layer." + (dolist (ext (magit-get-all "magit.extension")) + (let ((sym (intern (format "magit-%s-mode" ext)))) + (when (fboundp sym) + (funcall sym 1))))) + +(define-derived-mode magit-mode special-mode "Magit" + "Parent major mode from which Magit major modes inherit. + +Magit is documented in info node `(magit)'." + :group 'magit-modes + (buffer-disable-undo) + (setq truncate-lines t) + (setq buffer-read-only t) + (setq-local line-move-visual t) ; see #1771 + ;; Turn off syntactic font locking, but not by setting + ;; `font-lock-defaults' because that would enable font locking, and + ;; not all magit plugins may be ready for that (see #3950). + (setq-local font-lock-syntactic-face-function #'ignore) + (setq show-trailing-whitespace nil) + (setq-local symbol-overlay-inhibit-map t) + (setq list-buffers-directory (abbreviate-file-name default-directory)) + (hack-dir-local-variables-non-file-buffer) + (make-local-variable 'text-property-default-nonsticky) + (push (cons 'keymap t) text-property-default-nonsticky) + (add-hook 'post-command-hook #'magit-section-update-highlight t t) + (add-hook 'deactivate-mark-hook #'magit-section-update-highlight t t) + (setq-local redisplay-highlight-region-function 'magit-highlight-region) + (setq-local redisplay-unhighlight-region-function 'magit-unhighlight-region) + (setq mode-line-process (magit-repository-local-get 'mode-line-process)) + (when magit-disable-line-numbers + (when (bound-and-true-p global-linum-mode) + (linum-mode -1)) + (when (and (fboundp 'nlinum-mode) + (bound-and-true-p global-nlinum-mode)) + (nlinum-mode -1)) + (when (and (fboundp 'display-line-numbers-mode) + (bound-and-true-p global-display-line-numbers-mode)) + (display-line-numbers-mode -1))) + (add-hook 'kill-buffer-hook 'magit-preserve-section-visibility-cache) + (setq-local bookmark-make-record-function 'magit--make-bookmark)) + +;;; Highlighting + +(defvar-local magit-region-overlays nil) + +(defun magit-delete-region-overlays () + (mapc #'delete-overlay magit-region-overlays) + (setq magit-region-overlays nil)) + +(defun magit-highlight-region (start end window rol) + (magit-delete-region-overlays) + (if (and (run-hook-with-args-until-success 'magit-region-highlight-hook + (magit-current-section)) + (not magit-keep-region-overlay) + (not (= (line-number-at-pos start) + (line-number-at-pos end))) + ;; (not (eq (car-safe last-command-event) 'mouse-movement)) + ) + (funcall (default-value 'redisplay-unhighlight-region-function) rol) + (funcall (default-value 'redisplay-highlight-region-function) + start end window rol))) + +(defun magit-unhighlight-region (rol) + (setq magit-section-highlighted-section nil) + (magit-delete-region-overlays) + (funcall (default-value 'redisplay-unhighlight-region-function) rol)) + +;;; Local Variables + +(defvar-local magit-buffer-arguments nil) +(defvar-local magit-buffer-diff-args nil) +(defvar-local magit-buffer-diff-files nil) +(defvar-local magit-buffer-diff-files-suspended nil) +(defvar-local magit-buffer-file-name nil) +(defvar-local magit-buffer-files nil) +(defvar-local magit-buffer-log-args nil) +(defvar-local magit-buffer-log-files nil) +(defvar-local magit-buffer-range nil) +(defvar-local magit-buffer-range-hashed nil) +(defvar-local magit-buffer-refname nil) +(defvar-local magit-buffer-revision nil) +(defvar-local magit-buffer-revision-hash nil) +(defvar-local magit-buffer-revisions nil) +(defvar-local magit-buffer-typearg nil) +(defvar-local magit-buffer-upstream nil) + +;; These variables are also used in file-visiting buffers. +;; Because the user may change the major-mode, they have +;; to be permanent buffer-local. +(put 'magit-buffer-file-name 'permanent-local t) +(put 'magit-buffer-refname 'permanent-local t) +(put 'magit-buffer-revision 'permanent-local t) +(put 'magit-buffer-revision-hash 'permanent-local t) + +(defvar-local magit-refresh-args nil + "Obsolete. Possibly the arguments used to refresh the current buffer. +Some third-party packages might still use this, but Magit does not.") +(put 'magit-refresh-args 'permanent-local t) +(make-obsolete-variable 'magit-refresh-args nil "Magit 2.91.0") + +(defvar magit-buffer-lock-functions nil + "Obsolete buffer-locking support for third-party modes. +Implement the generic function `magit-buffer-value' for +your mode instead of adding an entry to this variable.") +(make-obsolete-variable 'magit-buffer-lock-functions nil "Magit 2.91.0") + +(cl-defgeneric magit-buffer-value () + (when-let ((fn (cdr (assq major-mode magit-buffer-lock-functions)))) + (funcall fn (with-no-warnings magit-refresh-args)))) + +(defvar-local magit-previous-section nil) +(put 'magit-previous-section 'permanent-local t) + +;;; Setup Buffer + +(defmacro magit-setup-buffer (mode &optional locked &rest bindings) + (declare (indent 2)) + `(magit-setup-buffer-internal + ,mode ,locked + ,(cons 'list (mapcar (pcase-lambda (`(,var ,form)) + `(list ',var ,form)) + bindings)))) + +(defun magit-setup-buffer-internal (mode locked bindings) + (let* ((value (and locked + (with-temp-buffer + (pcase-dolist (`(,var ,val) bindings) + (set (make-local-variable var) val)) + (let ((major-mode mode)) + (magit-buffer-value))))) + (buffer (magit-get-mode-buffer mode value)) + (section (and buffer (magit-current-section))) + (created (not buffer))) + (unless buffer + (setq buffer (magit-with-toplevel + (magit-generate-new-buffer mode value)))) + (with-current-buffer buffer + (setq magit-previous-section section) + (funcall mode) + (magit-xref-setup 'magit-setup-buffer-internal bindings) + (pcase-dolist (`(,var ,val) bindings) + (set (make-local-variable var) val)) + (when created + (magit-status-goto-initial-section) + (run-hooks 'magit-create-buffer-hook))) + (magit-display-buffer buffer) + (with-current-buffer buffer + (run-hooks 'magit-setup-buffer-hook) + (magit-refresh-buffer)) + buffer)) + +(defun magit-mode-setup (mode &rest args) + "Setup up a MODE buffer using ARGS to generate its content." + (declare (obsolete magit-setup-buffer "Magit 2.91.0")) + (with-no-warnings + (magit-mode-setup-internal mode args))) + +(defun magit-mode-setup-internal (mode args &optional locked) + "Setup up a MODE buffer using ARGS to generate its content. +When optional LOCKED is non-nil, then create a buffer that is +locked to its value, which is derived from MODE and ARGS." + (declare (obsolete magit-setup-buffer "Magit 2.91.0")) + (let* ((value (and locked + (with-temp-buffer + (with-no-warnings + (setq magit-refresh-args args)) + (let ((major-mode mode)) + (magit-buffer-value))))) + (buffer (magit-get-mode-buffer mode value)) + (section (and buffer (magit-current-section))) + (created (not buffer))) + (unless buffer + (setq buffer (magit-with-toplevel + (magit-generate-new-buffer mode value)))) + (with-current-buffer buffer + (setq magit-previous-section section) + (with-no-warnings + (setq magit-refresh-args args)) + (funcall mode) + (magit-xref-setup 'magit-mode-setup-internal args) + (when created + (magit-status-goto-initial-section) + (run-hooks 'magit-create-buffer-hook))) + (magit-display-buffer buffer) + (with-current-buffer buffer + (run-hooks 'magit-mode-setup-hook) + (magit-refresh-buffer)))) + +;;; Display Buffer + +(defvar magit-display-buffer-noselect nil + "If non-nil, then `magit-display-buffer' doesn't call `select-window'.") + +(defun magit-display-buffer (buffer &optional display-function) + "Display BUFFER in some window and maybe select it. + +If optional DISPLAY-FUNCTION is non-nil, then use that to display +the buffer. Otherwise use `magit-display-buffer-function', which +is the normal case. + +Then, unless `magit-display-buffer-noselect' is non-nil, select +the window which was used to display the buffer. + +Also run the hooks `magit-pre-display-buffer-hook' +and `magit-post-display-buffer-hook'." + (with-current-buffer buffer + (run-hooks 'magit-pre-display-buffer-hook)) + (let ((window (funcall (or display-function magit-display-buffer-function) + buffer))) + (unless magit-display-buffer-noselect + (let* ((old-frame (selected-frame)) + (new-frame (window-frame window))) + (select-window window) + (unless (eq old-frame new-frame) + (select-frame-set-input-focus new-frame))))) + (with-current-buffer buffer + (run-hooks 'magit-post-display-buffer-hook))) + +(defun magit-display-buffer-traditional (buffer) + "Display BUFFER the way this has traditionally been done." + (display-buffer + buffer (if (and (derived-mode-p 'magit-mode) + (not (memq (with-current-buffer buffer major-mode) + '(magit-process-mode + magit-revision-mode + magit-diff-mode + magit-stash-mode + magit-status-mode)))) + '(display-buffer-same-window) + nil))) ; display in another window + +(defun magit-display-buffer-same-window-except-diff-v1 (buffer) + "Display BUFFER in the selected window except for some modes. +If a buffer's `major-mode' derives from `magit-diff-mode' or +`magit-process-mode', display it in another window. Display all +other buffers in the selected window." + (display-buffer + buffer (if (with-current-buffer buffer + (derived-mode-p 'magit-diff-mode 'magit-process-mode)) + nil ; display in another window + '(display-buffer-same-window)))) + +(defun magit--display-buffer-fullframe (buffer alist) + (when-let ((window (or (display-buffer-reuse-window buffer alist) + (display-buffer-same-window buffer alist) + (display-buffer-pop-up-window buffer alist) + (display-buffer-use-some-window buffer alist)))) + (delete-other-windows window) + window)) + +(defun magit-display-buffer-fullframe-status-v1 (buffer) + "Display BUFFER, filling entire frame if BUFFER is a status buffer. +Otherwise, behave like `magit-display-buffer-traditional'." + (if (eq (with-current-buffer buffer major-mode) + 'magit-status-mode) + (display-buffer buffer '(magit--display-buffer-fullframe)) + (magit-display-buffer-traditional buffer))) + +(defun magit--display-buffer-topleft (buffer alist) + (or (display-buffer-reuse-window buffer alist) + (when-let ((window2 (display-buffer-pop-up-window buffer alist))) + (let ((window1 (get-buffer-window)) + (buffer1 (current-buffer)) + (buffer2 (window-buffer window2)) + (w2-quit-restore (window-parameter window2 'quit-restore))) + (set-window-buffer window1 buffer2) + (set-window-buffer window2 buffer1) + (select-window window2) + ;; Swap some window state that `magit-mode-quit-window' and + ;; `quit-restore-window' inspect. + (set-window-prev-buffers window2 (cdr (window-prev-buffers window1))) + (set-window-prev-buffers window1 nil) + (set-window-parameter window2 'magit-dedicated + (window-parameter window1 'magit-dedicated)) + (set-window-parameter window1 'magit-dedicated t) + (set-window-parameter window1 'quit-restore + (list 'window 'window + (nth 2 w2-quit-restore) + (nth 3 w2-quit-restore))) + (set-window-parameter window2 'quit-restore nil) + window1)))) + +(defun magit-display-buffer-fullframe-status-topleft-v1 (buffer) + "Display BUFFER, filling entire frame if BUFFER is a status buffer. +When BUFFER derives from `magit-diff-mode' or +`magit-process-mode', try to display BUFFER to the top or left of +the current buffer rather than to the bottom or right, as +`magit-display-buffer-fullframe-status-v1' would. Whether the +split is made vertically or horizontally is determined by +`split-window-preferred-function'." + (display-buffer + buffer + (cond ((eq (with-current-buffer buffer major-mode) + 'magit-status-mode) + '(magit--display-buffer-fullframe)) + ((with-current-buffer buffer + (derived-mode-p 'magit-diff-mode 'magit-process-mode)) + '(magit--display-buffer-topleft)) + (t + '(display-buffer-same-window))))) + +(defun magit--display-buffer-fullcolumn (buffer alist) + (when-let ((window (or (display-buffer-reuse-window buffer alist) + (display-buffer-same-window buffer alist) + (display-buffer-below-selected buffer alist)))) + (delete-other-windows-vertically window) + window)) + +(defun magit-display-buffer-fullcolumn-most-v1 (buffer) + "Display BUFFER using the full column except in some cases. +For most cases where BUFFER's `major-mode' derives from +`magit-mode', display it in the selected window and grow that +window to the full height of the frame, deleting other windows in +that column as necessary. However, display BUFFER in another +window if 1) BUFFER's mode derives from `magit-process-mode', or +2) BUFFER's mode derives from `magit-diff-mode', provided that +the mode of the current buffer derives from `magit-log-mode' or +`magit-cherry-mode'." + (display-buffer + buffer + (cond ((and (or git-commit-mode + (derived-mode-p 'magit-log-mode + 'magit-cherry-mode + 'magit-reflog-mode)) + (with-current-buffer buffer + (derived-mode-p 'magit-diff-mode))) + nil) + ((with-current-buffer buffer + (derived-mode-p 'magit-process-mode)) + nil) + (t + '(magit--display-buffer-fullcolumn))))) + +(defun magit-maybe-set-dedicated () + "Mark the selected window as dedicated if appropriate. + +If a new window was created to display the buffer, then remember +that fact. That information is used by `magit-mode-quit-window', +to determine whether the window should be deleted when its last +Magit buffer is buried." + (let ((window (get-buffer-window (current-buffer)))) + (when (and (window-live-p window) + (not (window-prev-buffers window))) + (set-window-parameter window 'magit-dedicated t)))) + +;;; Get Buffer + +(defvar-local magit--default-directory nil + "Value of `default-directory' when buffer is generated. +This exists to prevent a let-bound `default-directory' from +tricking `magit-get-mode-buffer' or `magit-mode-get-buffers' +into thinking a buffer belongs to a repo that it doesn't.") +(put 'magit--default-directory 'permanent-local t) + +(defun magit-mode-get-buffers () + (let ((topdir (magit-toplevel))) + (--filter (with-current-buffer it + (and (derived-mode-p 'magit-mode) + (equal magit--default-directory topdir))) + (buffer-list)))) + +(defvar-local magit-buffer-locked-p nil) +(put 'magit-buffer-locked-p 'permanent-local t) + +(defun magit-get-mode-buffer (mode &optional value frame) + "Return buffer belonging to the current repository whose major-mode is MODE. + +If no such buffer exists then return nil. Multiple buffers with +the same major-mode may exist for a repository but only one can +exist that hasn't been looked to its value. Return that buffer +\(or nil if there is no such buffer) unless VALUE is non-nil, in +which case return the buffer that has been looked to that value. + +If FRAME nil or omitted, then consider all buffers. Otherwise + only consider buffers that are displayed in some live window + on some frame. +If `all', then consider all buffers on all frames. +If `visible', then only consider buffers on all visible frames. +If `selected' or t, then only consider buffers on the selected + frame. +If a frame, then only consider buffers on that frame." + (if-let ((topdir (magit-toplevel))) + (cl-flet* ((b (buffer) + (with-current-buffer buffer + (and (eq major-mode mode) + (equal magit--default-directory topdir) + (if value + (and magit-buffer-locked-p + (equal (magit-buffer-value) value)) + (not magit-buffer-locked-p)) + buffer))) + (w (window) + (b (window-buffer window))) + (f (frame) + (-some #'w (window-list frame 'no-minibuf)))) + (pcase-exhaustive frame + (`nil (-some #'b (buffer-list))) + (`all (-some #'f (frame-list))) + (`visible (-some #'f (visible-frame-list))) + ((or `selected `t) (-some #'w (window-list (selected-frame)))) + ((guard (framep frame)) (-some #'w (window-list frame))))) + (magit--not-inside-repository-error))) + +(defun magit-mode-get-buffer (mode &optional create frame value) + (declare (obsolete magit-get-mode-buffer "Magit 2.91.0")) + (when create + (error "`magit-mode-get-buffer's CREATE argument is obsolete")) + (if-let ((topdir (magit-toplevel))) + (--first (with-current-buffer it + (and (eq major-mode mode) + (equal magit--default-directory topdir) + (if value + (and magit-buffer-locked-p + (equal (magit-buffer-value) value)) + (not magit-buffer-locked-p)))) + (if frame + (mapcar #'window-buffer + (window-list (unless (eq frame t) frame))) + (buffer-list))) + (magit--not-inside-repository-error))) + +(defun magit-generate-new-buffer (mode &optional value) + (let* ((name (funcall magit-generate-buffer-name-function mode value)) + (buffer (generate-new-buffer name))) + (with-current-buffer buffer + (setq magit--default-directory default-directory) + (setq magit-buffer-locked-p (and value t)) + (magit-restore-section-visibility-cache mode)) + (when magit-uniquify-buffer-names + (add-to-list 'uniquify-list-buffers-directory-modes mode) + (with-current-buffer buffer + (setq list-buffers-directory (abbreviate-file-name default-directory))) + (let ((uniquify-buffer-name-style + (if (memq uniquify-buffer-name-style '(nil forward)) + 'post-forward-angle-brackets + uniquify-buffer-name-style))) + (uniquify-rationalize-file-buffer-names + name (file-name-directory (directory-file-name default-directory)) + buffer))) + buffer)) + +(defun magit-generate-buffer-name-default-function (mode &optional value) + "Generate buffer name for a MODE buffer in the current repository. +The returned name is based on `magit-buffer-name-format' and +takes `magit-uniquify-buffer-names' and VALUE, if non-nil, into +account." + (let ((m (substring (symbol-name mode) 0 -5)) + (v (and value (format "%s" (if (listp value) value (list value))))) + (n (if magit-uniquify-buffer-names + (file-name-nondirectory + (directory-file-name default-directory)) + (abbreviate-file-name default-directory)))) + (format-spec + magit-buffer-name-format + `((?m . ,m) + (?M . ,(if (eq mode 'magit-status-mode) "magit" m)) + (?v . ,(or v "")) + (?V . ,(if v (concat " " v) "")) + (?t . ,n) + (?x . ,(if magit-uniquify-buffer-names "" "*")) + (?T . ,(if magit-uniquify-buffer-names n (concat n "*"))))))) + +;;; Buffer Lock + +(defun magit-toggle-buffer-lock () + "Lock the current buffer to its value or unlock it. + +Locking a buffer to its value prevents it from being reused to +display another value. The name of a locked buffer contains its +value, which allows telling it apart from other locked buffers +and the unlocked buffer. + +Not all Magit buffers can be locked to their values, for example +it wouldn't make sense to lock a status buffer. + +There can only be a single unlocked buffer using a certain +major-mode per repository. So when a buffer is being unlocked +and another unlocked buffer already exists for that mode and +repository, then the former buffer is instead deleted and the +latter is displayed in its place." + (interactive) + (if magit-buffer-locked-p + (if-let ((unlocked (magit-get-mode-buffer major-mode))) + (let ((locked (current-buffer))) + (switch-to-buffer unlocked nil t) + (kill-buffer locked)) + (setq magit-buffer-locked-p nil) + (rename-buffer (funcall magit-generate-buffer-name-function + major-mode))) + (if-let ((value (magit-buffer-value))) + (if-let ((locked (magit-get-mode-buffer major-mode value))) + (let ((unlocked (current-buffer))) + (switch-to-buffer locked nil t) + (kill-buffer unlocked)) + (setq magit-buffer-locked-p t) + (rename-buffer (funcall magit-generate-buffer-name-function + major-mode value))) + (user-error "Buffer has no value it could be locked to")))) + +;;; Bury Buffer + +(defun magit-mode-bury-buffer (&optional kill-buffer) + "Bury the current buffer. +With a prefix argument, kill the buffer instead. +With two prefix arguments, also kill all Magit buffers associated +with this repository. +This is done using `magit-bury-buffer-function'." + (interactive "P") + ;; Kill all associated Magit buffers when a double prefix arg is given. + (when (>= (prefix-numeric-value kill-buffer) 16) + (let ((current (current-buffer))) + (dolist (buf (magit-mode-get-buffers)) + (unless (eq buf current) + (kill-buffer buf))))) + (funcall magit-bury-buffer-function kill-buffer)) + +(defun magit-mode-quit-window (kill-buffer) + "Quit the selected window and bury its buffer. + +This behaves similar to `quit-window', but when the window +was originally created to display a Magit buffer and the +current buffer is the last remaining Magit buffer that was +ever displayed in the selected window, then delete that +window." + (if (or (one-window-p) + (--first (let ((buffer (car it))) + (and (not (eq buffer (current-buffer))) + (buffer-live-p buffer) + (or (not (window-parameter nil 'magit-dedicated)) + (with-current-buffer buffer + (derived-mode-p 'magit-mode + 'magit-process-mode))))) + (window-prev-buffers))) + (quit-window kill-buffer) + (let ((window (selected-window))) + (quit-window kill-buffer) + (when (window-live-p window) + (delete-window window))))) + +;;; Refresh Buffers + +(defvar inhibit-magit-refresh nil) + +(defun magit-refresh () + "Refresh some buffers belonging to the current repository. + +Refresh the current buffer if its major mode derives from +`magit-mode', and refresh the corresponding status buffer. + +Run hooks `magit-pre-refresh-hook' and `magit-post-refresh-hook'." + (interactive) + (unless inhibit-magit-refresh + (unwind-protect + (let ((start (current-time)) + (magit--refresh-cache (or magit--refresh-cache + (list (cons 0 0))))) + (when magit-refresh-verbose + (message "Refreshing magit...")) + (magit-run-hook-with-benchmark 'magit-pre-refresh-hook) + (cond ((derived-mode-p 'magit-mode) + (magit-refresh-buffer)) + ((derived-mode-p 'tabulated-list-mode) + (revert-buffer))) + (--when-let (and magit-refresh-status-buffer + (not (derived-mode-p 'magit-status-mode)) + (magit-get-mode-buffer 'magit-status-mode)) + (with-current-buffer it + (magit-refresh-buffer))) + (magit-auto-revert-buffers) + (cond + ((and (not this-command) + (memq last-command magit-post-commit-hook-commands)) + (magit-run-hook-with-benchmark 'magit-post-commit-hook)) + ((memq this-command magit-post-stage-hook-commands) + (magit-run-hook-with-benchmark 'magit-post-stage-hook)) + ((memq this-command magit-post-unstage-hook-commands) + (magit-run-hook-with-benchmark 'magit-post-unstage-hook))) + (magit-run-hook-with-benchmark 'magit-post-refresh-hook) + (when magit-refresh-verbose + (message "Refreshing magit...done (%.3fs, cached %s/%s)" + (float-time (time-subtract (current-time) start)) + (caar magit--refresh-cache) + (+ (caar magit--refresh-cache) + (cdar magit--refresh-cache))))) + (run-hooks 'magit-unwind-refresh-hook)))) + +(defun magit-refresh-all () + "Refresh all buffers belonging to the current repository. + +Refresh all Magit buffers belonging to the current repository, +and revert buffers that visit files located inside the current +repository. + +Run hooks `magit-pre-refresh-hook' and `magit-post-refresh-hook'." + (interactive) + (magit-run-hook-with-benchmark 'magit-pre-refresh-hook) + (dolist (buffer (magit-mode-get-buffers)) + (with-current-buffer buffer (magit-refresh-buffer))) + (magit-auto-revert-buffers) + (magit-run-hook-with-benchmark 'magit-post-refresh-hook)) + +(defvar-local magit-refresh-start-time nil) + +(defun magit-refresh-buffer () + "Refresh the current Magit buffer." + (setq magit-refresh-start-time (current-time)) + (let ((refresh (intern (format "%s-refresh-buffer" + (substring (symbol-name major-mode) 0 -5)))) + (magit--refresh-cache (or magit--refresh-cache (list (cons 0 0))))) + (when (functionp refresh) + (when magit-refresh-verbose + (message "Refreshing buffer `%s'..." (buffer-name))) + (let* ((buffer (current-buffer)) + (windows + (--mapcat (with-selected-window it + (with-current-buffer buffer + (when-let ((section (magit-current-section))) + (list + (nconc (list it section) + (magit-refresh-get-relative-position)))))) + (or (get-buffer-window-list buffer nil t) + (list (selected-window)))))) + (deactivate-mark) + (setq magit-section-highlight-overlays nil) + (setq magit-section-highlighted-section nil) + (setq magit-section-highlighted-sections nil) + (setq magit-section-unhighlight-sections nil) + (magit-process-unset-mode-line-error-status) + (let ((inhibit-read-only t)) + (erase-buffer) + (save-excursion + (apply refresh (with-no-warnings magit-refresh-args)))) + (dolist (window windows) + (with-selected-window (car window) + (with-current-buffer buffer + (apply #'magit-section-goto-successor (cdr window))))) + (run-hooks 'magit-refresh-buffer-hook) + (magit-section-update-highlight) + (set-buffer-modified-p nil)) + (when magit-refresh-verbose + (message "Refreshing buffer `%s'...done (%.3fs)" (buffer-name) + (float-time (time-subtract (current-time) + magit-refresh-start-time))))))) + +(defun magit-refresh-get-relative-position () + (when-let ((section (magit-current-section))) + (let ((start (oref section start))) + (list (count-lines start (point)) + (- (point) (line-beginning-position)) + (and (magit-hunk-section-p section) + (region-active-p) + (progn (goto-char (line-beginning-position)) + (when (looking-at "^[-+]") (forward-line)) + (while (looking-at "^[ @]") (forward-line)) + (let ((beg (point))) + (cond ((looking-at "^[-+]") + (forward-line) + (while (looking-at "^[-+]") (forward-line)) + (while (looking-at "^ ") (forward-line)) + (forward-line -1) + (regexp-quote (buffer-substring-no-properties + beg (line-end-position)))) + (t t))))))))) + +;;; Save File-Visiting Buffers + +(defvar disable-magit-save-buffers nil) + +(defun magit-pre-command-hook () + (setq disable-magit-save-buffers nil)) +(add-hook 'pre-command-hook #'magit-pre-command-hook) + +(defvar magit-after-save-refresh-buffers nil) + +(defun magit-after-save-refresh-buffers () + (dolist (buffer magit-after-save-refresh-buffers) + (when (buffer-live-p buffer) + (with-current-buffer buffer + (magit-refresh-buffer)))) + (setq magit-after-save-refresh-buffers nil) + (remove-hook 'post-command-hook 'magit-after-save-refresh-buffers)) + +(defun magit-after-save-refresh-status () + "Refresh the status buffer of the current repository. + +This function is intended to be added to `after-save-hook'. + +If the status buffer does not exist or the file being visited in +the current buffer isn't inside the working tree of a repository, +then do nothing. + +Note that refreshing a Magit buffer is done by re-creating its +contents from scratch, which can be slow in large repositories. +If you are not satisfied with Magit's performance, then you +should obviously not add this function to that hook." + (when (and (not disable-magit-save-buffers) + (magit-inside-worktree-p t)) + (--when-let (ignore-errors (magit-get-mode-buffer 'magit-status-mode)) + (add-to-list 'magit-after-save-refresh-buffers it) + (add-hook 'post-command-hook 'magit-after-save-refresh-buffers)))) + +(defun magit-maybe-save-repository-buffers () + "Maybe save file-visiting buffers belonging to the current repository. +Do so if `magit-save-repository-buffers' is non-nil. You should +not remove this from any hooks, instead set that variable to nil +if you so desire." + (when (and magit-save-repository-buffers + (not disable-magit-save-buffers)) + (setq disable-magit-save-buffers t) + (let ((msg (current-message))) + (magit-save-repository-buffers + (eq magit-save-repository-buffers 'dontask)) + (when (and msg + (current-message) + (not (equal msg (current-message)))) + (message "%s" msg))))) + +(add-hook 'magit-pre-refresh-hook #'magit-maybe-save-repository-buffers) +(add-hook 'magit-pre-call-git-hook #'magit-maybe-save-repository-buffers) +(add-hook 'magit-pre-start-git-hook #'magit-maybe-save-repository-buffers) + +(defvar-local magit-inhibit-refresh-save nil) + +(defun magit-save-repository-buffers (&optional arg) + "Save file-visiting buffers belonging to the current repository. +After any buffer where `buffer-save-without-query' is non-nil +is saved without asking, the user is asked about each modified +buffer which visits a file in the current repository. Optional +argument (the prefix) non-nil means save all with no questions." + (interactive "P") + (when-let ((topdir (magit-rev-parse-safe "--show-toplevel"))) + (let ((remote (file-remote-p topdir)) + (save-some-buffers-action-alist + `((?Y (lambda (buffer) + (with-current-buffer buffer + (setq buffer-save-without-query t) + (save-buffer))) + "to save the current buffer and remember choice") + (?N (lambda (buffer) + (with-current-buffer buffer + (setq magit-inhibit-refresh-save t))) + "to skip the current buffer and remember choice") + ,@save-some-buffers-action-alist))) + (save-some-buffers + arg (lambda () + (and (not magit-inhibit-refresh-save) + buffer-file-name + ;; Avoid needlessly connecting to unrelated remotes. + (equal (file-remote-p buffer-file-name) + remote) + ;; For remote files this makes network requests and + ;; therefore has to come after the above to avoid + ;; unnecessarily waiting for unrelated hosts. + (file-exists-p (file-name-directory buffer-file-name)) + (string-prefix-p topdir (file-truename buffer-file-name)) + (equal (magit-rev-parse-safe "--show-toplevel") + topdir))))))) + +;;; Restore Window Configuration + +(defvar magit-inhibit-save-previous-winconf nil) + +(defvar-local magit-previous-window-configuration nil) +(put 'magit-previous-window-configuration 'permanent-local t) + +(defun magit-save-window-configuration () + "Save the current window configuration. + +Later, when the buffer is buried, it may be restored by +`magit-restore-window-configuration'." + (if magit-inhibit-save-previous-winconf + (when (eq magit-inhibit-save-previous-winconf 'unset) + (setq magit-previous-window-configuration nil)) + (unless (get-buffer-window (current-buffer) (selected-frame)) + (setq magit-previous-window-configuration + (current-window-configuration))))) + +(defun magit-restore-window-configuration (&optional kill-buffer) + "Bury or kill the current buffer and restore previous window configuration." + (let ((winconf magit-previous-window-configuration) + (buffer (current-buffer)) + (frame (selected-frame))) + (quit-window kill-buffer (selected-window)) + (when (and winconf (equal frame (window-configuration-frame winconf))) + (set-window-configuration winconf) + (when (buffer-live-p buffer) + (with-current-buffer buffer + (setq magit-previous-window-configuration nil)))))) + +;;; Buffer History + +(defun magit-go-backward () + "Move backward in current buffer's history." + (interactive) + (if help-xref-stack + (help-xref-go-back (current-buffer)) + (user-error "No previous entry in buffer's history"))) + +(defun magit-go-forward () + "Move forward in current buffer's history." + (interactive) + (if help-xref-forward-stack + (help-xref-go-forward (current-buffer)) + (user-error "No next entry in buffer's history"))) + +(defun magit-insert-xref-buttons () + "Insert xref buttons." + (when (or help-xref-stack help-xref-forward-stack) + (when help-xref-stack + (magit-xref-insert-button help-back-label 'magit-xref-backward)) + (when help-xref-forward-stack + (when help-xref-stack + (insert " ")) + (magit-xref-insert-button help-forward-label 'magit-xref-forward)))) + +(defun magit-xref-insert-button (label type) + (magit-insert-section (button label) + (insert-text-button label 'type type + 'help-args (list (current-buffer))))) + +(define-button-type 'magit-xref-backward + :supertype 'help-back + 'mouse-face 'magit-section-highlight + 'help-echo (purecopy "mouse-2, RET: go back to previous history entry")) + +(define-button-type 'magit-xref-forward + :supertype 'help-forward + 'mouse-face 'magit-section-highlight + 'help-echo (purecopy "mouse-2, RET: go back to next history entry")) + +(defvar magit-xref-modes + '(magit-log-mode + magit-reflog-mode + magit-diff-mode + magit-revision-mode) + "List of modes for which to insert navigation buttons.") + +(defun magit-xref-setup (fn args) + (when (memq major-mode magit-xref-modes) + (when help-xref-stack-item + (push (cons (point) help-xref-stack-item) help-xref-stack) + (setq help-xref-forward-stack nil)) + (when (called-interactively-p 'interactive) + (--when-let (nthcdr 10 help-xref-stack) + (setcdr it nil))) + (setq help-xref-stack-item + (list 'magit-xref-restore fn default-directory args)))) + +(defun magit-xref-restore (fn dir args) + (setq default-directory dir) + (funcall fn major-mode nil args) + (magit-refresh-buffer)) + +;;; Repository-Local Cache + +(defvar magit-repository-local-cache nil + "Alist mapping `magit-toplevel' paths to alists of key/value pairs.") + +(defun magit-repository-local-repository () + "Return the key for the current repository." + (or (bound-and-true-p magit--default-directory) + (magit-toplevel))) + +(defun magit-repository-local-set (key value &optional repository) + "Set the repository-local VALUE for KEY. + +Unless specified, REPOSITORY is the current buffer's repository. + +If REPOSITORY is nil (meaning there is no current repository), +then the value is not cached, and we return nil." + (let* ((repokey (or repository (magit-repository-local-repository))) + (cache (assoc repokey magit-repository-local-cache))) + ;; Don't cache values for a nil REPOSITORY, as the 'set' and 'get' + ;; calls for some KEY may happen in unrelated contexts. + (when repokey + (if cache + (let ((keyvalue (assoc key (cdr cache)))) + (if keyvalue + ;; Update pre-existing value for key. + (setcdr keyvalue value) + ;; No such key in repository-local cache. + (push (cons key value) (cdr cache)))) + ;; No cache for this repository. + (push (cons repokey (list (cons key value))) + magit-repository-local-cache))))) + +(defun magit-repository-local-exists-p (key &optional repository) + "Non-nil when a repository-local value exists for KEY. + +Returns a (KEY . value) cons cell. + +The KEY is matched using `equal'. + +Unless specified, REPOSITORY is the current buffer's repository." + (let* ((repokey (or repository (magit-repository-local-repository))) + (cache (assoc repokey magit-repository-local-cache))) + (and cache + (assoc key (cdr cache))))) + +(defun magit-repository-local-get (key &optional default repository) + "Return the repository-local value for KEY. + +Return DEFAULT if no value for KEY exists. + +The KEY is matched using `equal'. + +Unless specified, REPOSITORY is the current buffer's repository." + (let ((keyvalue (magit-repository-local-exists-p key repository))) + (if keyvalue + (cdr keyvalue) + default))) + +(defun magit-repository-local-delete (key &optional repository) + "Delete the repository-local value for KEY. + +Unless specified, REPOSITORY is the current buffer's repository." + (let* ((repokey (or repository (magit-repository-local-repository))) + (cache (assoc repokey magit-repository-local-cache))) + (when cache + ;; There is no `assoc-delete-all'. + (setf (cdr cache) + (cl-delete key (cdr cache) :key #'car :test #'equal))))) + +(defun magit-zap-caches () + "Zap caches for the current repository. +Remove the repository's entry from `magit-repository-local-cache' +and set `magit-section-visibility-cache' to nil in all of the +repository's Magit buffers." + (interactive) + (magit-with-toplevel + (setq magit-repository-local-cache + (cl-delete default-directory + magit-repository-local-cache + :key #'car :test #'equal))) + (dolist (buffer (magit-mode-get-buffers)) + (with-current-buffer buffer + (setq magit-section-visibility-cache nil))) + (setq magit--libgit-available-p eieio-unbound)) + +;;; Utilities + +(defun magit-run-hook-with-benchmark (hook) + (when hook + (if magit-refresh-verbose + (let ((start (current-time))) + (message "Running %s..." hook) + (run-hooks hook) + (message "Running %s...done (%.3fs)" hook + (float-time (time-subtract (current-time) start)))) + (run-hooks hook)))) + +;;; _ +(provide 'magit-mode) +;;; magit-mode.el ends here diff --git a/elpa/magit-20191122.2040/magit-mode.elc b/elpa/magit-20191122.2040/magit-mode.elc new file mode 100644 index 0000000000000000000000000000000000000000..4eb13736e43accaca65dd6debd7ab4415244f9a2 GIT binary patch literal 59591 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 literal 0 HcmV?d00001 diff --git a/elpa/magit-20191122.2040/magit-notes.el b/elpa/magit-20191122.2040/magit-notes.el new file mode 100644 index 00000000..1bd1fd34 --- /dev/null +++ b/elpa/magit-20191122.2040/magit-notes.el @@ -0,0 +1,200 @@ +;;; magit-notes.el --- notes support -*- lexical-binding: t -*- + +;; Copyright (C) 2010-2019 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; This library implements support for `git-notes'. + +;;; Code: + +(require 'magit) + +;;; Commands + +;;;###autoload (autoload 'magit-notes "magit" nil t) +(define-transient-command magit-notes () + "Edit notes attached to commits." + :man-page "git-notes" + ["Configure local settings" + ("c" magit-core.notesRef) + ("d" magit-notes.displayRef)] + ["Configure global settings" + ("C" magit-global-core.notesRef) + ("D" magit-global-notes.displayRef)] + ["Arguments for prune" + :if-not magit-notes-merging-p + ("-n" "Dry run" ("-n" "--dry-run"))] + ["Arguments for edit and remove" + :if-not magit-notes-merging-p + (magit-notes:--ref)] + ["Arguments for merge" + :if-not magit-notes-merging-p + (magit-notes:--strategy)] + ["Actions" + :if-not magit-notes-merging-p + ("T" "Edit" magit-notes-edit) + ("r" "Remove" magit-notes-remove) + ("m" "Merge" magit-notes-merge) + ("p" "Prune" magit-notes-prune)] + ["Actions" + :if magit-notes-merging-p + ("c" "Commit merge" magit-notes-merge-commit) + ("a" "Abort merge" magit-notes-merge-abort)]) + +(defun magit-notes-merging-p () + (let ((dir (magit-git-dir "NOTES_MERGE_WORKTREE"))) + (and (file-directory-p dir) + (directory-files dir nil "^[^.]")))) + +(define-infix-command magit-core.notesRef () + :class 'magit--git-variable + :variable "core.notesRef" + :reader 'magit-notes-read-ref + :prompt "Set local core.notesRef") + +(define-infix-command magit-notes.displayRef () + :class 'magit--git-variable + :variable "notes.displayRef" + :multi-value t + :reader 'magit-notes-read-refs + :prompt "Set local notes.displayRef") + +(define-infix-command magit-global-core.notesRef () + :class 'magit--git-variable + :variable "core.notesRef" + :reader 'magit-notes-read-ref + :prompt "Set global core.notesRef") + +(define-infix-command magit-global-notes.displayRef () + :class 'magit--git-variable + :variable "notes.displayRef" + :multi-value t + :reader 'magit-notes-read-refs + :prompt "Set global notes.displayRef") + +(define-infix-argument magit-notes:--ref () + :description "Merge strategy" + :class 'transient-option + :key "-r" + :argument "--ref=" + :reader 'magit-notes-read-ref) + +(define-infix-argument magit-notes:--strategy () + :description "Merge strategy" + :class 'transient-option + :shortarg "-s" + :argument "--strategy=" + :choices '("manual" "ours" "theirs" "union" "cat_sort_uniq")) + +(defun magit-notes-edit (commit &optional ref) + "Edit the note attached to COMMIT. +REF is the notes ref used to store the notes. + +Interactively or when optional REF is nil use the value of Git +variable `core.notesRef' or \"refs/notes/commits\" if that is +undefined." + (interactive (magit-notes-read-args "Edit notes")) + (magit-run-git-with-editor "notes" (and ref (concat "--ref=" ref)) + "edit" commit)) + +(defun magit-notes-remove (commit &optional ref) + "Remove the note attached to COMMIT. +REF is the notes ref from which the note is removed. + +Interactively or when optional REF is nil use the value of Git +variable `core.notesRef' or \"refs/notes/commits\" if that is +undefined." + (interactive (magit-notes-read-args "Remove notes")) + (magit-run-git-with-editor "notes" (and ref (concat "--ref=" ref)) + "remove" commit)) + +(defun magit-notes-merge (ref) + "Merge the notes ref REF into the current notes ref. + +The current notes ref is the value of Git variable +`core.notesRef' or \"refs/notes/commits\" if that is undefined. + +When there are conflicts, then they have to be resolved in the +temporary worktree \".git/NOTES_MERGE_WORKTREE\". When +done use `magit-notes-merge-commit' to finish. To abort +use `magit-notes-merge-abort'." + (interactive (list (magit-read-string-ns "Merge reference"))) + (magit-run-git-with-editor "notes" "merge" ref)) + +(defun magit-notes-merge-commit () + "Commit the current notes ref merge. +Also see `magit-notes-merge'." + (interactive) + (magit-run-git-with-editor "notes" "merge" "--commit")) + +(defun magit-notes-merge-abort () + "Abort the current notes ref merge. +Also see `magit-notes-merge'." + (interactive) + (magit-run-git-with-editor "notes" "merge" "--abort")) + +(defun magit-notes-prune (&optional dry-run) + "Remove notes about unreachable commits." + (interactive (list (and (member "--dry-run" (transient-args 'magit-notes)) t))) + (when dry-run + (magit-process-buffer)) + (magit-run-git-with-editor "notes" "prune" (and dry-run "--dry-run"))) + +;;; Readers + +(defun magit-notes-read-ref (prompt _initial-input history) + (--when-let (magit-completing-read + prompt (magit-list-notes-refnames) nil nil + (--when-let (magit-get "core.notesRef") + (if (string-prefix-p "refs/notes/" it) + (substring it 11) + it)) + history) + (if (string-prefix-p "refs/" it) + it + (concat "refs/notes/" it)))) + +(defun magit-notes-read-refs (prompt) + (mapcar (lambda (ref) + (if (string-prefix-p "refs/" ref) + ref + (concat "refs/notes/" ref))) + (completing-read-multiple + (concat prompt ": ") + (magit-list-notes-refnames) nil nil + (mapconcat (lambda (ref) + (if (string-prefix-p "refs/notes/" ref) + (substring ref 11) + ref)) + (magit-get-all "notes.displayRef") + ",")))) + +(defun magit-notes-read-args (prompt) + (list (magit-read-branch-or-commit prompt (magit-stash-at-point)) + (--when-let (--first (string-match "^--ref=\\(.+\\)" it) + (transient-args 'magit-notes)) + (match-string 1 it)))) + +;;; _ +(provide 'magit-notes) +;;; magit-notes.el ends here diff --git a/elpa/magit-20191122.2040/magit-notes.elc b/elpa/magit-20191122.2040/magit-notes.elc new file mode 100644 index 0000000000000000000000000000000000000000..bbbefeefefd230b34b8a3a853d864787abe84c25 GIT binary patch literal 9045 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 GHU0y%2|^?Q literal 0 HcmV?d00001 diff --git a/elpa/magit-20191122.2040/magit-obsolete.el b/elpa/magit-20191122.2040/magit-obsolete.el new file mode 100644 index 00000000..46f7520e --- /dev/null +++ b/elpa/magit-20191122.2040/magit-obsolete.el @@ -0,0 +1,106 @@ +;;; magit-obsolete.el --- obsolete definitions -*- lexical-binding: t -*- + +;; Copyright (C) 2010-2019 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; This library defines aliases for obsolete variables and functions. + +;;; Code: + +(require 'magit) + +;;; Obsolete since v2.91.0 + +(define-obsolete-function-alias 'magit-diff-visit-file-worktree + 'magit-diff-visit-worktree-file "Magit 2.91.0") + +(define-obsolete-function-alias 'magit-status-internal + 'magit-status-setup-buffer "Magit 2.91.0") + +(define-obsolete-variable-alias 'magit-mode-setup-hook + 'magit-setup-buffer-hook "Magit 2.91.0") + +(define-obsolete-variable-alias 'magit-branch-popup-show-variables + 'magit-branch-direct-configure "Magit 2.91.0") + +(define-obsolete-function-alias 'magit-dispatch-popup + 'magit-dispatch "Magit 2.91.0") + +(define-obsolete-function-alias 'magit-repolist-column-dirty + 'magit-repolist-column-flag "Magit 2.91.0") + +(defun magit--magit-popup-warning () + (display-warning 'magit "\ +Magit no longer uses Magit-Popup. +It now uses Transient. +See https://emacsair.me/2019/02/14/transient-0.1. + +However your configuration and/or some third-party package that +you use still depends on the `magit-popup' package. But because +`magit' no longer depends on that, `package' has removed it from +your system. + +If some package that you use still depends on `magit-popup' but +does not declare it as a dependency, then please contact its +maintainer about that and install `magit-popup' explicitly. + +If you yourself use functions that are defined in `magit-popup' +in your configuration, then the next step depends on what you use +that for. + +* If you use `magit-popup' to define your own popups but do not + modify any of Magit's old popups, then you have to install + `magit-popup' explicitly. (You can also migrate to Transient, + but there is no need to rush that.) + +* If you add additional arguments and/or actions to Magit's popups, + then you have to port that to modify the new \"transients\" instead. + See https://github.com/magit/magit/wiki/\ +Converting-popup-modifications-to-transient-modifications + +To find installed packages that still use `magit-popup' you can +use e.g. \"M-x rgrep RET magit-popup RET RET ~/.emacs.d/ RET\".")) +(cl-eval-when (eval load) + (unless (require (quote magit-popup) nil t) + (defun magit-define-popup-switch (&rest _) + (magit--magit-popup-warning)) + (defun magit-define-popup-option (&rest _) + (magit--magit-popup-warning)) + (defun magit-define-popup-variable (&rest _) + (magit--magit-popup-warning)) + (defun magit-define-popup-action (&rest _) + (magit--magit-popup-warning)) + (defun magit-define-popup-sequence-action (&rest _) + (magit--magit-popup-warning)) + (defun magit-define-popup-key (&rest _) + (magit--magit-popup-warning)) + (defun magit-define-popup-keys-deferred (&rest _) + (magit--magit-popup-warning)) + (defun magit-change-popup-key (&rest _) + (magit--magit-popup-warning)) + (defun magit-remove-popup-key (&rest _) + (magit--magit-popup-warning)))) + +;;; _ +(provide 'magit-obsolete) +;;; magit-obsolete.el ends here diff --git a/elpa/magit-20191122.2040/magit-obsolete.elc b/elpa/magit-20191122.2040/magit-obsolete.elc new file mode 100644 index 0000000000000000000000000000000000000000..3eb98fe8adce7139203c78d7a00a4cd24852ef65 GIT binary patch literal 3795 zcmcInOK;mo5O#{5^apyKDnM-)CMD9ZxJH1cZh#tSf+F#y2#sb%E~SOZU3PbAMLqPl z_nRfDP>Fj=Y=9OuJ3EhWp1OSb`_*@QdwY}1%S*a4b)za-gfB|d%Ua})?xl6gXiCrG z<8ZQ8enq0H$TVKn>L1~8?BYo{yjdwnC8SX6q@!Y^MXhowOzyl@dg+dEYMm!h6tbYL zmgFK%FFun|7|77ZQ*N{uU~YXGJp)BYFWz2VUsJvkR^%Qg9tHJ67vv1(LeoN0WyFq> z-W5ku*h)!Deg($#xYG*=zUYq)_|m`0WOA_Bcp2rUkTlJX=W{&C_gR|oON!?h&k3H> zr#$YbHG3W8Uz765gRc zIr)YezI`3EKY5X*XJ_C|`FY9$*phQ*VP04?R-WQ89h>=4xf_(H^G=l2B4 z(*(-X`Gd;ejFfNn49XeJlpjWPjOLcO!wI|7(@!}EB6H5qr}WOszguM`)nchU6|xkS z60Z9i6{;+wd*zgmxJ070v3K6eo_l;eoCH47s)B?&8JUGMmGsDrS3!OnUnKE-+KYEy z_|`>AqaL*2E3hHzsZRQ~i56{HBJW|>Jql-JT8(^*I-Zp=cf;M$r6|x3oVb@obT6t_ z((rDTSiqg!)V0+9keb%-+6(@UrKq>+a+R@Hho1L4S+% zSb5*LpJp@34Ou7~*K(H5lZ)9roh2tTKd?vhIKh=n|7O+_&5kyvwcI-cc%e@dI^@h) zG|5_`{V7{SjbLCJk>80W(}d47F0v`)yh5WdWFvLq2vfkXB)uPDvOipmiGD%Y7cv*P znCXsbA5INU??@5;h~D=)_i2R^v9dNuEkfCp*3`iU*tv0D*1@Ukva@<@DSP;^p}R&d zS~#_xCWXu^fnFhcQsgT&8QxAD%&gRV)l#WuzER3^CLg zVA@qFKQxufm9I8~^=vCg#L21*MwhM5!|?27!6f7#RD{8}BQ8VYJrK^`UXF^EA3WkE zn{l|-Y-5j6rh~<$vB97p34jjp?dT$JdOJFeW(`C*O&tM8%yJ&dnI=NhP~`>~Y{--p z@_8RwQWZUWZyhUHp>43-9xJ}Rt8)Yw(ZQd%!b4nCnC7)wT7jmA>)XmWVhL;wT<1vg zng9rZ9Jp-jRsquZkgH+qDRvItI}~G%{wVCS<%We6=!ycH1g|nIVsNJOJ7^1;G4`b~ zw$B1w=&|S`v8HUgtxA_ogWFOR0G?=E(P+@Cb`hg<&O%Z3|JUkH&900_4SO`4zEK7h zD)08K$eU=ZBHB4(pKlEItdF?~T>7$scbpSlVRMP^hJpP9@R{Z#882ga@+$g3c8PvU zZ(iQesQANoru{pMLvM +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; This library implements patch commands. + +;;; Code: + +(eval-when-compile + (require 'subr-x)) + +(require 'magit) + +;;; Options + +(defcustom magit-patch-save-arguments '(exclude "--stat") + "Control arguments used by the command `magit-patch-save'. + +`magit-patch-save' (which see) saves a diff for the changes +shown in the current buffer in a patch file. It may use the +same arguments as used in the buffer or a subset thereof, or +a constant list of arguments, depending on this option and +the prefix argument." + :package-version '(magit . "2.12.0") + :group 'magit-diff + :type '(choice (const :tag "use buffer arguments" buffer) + (cons :tag "use buffer arguments except" + (const :format "" exclude) + (repeat :format "%v%i\n" + (string :tag "Argument"))) + (repeat :tag "use constant arguments" + (string :tag "Argument")))) + +;;; Commands + +;;;###autoload (autoload 'magit-patch "magit-patch" nil t) +(define-transient-command magit-patch () + "Create or apply patches." + ["Actions" + ("c" "Create patches" magit-patch-create) + ("a" "Apply patch" magit-patch-apply) + ("s" "Save diff as patch" magit-patch-save) + ("r" "Request pull" magit-request-pull)]) + +;;;###autoload (autoload 'magit-patch-create "magit-patch" nil t) +(define-transient-command magit-patch-create (range args files) + "Create patches for the commits in RANGE. +When a single commit is given for RANGE, create a patch for the +changes introduced by that commit (unlike 'git format-patch' +which creates patches for all commits that are reachable from +`HEAD' but not from the specified commit)." + :man-page "git-format-patch" + ["Mail arguments" + (magit-format-patch:--in-reply-to) + (magit-format-patch:--thread) + (magit-format-patch:--reroll-count) + (magit-format-patch:--subject-prefix) + ("C-m l " "Add cover letter" "--cover-letter") + (magit-format-patch:--from) + (magit-format-patch:--to) + (magit-format-patch:--cc) + (magit-format-patch:--output-directory)] + ["Diff arguments" + (magit-diff:-U) + (magit-diff:-M) + (magit-diff:-C) + (magit-diff:--diff-algorithm) + (magit:--) + (7 "-b" "Ignore whitespace changes" ("-b" "--ignore-space-change")) + (7 "-w" "Ignore all whitespace" ("-w" "--ignore-all-space"))] + ["Actions" + ("c" "Create patches" magit-patch-create)] + (interactive + (if (not (eq current-transient-command 'magit-patch-create)) + (list nil nil nil) + (cons (if-let ((revs (magit-region-values 'commit t))) + (concat (car (last revs)) "^.." (car revs)) + (let ((range (magit-read-range-or-commit + "Format range or commit"))) + (if (string-match-p "\\.\\." range) + range + (format "%s~..%s" range range)))) + (let ((args (transient-args 'magit-patch-create))) + (list (-filter #'stringp args) + (cdr (assoc "--" args))))))) + (if (not range) + (transient-setup 'magit-patch-create) + (magit-run-git "format-patch" range args "--" files) + (when (member "--cover-letter" args) + (save-match-data + (find-file + (expand-file-name + (concat (--some (and (string-match "\\`--reroll-count=\\(.+\\)" it) + (format "v%s-" (match-string 1 it))) + args) + "0000-cover-letter.patch") + (let ((topdir (magit-toplevel))) + (or (--some (and (string-match "\\`--output-directory=\\(.+\\)" it) + (expand-file-name (match-string 1 it) topdir)) + args) + topdir)))))))) + +(define-infix-argument magit-format-patch:--in-reply-to () + :description "In reply to" + :class 'transient-option + :key "C-m r " + :argument "--in-reply-to=") + +(define-infix-argument magit-format-patch:--thread () + :description "Thread style" + :class 'transient-option + :key "C-m s " + :argument "--thread=") + +(define-infix-argument magit-format-patch:--reroll-count () + :description "Reroll count" + :class 'transient-option + :key "C-m v " + :shortarg "-v" + :argument "--reroll-count=" + :reader 'transient-read-number-N+) + +(define-infix-argument magit-format-patch:--subject-prefix () + :description "Subject Prefix" + :class 'transient-option + :key "C-m p " + :argument "--subject-prefix=") + +(define-infix-argument magit-format-patch:--from () + :description "From" + :class 'transient-option + :key "C-m C-f" + :argument "--from=" + :reader 'magit-transient-read-person) + +(define-infix-argument magit-format-patch:--to () + :description "To" + :class 'transient-option + :key "C-m C-t" + :argument "--to=" + :reader 'magit-transient-read-person) + +(define-infix-argument magit-format-patch:--cc () + :description "CC" + :class 'transient-option + :key "C-m C-c" + :argument "--cc=" + :reader 'magit-transient-read-person) + +(define-infix-argument magit-format-patch:--output-directory () + :description "Output directory" + :class 'transient-option + :key "C-m o " + :shortarg "-o" + :argument "--output-directory=" + :reader 'transient-read-existing-directory) + +;;;###autoload (autoload 'magit-patch-apply "magit-patch" nil t) +(define-transient-command magit-patch-apply (file &rest args) + "Apply the patch file FILE." + :man-page "git-apply" + ["Arguments" + ("-i" "Also apply to index" "--index") + ("-c" "Only apply to index" "--cached") + ("-3" "Fall back on 3way merge" ("-3" "--3way"))] + ["Actions" + ("a" "Apply patch" magit-patch-apply)] + (interactive + (if (not (eq current-transient-command 'magit-patch-apply)) + (list nil) + (list (expand-file-name + (read-file-name "Apply patch: " + default-directory nil nil + (when-let ((file (magit-file-at-point))) + (file-relative-name file)))) + (transient-args 'magit-patch-apply)))) + (if (not file) + (transient-setup 'magit-patch-apply) + (magit-run-git "apply" args "--" (magit-convert-filename-for-git file)))) + +;;;###autoload +(defun magit-patch-save (file &optional arg) + "Write current diff into patch FILE. + +What arguments are used to create the patch depends on the value +of `magit-patch-save-arguments' and whether a prefix argument is +used. + +If the value is the symbol `buffer', then use the same arguments +as the buffer. With a prefix argument use no arguments. + +If the value is a list beginning with the symbol `exclude', then +use the same arguments as the buffer except for those matched by +entries in the cdr of the list. The comparison is done using +`string-prefix-p'. With a prefix argument use the same arguments +as the buffer. + +If the value is a list of strings (including the empty list), +then use those arguments. With a prefix argument use the same +arguments as the buffer. + +Of course the arguments that are required to actually show the +same differences as those shown in the buffer are always used." + (interactive (list (read-file-name "Write patch file: " default-directory) + current-prefix-arg)) + (unless (derived-mode-p 'magit-diff-mode) + (user-error "Only diff buffers can be saved as patches")) + (let ((rev magit-buffer-range) + (typearg magit-buffer-typearg) + (args magit-buffer-diff-args) + (files magit-buffer-diff-files)) + (cond ((eq magit-patch-save-arguments 'buffer) + (when arg + (setq args nil))) + ((eq (car-safe magit-patch-save-arguments) 'exclude) + (unless arg + (setq args (-difference args (cdr magit-patch-save-arguments))))) + ((not arg) + (setq args magit-patch-save-arguments))) + (with-temp-file file + (magit-git-insert "diff" rev "-p" typearg args "--" files))) + (magit-refresh)) + +;;;###autoload +(defun magit-request-pull (url start end) + "Request upstream to pull from you public repository. + +URL is the url of your publicly accessible repository. +START is a commit that already is in the upstream repository. +END is the last commit, usually a branch name, which upstream +is asked to pull. START has to be reachable from that commit." + (interactive + (list (magit-get "remote" (magit-read-remote "Remote") "url") + (magit-read-branch-or-commit "Start" (magit-get-upstream-branch)) + (magit-read-branch-or-commit "End"))) + (let ((dir default-directory)) + ;; mu4e changes default-directory + (compose-mail) + (setq default-directory dir)) + (message-goto-body) + (magit-git-insert "request-pull" start url end) + (set-buffer-modified-p nil)) + +;;; _ +(provide 'magit-patch) +;;; magit-patch.el ends here diff --git a/elpa/magit-20191122.2040/magit-patch.elc b/elpa/magit-20191122.2040/magit-patch.elc new file mode 100644 index 0000000000000000000000000000000000000000..8f9d0a76d033e13017e8b5f3fbc46c406db421b5 GIT binary patch literal 13403 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 pu?oU_4g3Ob-ime2T&SiNxUnDkQ0opu=%z`09N +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; This library implements the tools used to run Git for side-effects. + +;; Note that the functions used to run Git and then consume its +;; output, are defined in `magit-git.el'. There's a bit of overlap +;; though. + +;;; Code: + +(require 'ansi-color) +(require 'cl-lib) +(require 'dash) + +(eval-when-compile + (require 'subr-x)) + +(require 'with-editor) +(require 'magit-utils) +(require 'magit-section) +(require 'magit-git) +(require 'magit-mode) + +(declare-function auth-source-search "auth-source" + (&rest spec &key max require create delete &allow-other-keys)) + +;;; Options + +(defcustom magit-process-connection-type (not (eq system-type 'cygwin)) + "Connection type used for the Git process. + +If nil, use pipes: this is usually more efficient, and works on Cygwin. +If t, use ptys: this enables Magit to prompt for passphrases when needed." + :group 'magit-process + :type '(choice (const :tag "pipe" nil) + (const :tag "pty" t))) + +(defcustom magit-need-cygwin-noglob + (and (eq system-type 'windows-nt) + (with-temp-buffer + (let ((process-environment + (append magit-git-environment process-environment))) + (condition-case e + (process-file magit-git-executable + nil (current-buffer) nil + "-c" "alias.echo=!echo" "echo" "x{0}") + (file-error + (lwarn 'magit-process :warning + "Could not run Git: %S" e)))) + (equal "x0\n" (buffer-string)))) + "Whether to use a workaround for Cygwin's globbing behavior. + +If non-nil, add environment variables to `process-environment' to +prevent the git.exe distributed by Cygwin and MSYS2 from +attempting to perform glob expansion when called from a native +Windows build of Emacs. See #2246." + :package-version '(magit . "2.3.0") + :group 'magit-process + :type '(choice (const :tag "Yes" t) + (const :tag "No" nil))) + +(defcustom magit-process-popup-time -1 + "Popup the process buffer if a command takes longer than this many seconds." + :group 'magit-process + :type '(choice (const :tag "Never" -1) + (const :tag "Immediately" 0) + (integer :tag "After this many seconds"))) + +(defcustom magit-process-log-max 32 + "Maximum number of sections to keep in a process log buffer. +When adding a new section would go beyond the limit set here, +then the older half of the sections are remove. Sections that +belong to processes that are still running are never removed. +When this is nil, no sections are ever removed." + :package-version '(magit . "2.1.0") + :group 'magit-process + :type '(choice (const :tag "Never remove old sections" nil) integer)) + +(defcustom magit-process-error-tooltip-max-lines 20 + "The number of lines for `magit-process-error-lines' to return. + +These are displayed in a tooltip for `mode-line-process' errors. + +If `magit-process-error-tooltip-max-lines' is nil, the tooltip +displays the text of `magit-process-error-summary' instead." + :package-version '(magit . "2.12.0") + :group 'magit-process + :type '(choice (const :tag "Use summary line" nil) + integer)) + +(defcustom magit-credential-cache-daemon-socket + (--some (pcase-let ((`(,prog . ,args) (split-string it))) + (if (and prog + (string-match-p + "\\`\\(?:\\(?:/.*/\\)?git-credential-\\)?cache\\'" prog)) + (or (cl-loop for (opt val) on args + if (string= opt "--socket") + return val) + (expand-file-name "~/.git-credential-cache/socket")))) + ;; Note: `magit-process-file' is not yet defined when + ;; evaluating this form, so we use `process-lines'. + (ignore-errors + (let ((process-environment + (append magit-git-environment process-environment))) + (process-lines magit-git-executable + "config" "--get-all" "credential.helper")))) + "If non-nil, start a credential cache daemon using this socket. + +When using Git's cache credential helper in the normal way, Emacs +sends a SIGHUP to the credential daemon after the git subprocess +has exited, causing the daemon to also quit. This can be avoided +by starting the `git-credential-cache--daemon' process directly +from Emacs. + +The function `magit-maybe-start-credential-cache-daemon' takes +care of starting the daemon if necessary, using the value of this +option as the socket. If this option is nil, then it does not +start any daemon. Likewise if another daemon is already running, +then it starts no new daemon. This function has to be a member +of the hook variable `magit-credential-hook' for this to work. +If an error occurs while starting the daemon, most likely because +the necessary executable is missing, then the function removes +itself from the hook, to avoid further futile attempts." + :package-version '(magit . "2.3.0") + :group 'magit-process + :type '(choice (file :tag "Socket") + (const :tag "Don't start a cache daemon" nil))) + +(defcustom magit-process-yes-or-no-prompt-regexp + (concat " [\[(]" + "\\([Yy]\\(?:es\\)?\\)" + "[/|]" + "\\([Nn]o?\\)" + ;; OpenSSH v8 prints this. See #3969. + "\\(?:/\\[fingerprint\\]\\)?" + "[\])] ?[?:] ?$") + "Regexp matching Yes-or-No prompts of Git and its subprocesses." + :package-version '(magit . "2.1.0") + :group 'magit-process + :type 'regexp) + +(defcustom magit-process-password-prompt-regexps + '("^\\(Enter \\)?[Pp]assphrase\\( for \\(RSA \\)?key '.*'\\)?: ?$" + ;; Match-group 99 is used to identify the "user@host" part. + "^\\(Enter \\)?[Pp]assword\\( for '\\(https?://\\)?\\(?99:.*\\)'\\)?: ?$" + "^.*'s password: ?$" + "^Yubikey for .*: ?$" + "^Enter PIN for .*: ?$") + "List of regexps matching password prompts of Git and its subprocesses. +Also see `magit-process-find-password-functions'." + :package-version '(magit . "2.8.0") + :group 'magit-process + :type '(repeat (regexp))) + +(defcustom magit-process-find-password-functions nil + "List of functions to try in sequence to get a password. + +These functions may be called when git asks for a password, which +is detected using `magit-process-password-prompt-regexps'. They +are called if and only if matching the prompt resulted in the +value of the 99th submatch to be non-nil. Therefore users can +control for which prompts these functions should be called by +putting the host name in the 99th submatch, or not. + +If the functions are called, then they are called in the order +given, with the host name as only argument, until one of them +returns non-nil. If they are not called or none of them returns +non-nil, then the password is read from the user instead." + :package-version '(magit . "2.3.0") + :group 'magit-process + :type 'hook + :options '(magit-process-password-auth-source)) + +(defcustom magit-process-username-prompt-regexps + '("^Username for '.*': ?$") + "List of regexps matching username prompts of Git and its subprocesses." + :package-version '(magit . "2.1.0") + :group 'magit-process + :type '(repeat (regexp))) + +(defcustom magit-process-prompt-functions nil + "List of functions used to forward arbitrary questions to the user. + +Magit has dedicated support for forwarding username and password +prompts and Yes-or-No questions asked by Git and its subprocesses +to the user. This can be customized using other options in the +`magit-process' customization group. + +If you encounter a new question that isn't handled by default, +then those options should be used instead of this hook. + +However subprocesses may also ask questions that differ too much +from what the code related to the above options assume, and this +hook allows users to deal with such questions explicitly. + +Each function is called with the process and the output string +as arguments until one of the functions returns non-nil. The +function is responsible for asking the user the appropriate +question using e.g. `read-char-choice' and then forwarding the +answer to the process using `process-send-string'. + +While functions such as `magit-process-yes-or-no-prompt' may not +be sufficient to handle some prompt, it may still be of benefit +to look at the implementations to gain some insights on how to +implement such functions." + :package-version '(magit . "2.91.0") + :group 'magit-process + :type 'hook) + +(defcustom magit-process-ensure-unix-line-ending t + "Whether Magit should ensure a unix coding system when talking to Git." + :package-version '(magit . "2.6.0") + :group 'magit-process + :type 'boolean) + +(defcustom magit-process-display-mode-line-error t + "Whether Magit should retain and highlight process errors in the mode line." + :package-version '(magit . "2.12.0") + :group 'magit-process + :type 'boolean) + +(defface magit-process-ok + '((t :inherit magit-section-heading :foreground "green")) + "Face for zero exit-status." + :group 'magit-faces) + +(defface magit-process-ng + '((t :inherit magit-section-heading :foreground "red")) + "Face for non-zero exit-status." + :group 'magit-faces) + +(defface magit-mode-line-process + '((t :inherit mode-line-emphasis)) + "Face for `mode-line-process' status when Git is running for side-effects." + :group 'magit-faces) + +(defface magit-mode-line-process-error + '((t :inherit error)) + "Face for `mode-line-process' error status. + +Used when `magit-process-display-mode-line-error' is non-nil." + :group 'magit-faces) + +;;; Process Mode + +(defvar magit-process-mode-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map magit-mode-map) + map) + "Keymap for `magit-process-mode'.") + +(define-derived-mode magit-process-mode magit-mode "Magit Process" + "Mode for looking at Git process output." + :group 'magit-process + (hack-dir-local-variables-non-file-buffer) + (setq imenu-prev-index-position-function + 'magit-imenu--process-prev-index-position-function) + (setq imenu-extract-index-name-function + 'magit-imenu--process-extract-index-name-function)) + +(defun magit-process-buffer (&optional nodisplay) + "Display the current repository's process buffer. + +If that buffer doesn't exist yet, then create it. +Non-interactively return the buffer and unless +optional NODISPLAY is non-nil also display it." + (interactive) + (let ((topdir (magit-toplevel))) + (unless topdir + (magit--with-safe-default-directory nil + (setq topdir default-directory) + (let (prev) + (while (not (equal topdir prev)) + (setq prev topdir) + (setq topdir (file-name-directory (directory-file-name topdir))))))) + (let ((buffer (or (--first (with-current-buffer it + (and (eq major-mode 'magit-process-mode) + (equal default-directory topdir))) + (buffer-list)) + (let ((default-directory topdir)) + (magit-generate-new-buffer 'magit-process-mode))))) + (with-current-buffer buffer + (if magit-root-section + (when magit-process-log-max + (magit-process-truncate-log)) + (magit-process-mode) + (let ((inhibit-read-only t) + (magit-insert-section--parent nil) + (magit-insert-section--oldroot nil)) + (make-local-variable 'text-property-default-nonsticky) + (magit-insert-section (processbuf) + (insert "\n"))))) + (unless nodisplay + (magit-display-buffer buffer)) + buffer))) + +(defun magit-process-kill () + "Kill the process at point." + (interactive) + (when-let ((process (magit-section-value-if 'process))) + (unless (eq (process-status process) 'run) + (user-error "Process isn't running")) + (magit-confirm 'kill-process) + (kill-process process))) + +;;; Synchronous Processes + +(defvar magit-process-raise-error nil) + +(defun magit-git (&rest args) + "Call Git synchronously in a separate process, for side-effects. + +Option `magit-git-executable' specifies the Git executable. +The arguments ARGS specify arguments to Git, they are flattened +before use. + +Process output goes into a new section in the buffer returned by +`magit-process-buffer'. If Git exits with a non-zero status, +then raise an error." + (let ((magit-process-raise-error t)) + (magit-call-git args))) + +(defun magit-run-git (&rest args) + "Call Git synchronously in a separate process, and refresh. + +Option `magit-git-executable' specifies the Git executable and +option `magit-git-global-arguments' specifies constant arguments. +The arguments ARGS specify arguments to Git, they are flattened +before use. + +After Git returns, the current buffer (if it is a Magit buffer) +as well as the current repository's status buffer are refreshed. + +Process output goes into a new section in the buffer returned by +`magit-process-buffer'." + (let ((magit--refresh-cache (list (cons 0 0)))) + (magit-call-git args) + (when (member (car args) '("init" "clone")) + ;; Creating a new repository invalidates the cache. + (setq magit--refresh-cache nil)) + (magit-refresh))) + +(defvar magit-pre-call-git-hook nil) + +(defun magit-call-git (&rest args) + "Call Git synchronously in a separate process. + +Option `magit-git-executable' specifies the Git executable and +option `magit-git-global-arguments' specifies constant arguments. +The arguments ARGS specify arguments to Git, they are flattened +before use. + +Process output goes into a new section in the buffer returned by +`magit-process-buffer'." + (run-hooks 'magit-pre-call-git-hook) + (let ((default-process-coding-system (magit--process-coding-system))) + (apply #'magit-call-process magit-git-executable + (magit-process-git-arguments args)))) + +(defun magit-call-process (program &rest args) + "Call PROGRAM synchronously in a separate process. +Process output goes into a new section in the buffer returned by +`magit-process-buffer'." + (pcase-let ((`(,process-buf . ,section) + (magit-process-setup program args))) + (magit-process-finish + (let ((inhibit-read-only t)) + (apply #'magit-process-file program nil process-buf nil args)) + process-buf (current-buffer) default-directory section))) + +(defun magit-process-file (process &optional infile buffer display &rest args) + "Process files synchronously in a separate process. +Identical to `process-file' but temporarily enable Cygwin's +\"noglob\" option during the call and ensure unix eol +conversion." + (let ((process-environment (magit-process-environment)) + (default-process-coding-system (magit--process-coding-system))) + (apply #'process-file process infile buffer display args))) + +(defun magit-process-environment () + ;; The various w32 hacks are only applicable when running on the + ;; local machine. As of Emacs 25.1, a local binding of + ;; process-environment different from the top-level value affects + ;; the environment used in + ;; tramp-sh-handle-{start-file-process,process-file}. + (let ((local (not (file-remote-p default-directory)))) + (append magit-git-environment + (and local + (cdr (assoc magit-git-executable magit-git-w32-path-hack))) + (and local magit-need-cygwin-noglob + (mapcar (lambda (var) + (concat var "=" (--if-let (getenv var) + (concat it " noglob") + "noglob"))) + '("CYGWIN" "MSYS"))) + process-environment))) + +(defvar magit-this-process nil) + +(defun magit-run-git-with-input (&rest args) + "Call Git in a separate process. +ARGS is flattened and then used as arguments to Git. + +The current buffer's content is used as the process' standard +input. + +Option `magit-git-executable' specifies the Git executable and +option `magit-git-global-arguments' specifies constant arguments. +The remaining arguments ARGS specify arguments to Git, they are +flattened before use." + (when (eq system-type 'windows-nt) + ;; On w32, git expects UTF-8 encoded input, ignore any user + ;; configuration telling us otherwise (see #3250). + (encode-coding-region (point-min) (point-max) 'utf-8-unix)) + (if (file-remote-p default-directory) + ;; We lack `process-file-region', so fall back to asynch + + ;; waiting in remote case. + (progn + (magit-start-git (current-buffer) args) + (while (and magit-this-process + (eq (process-status magit-this-process) 'run)) + (sleep-for 0.005))) + (run-hooks 'magit-pre-call-git-hook) + (pcase-let* ((process-environment (magit-process-environment)) + (default-process-coding-system (magit--process-coding-system)) + (flat-args (magit-process-git-arguments args)) + (`(,process-buf . ,section) + (magit-process-setup magit-git-executable flat-args)) + (inhibit-read-only t)) + (magit-process-finish + (apply #'call-process-region (point-min) (point-max) + magit-git-executable nil process-buf nil flat-args) + process-buf nil default-directory section)))) + +;;; Asynchronous Processes + +(defun magit-run-git-async (&rest args) + "Start Git, prepare for refresh, and return the process object. +ARGS is flattened and then used as arguments to Git. + +Display the command line arguments in the echo area. + +After Git returns some buffers are refreshed: the buffer that was +current when this function was called (if it is a Magit buffer +and still alive), as well as the respective Magit status buffer. + +See `magit-start-process' for more information." + (message "Running %s %s" magit-git-executable + (let ((m (mapconcat #'identity (-flatten args) " "))) + (remove-list-of-text-properties 0 (length m) '(face) m) + m)) + (magit-start-git nil args)) + +(defun magit-run-git-with-editor (&rest args) + "Export GIT_EDITOR and start Git. +Also prepare for refresh and return the process object. +ARGS is flattened and then used as arguments to Git. + +Display the command line arguments in the echo area. + +After Git returns some buffers are refreshed: the buffer that was +current when this function was called (if it is a Magit buffer +and still alive), as well as the respective Magit status buffer. + +See `magit-start-process' and `with-editor' for more information." + (magit--record-separated-gitdir) + (magit-with-editor (magit-run-git-async args))) + +(defun magit-run-git-sequencer (&rest args) + "Export GIT_EDITOR and start Git. +Also prepare for refresh and return the process object. +ARGS is flattened and then used as arguments to Git. + +Display the command line arguments in the echo area. + +After Git returns some buffers are refreshed: the buffer that was +current when this function was called (if it is a Magit buffer +and still alive), as well as the respective Magit status buffer. +If the sequence stops at a commit, make the section representing +that commit the current section by moving `point' there. + +See `magit-start-process' and `with-editor' for more information." + (apply #'magit-run-git-with-editor args) + (set-process-sentinel magit-this-process #'magit-sequencer-process-sentinel) + magit-this-process) + +(defvar magit-pre-start-git-hook nil) + +(defun magit-start-git (input &rest args) + "Start Git, prepare for refresh, and return the process object. + +If INPUT is non-nil, it has to be a buffer or the name of an +existing buffer. The buffer content becomes the processes +standard input. + +Option `magit-git-executable' specifies the Git executable and +option `magit-git-global-arguments' specifies constant arguments. +The remaining arguments ARGS specify arguments to Git, they are +flattened before use. + +After Git returns some buffers are refreshed: the buffer that was +current when this function was called (if it is a Magit buffer +and still alive), as well as the respective Magit status buffer. + +See `magit-start-process' for more information." + (run-hooks 'magit-pre-start-git-hook) + (let ((default-process-coding-system (magit--process-coding-system))) + (apply #'magit-start-process magit-git-executable input + (magit-process-git-arguments args)))) + +(defun magit-start-process (program &optional input &rest args) + "Start PROGRAM, prepare for refresh, and return the process object. + +If optional argument INPUT is non-nil, it has to be a buffer or +the name of an existing buffer. The buffer content becomes the +processes standard input. + +The process is started using `start-file-process' and then setup +to use the sentinel `magit-process-sentinel' and the filter +`magit-process-filter'. Information required by these functions +is stored in the process object. When this function returns the +process has not started to run yet so it is possible to override +the sentinel and filter. + +After the process returns, `magit-process-sentinel' refreshes the +buffer that was current when `magit-start-process' was called (if +it is a Magit buffer and still alive), as well as the respective +Magit status buffer." + (pcase-let* + ((`(,process-buf . ,section) + (magit-process-setup program args)) + (process + (let ((process-connection-type + ;; Don't use a pty, because it would set icrnl + ;; which would modify the input (issue #20). + (and (not input) magit-process-connection-type)) + (process-environment (magit-process-environment)) + (default-process-coding-system (magit--process-coding-system))) + (apply #'start-file-process + (file-name-nondirectory program) + process-buf program args)))) + (with-editor-set-process-filter process #'magit-process-filter) + (set-process-sentinel process #'magit-process-sentinel) + (set-process-buffer process process-buf) + (when (eq system-type 'windows-nt) + ;; On w32, git expects UTF-8 encoded input, ignore any user + ;; configuration telling us otherwise. + (set-process-coding-system process 'utf-8-unix)) + (process-put process 'section section) + (process-put process 'command-buf (current-buffer)) + (process-put process 'default-dir default-directory) + (when inhibit-magit-refresh + (process-put process 'inhibit-refresh t)) + (oset section process process) + (with-current-buffer process-buf + (set-marker (process-mark process) (point))) + (when input + (with-current-buffer input + (process-send-region process (point-min) (point-max)) + (process-send-eof process))) + (setq magit-this-process process) + (oset section value process) + (magit-process-display-buffer process) + process)) + +(defun magit-parse-git-async (&rest args) + (setq args (magit-process-git-arguments args)) + (let ((command-buf (current-buffer)) + (process-buf (generate-new-buffer " *temp*")) + (toplevel (magit-toplevel))) + (with-current-buffer process-buf + (setq default-directory toplevel) + (let ((process + (let ((process-connection-type nil) + (process-environment (magit-process-environment)) + (default-process-coding-system + (magit--process-coding-system))) + (apply #'start-file-process "git" process-buf + magit-git-executable args)))) + (process-put process 'command-buf command-buf) + (process-put process 'parsed (point)) + (setq magit-this-process process) + process)))) + +;;; Process Internals + +(defun magit-process-setup (program args) + (magit-process-set-mode-line program args) + (let ((pwd default-directory) + (buf (magit-process-buffer t))) + (cons buf (with-current-buffer buf + (prog1 (magit-process-insert-section pwd program args nil nil) + (backward-char 1)))))) + +(defun magit-process-insert-section (pwd program args &optional errcode errlog) + (let ((inhibit-read-only t) + (magit-insert-section--parent magit-root-section) + (magit-insert-section--oldroot nil)) + (goto-char (1- (point-max))) + (magit-insert-section (process) + (insert (if errcode + (format "%3s " (propertize (number-to-string errcode) + 'font-lock-face 'magit-process-ng)) + "run ")) + (unless (equal (expand-file-name pwd) + (expand-file-name default-directory)) + (insert (file-relative-name pwd default-directory) ?\s)) + (cond + ((and args (equal program magit-git-executable)) + (setq args (-split-at (length magit-git-global-arguments) args)) + (insert (propertize (file-name-nondirectory program) + 'font-lock-face 'magit-section-heading) " ") + (insert (propertize (char-to-string magit-ellipsis) + 'font-lock-face 'magit-section-heading + 'help-echo (mapconcat #'identity (car args) " "))) + (insert " ") + (insert (propertize (mapconcat #'shell-quote-argument (cadr args) " ") + 'font-lock-face 'magit-section-heading))) + ((and args (equal program shell-file-name)) + (insert (propertize (cadr args) + 'font-lock-face 'magit-section-heading))) + (t + (insert (propertize (file-name-nondirectory program) + 'font-lock-face 'magit-section-heading) " ") + (insert (propertize (mapconcat #'shell-quote-argument args " ") + 'font-lock-face 'magit-section-heading)))) + (magit-insert-heading) + (when errlog + (if (bufferp errlog) + (insert (with-current-buffer errlog + (buffer-substring-no-properties (point-min) (point-max)))) + (insert-file-contents errlog) + (goto-char (1- (point-max))))) + (insert "\n")))) + +(defun magit-process-truncate-log () + (let* ((head nil) + (tail (oref magit-root-section children)) + (count (length tail))) + (when (> (1+ count) magit-process-log-max) + (while (and (cdr tail) + (> count (/ magit-process-log-max 2))) + (let* ((inhibit-read-only t) + (section (car tail)) + (process (oref section process))) + (cond ((not process)) + ((memq (process-status process) '(exit signal)) + (delete-region (oref section start) + (1+ (oref section end))) + (cl-decf count)) + (t + (push section head)))) + (pop tail)) + (oset magit-root-section children + (nconc (reverse head) tail))))) + +(defun magit-process-sentinel (process event) + "Default sentinel used by `magit-start-process'." + (when (memq (process-status process) '(exit signal)) + (setq event (substring event 0 -1)) + (when (string-match "^finished" event) + (message (concat (capitalize (process-name process)) " finished"))) + (magit-process-finish process) + (when (eq process magit-this-process) + (setq magit-this-process nil)) + (unless (process-get process 'inhibit-refresh) + (let ((command-buf (process-get process 'command-buf))) + (if (buffer-live-p command-buf) + (with-current-buffer command-buf + (magit-refresh)) + (with-temp-buffer + (setq default-directory (process-get process 'default-dir)) + (magit-refresh))))))) + +(defun magit-sequencer-process-sentinel (process event) + "Special sentinel used by `magit-run-git-sequencer'." + (when (memq (process-status process) '(exit signal)) + (magit-process-sentinel process event) + (when-let ((process-buf (process-buffer process))) + (when (buffer-live-p process-buf) + (when-let ((status-buf (with-current-buffer process-buf + (magit-get-mode-buffer 'magit-status-mode)))) + (with-current-buffer status-buf + (--when-let + (magit-get-section + `((commit . ,(magit-rev-parse "HEAD")) + (,(pcase (car (cadr (-split-at + (1+ (length magit-git-global-arguments)) + (process-command process)))) + ((or "rebase" "am") 'rebase-sequence) + ((or "cherry-pick" "revert") 'sequence))) + (status))) + (goto-char (oref it start)) + (magit-section-update-highlight)))))))) + +(defun magit-process-filter (proc string) + "Default filter used by `magit-start-process'." + (with-current-buffer (process-buffer proc) + (let ((inhibit-read-only t)) + (goto-char (process-mark proc)) + ;; Find last ^M in string. If one was found, ignore + ;; everything before it and delete the current line. + (when-let ((ret-pos (cl-position ?\r string :from-end t))) + (cl-callf substring string (1+ ret-pos)) + (delete-region (line-beginning-position) (point))) + (insert (propertize string 'magit-section + (process-get proc 'section))) + (set-marker (process-mark proc) (point)) + ;; Make sure prompts are matched after removing ^M. + (magit-process-yes-or-no-prompt proc string) + (magit-process-username-prompt proc string) + (magit-process-password-prompt proc string) + (run-hook-with-args-until-success 'magit-process-prompt-functions + proc string)))) + +(defmacro magit-process-kill-on-abort (proc &rest body) + (declare (indent 1) (debug (form body))) + (let ((map (cl-gensym))) + `(let ((,map (make-sparse-keymap))) + (set-keymap-parent ,map minibuffer-local-map) + (define-key ,map "\C-g" + (lambda () + (interactive) + (ignore-errors (kill-process ,proc)) + (abort-recursive-edit))) + (let ((minibuffer-local-map ,map)) + ,@body)))) + +(defun magit-process-yes-or-no-prompt (process string) + "Forward Yes-or-No prompts to the user." + (when-let ((beg (string-match magit-process-yes-or-no-prompt-regexp string))) + (let ((max-mini-window-height 30)) + (process-send-string + process + (downcase + (concat + (match-string + (if (save-match-data + (magit-process-kill-on-abort process + (yes-or-no-p (substring string 0 beg)))) 1 2) + string) + "\n")))))) + +(defun magit-process-password-auth-source (key) + "Use `auth-source-search' to get a password. +If found, return the password. Otherwise, return nil. + +To use this function add it to the appropriate hook + (add-hook 'magit-process-find-password-functions + 'magit-process-password-auth-source) + +KEY typically derives from a prompt such as: + Password for 'https://tarsius@bitbucket.org' +in which case it would be the string + tarsius@bitbucket.org +which matches the ~/.authinfo.gpg entry + machine bitbucket.org login tarsius password 12345 +or iff that is undefined, for backward compatibility + machine tarsius@bitbucket.org password 12345" + (require 'auth-source) + (and (string-match "\\`\\(.+\\)@\\([^@]+\\)\\'" key) + (let* ((user (match-string 1 key)) + (host (match-string 2 key)) + (secret + (plist-get + (car (or (auth-source-search :max 1 :host host :user user) + (auth-source-search :max 1 :host key))) + :secret))) + (if (functionp secret) + (funcall secret) + secret)))) + +(defun magit-process-password-prompt (process string) + "Find a password based on prompt STRING and send it to git. +Use `magit-process-password-prompt-regexps' to find a known +prompt. If and only if one is found, then call functions in +`magit-process-find-password-functions' until one of them returns +the password. If all function return nil, then read the password +from the user." + (when-let ((prompt (magit-process-match-prompt + magit-process-password-prompt-regexps string))) + (process-send-string + process (magit-process-kill-on-abort process + (concat (or (when-let ((key (match-string 99 string))) + (run-hook-with-args-until-success + 'magit-process-find-password-functions key)) + (read-passwd prompt)) + "\n"))))) + +(defun magit-process-username-prompt (process string) + "Forward username prompts to the user." + (--when-let (magit-process-match-prompt + magit-process-username-prompt-regexps string) + (process-send-string + process (magit-process-kill-on-abort process + (concat (read-string it nil nil (user-login-name)) "\n"))))) + +(defun magit-process-match-prompt (prompts string) + "Match STRING against PROMPTS and set match data. +Return the matched string suffixed with \": \", if needed." + (when (--any-p (string-match it string) prompts) + (let ((prompt (match-string 0 string))) + (cond ((string-suffix-p ": " prompt) prompt) + ((string-suffix-p ":" prompt) (concat prompt " ")) + (t (concat prompt ": ")))))) + +(defun magit--process-coding-system () + (let ((fro (or magit-git-output-coding-system + (car default-process-coding-system))) + (to (cdr default-process-coding-system))) + (if magit-process-ensure-unix-line-ending + (cons (coding-system-change-eol-conversion fro 'unix) + (coding-system-change-eol-conversion to 'unix)) + (cons fro to)))) + +(defvar magit-credential-hook nil + "Hook run before Git needs credentials.") + +(defvar magit-credential-cache-daemon-process nil) + +(defun magit-maybe-start-credential-cache-daemon () + "Maybe start a `git-credential-cache--daemon' process. + +If such a process is already running or if the value of option +`magit-credential-cache-daemon-socket' is nil, then do nothing. +Otherwise start the process passing the value of that options +as argument." + (unless (or (not magit-credential-cache-daemon-socket) + (process-live-p magit-credential-cache-daemon-process) + (memq magit-credential-cache-daemon-process + (list-system-processes))) + (setq magit-credential-cache-daemon-process + (or (--first (let* ((attr (process-attributes it)) + (comm (cdr (assq 'comm attr))) + (user (cdr (assq 'user attr)))) + (and (string= comm "git-credential-cache--daemon") + (string= user user-login-name))) + (list-system-processes)) + (condition-case nil + (start-process "git-credential-cache--daemon" + " *git-credential-cache--daemon*" + magit-git-executable + "credential-cache--daemon" + magit-credential-cache-daemon-socket) + ;; Some Git implementations (e.g. Windows) won't have + ;; this program; if we fail the first time, stop trying. + ((debug error) + (remove-hook 'magit-credential-hook + #'magit-maybe-start-credential-cache-daemon))))))) + +(add-hook 'magit-credential-hook #'magit-maybe-start-credential-cache-daemon) + +(defun tramp-sh-handle-start-file-process--magit-tramp-process-environment + (fn name buffer program &rest args) + (if magit-tramp-process-environment + (apply fn name buffer + (car magit-tramp-process-environment) + (append (cdr magit-tramp-process-environment) + (cons program args))) + (apply fn name buffer program args))) + +(advice-add 'tramp-sh-handle-start-file-process :around + 'tramp-sh-handle-start-file-process--magit-tramp-process-environment) + +(defun tramp-sh-handle-process-file--magit-tramp-process-environment + (fn program &optional infile destination display &rest args) + (if magit-tramp-process-environment + (apply fn "env" infile destination display + (append magit-tramp-process-environment + (cons program args))) + (apply fn program infile destination display args))) + +(advice-add 'tramp-sh-handle-process-file :around + 'tramp-sh-handle-process-file--magit-tramp-process-environment) + +(defvar magit-mode-line-process-map + (let ((map (make-sparse-keymap))) + (define-key map (kbd " ") + 'magit-process-buffer) + map) + "Keymap for `mode-line-process'.") + +(defun magit-process-set-mode-line (program args) + "Display the git command (sans arguments) in the mode line." + (when (equal program magit-git-executable) + (setq args (nthcdr (length magit-git-global-arguments) args))) + (let ((str (concat " " (propertize + (concat (file-name-nondirectory program) + (and args (concat " " (car args)))) + 'mouse-face 'highlight + 'keymap magit-mode-line-process-map + 'help-echo "mouse-1: Show process buffer" + 'font-lock-face 'magit-mode-line-process)))) + (magit-repository-local-set 'mode-line-process str) + (dolist (buf (magit-mode-get-buffers)) + (with-current-buffer buf + (setq mode-line-process str))) + (force-mode-line-update t))) + +(defun magit-process-set-mode-line-error-status (&optional error str) + "Apply an error face to the string set by `magit-process-set-mode-line'. + +If ERROR is supplied, include it in the `mode-line-process' tooltip. + +If STR is supplied, it replaces the `mode-line-process' text." + (setq str (or str (magit-repository-local-get 'mode-line-process))) + (when str + (setq error (format "%smouse-1: Show process buffer" + (if (stringp error) + (concat error "\n\n") + ""))) + (setq str (concat " " (propertize + (substring-no-properties str 1) + 'mouse-face 'highlight + 'keymap magit-mode-line-process-map + 'help-echo error + 'font-lock-face 'magit-mode-line-process-error))) + (magit-repository-local-set 'mode-line-process str) + (dolist (buf (magit-mode-get-buffers)) + (with-current-buffer buf + (setq mode-line-process str))) + (force-mode-line-update t) + ;; We remove any error status from the mode line when a magit + ;; buffer is refreshed (see `magit-refresh-buffer'), but we must + ;; ensure that we ignore any refreshes during the remainder of the + ;; current command -- otherwise a newly-set error status would be + ;; removed before it was seen. We set a flag which prevents the + ;; status from being removed prior to the next command, so that + ;; the error status is guaranteed to remain visible until then. + (let ((repokey (magit-repository-local-repository))) + ;; The following closure captures the repokey value, and is + ;; added to `pre-command-hook'. + (cl-labels ((enable-magit-process-unset-mode-line + () ;; Remove ourself from the hook variable, so + ;; that we only run once. + (remove-hook 'pre-command-hook + #'enable-magit-process-unset-mode-line) + ;; Clear the inhibit flag for the repository in + ;; which we set it. + (magit-repository-local-set + 'inhibit-magit-process-unset-mode-line nil repokey))) + ;; Set the inhibit flag until the next command is invoked. + (magit-repository-local-set + 'inhibit-magit-process-unset-mode-line t repokey) + (add-hook 'pre-command-hook + #'enable-magit-process-unset-mode-line))))) + +(defun magit-process-unset-mode-line-error-status () + "Remove any current error status from the mode line." + (let ((status (or mode-line-process + (magit-repository-local-get 'mode-line-process)))) + (when (and status + (eq (get-text-property 1 'font-lock-face status) + 'magit-mode-line-process-error)) + (magit-process-unset-mode-line)))) + +(defun magit-process-unset-mode-line (&optional directory) + "Remove the git command from the mode line." + (let ((default-directory (or directory default-directory))) + (unless (magit-repository-local-get 'inhibit-magit-process-unset-mode-line) + (magit-repository-local-set 'mode-line-process nil) + (dolist (buf (magit-mode-get-buffers)) + (with-current-buffer buf (setq mode-line-process nil))) + (force-mode-line-update t)))) + +(defvar magit-process-error-message-regexps + (list "^\\*ERROR\\*: Canceled by user$" + "^\\(?:error\\|fatal\\|git\\): \\(.*\\)$" + "^\\(Cannot rebase:.*\\)$")) + +(define-error 'magit-git-error "Git error") + +(defun magit-process-error-summary (process-buf section) + "A one-line error summary from the given SECTION." + (or (and (buffer-live-p process-buf) + (with-current-buffer process-buf + (and (oref section content) + (save-excursion + (goto-char (oref section end)) + (run-hook-wrapped + 'magit-process-error-message-regexps + (lambda (re) + (save-excursion + (and (re-search-backward + re (oref section start) t) + (or (match-string-no-properties 1) + (and (not magit-process-raise-error) + 'suppressed)))))))))) + "Git failed")) + +(defun magit-process-error-tooltip (process-buf section) + "Returns the text from SECTION of the PROCESS-BUF buffer. + +Limited by `magit-process-error-tooltip-max-lines'." + (and (integerp magit-process-error-tooltip-max-lines) + (> magit-process-error-tooltip-max-lines 0) + (buffer-live-p process-buf) + (with-current-buffer process-buf + (save-excursion + (goto-char (or (oref section content) + (oref section start))) + (buffer-substring-no-properties + (point) + (save-excursion + (forward-line magit-process-error-tooltip-max-lines) + (goto-char + (if (> (point) (oref section end)) + (oref section end) + (point))) + ;; Remove any trailing whitespace. + (when (re-search-backward "[^[:space:]\n]" + (oref section start) t) + (forward-char 1)) + (point))))))) + +(defvar-local magit-this-error nil) + +(defvar magit-process-finish-apply-ansi-colors nil) + +(defun magit-process-finish (arg &optional process-buf command-buf + default-dir section) + (unless (integerp arg) + (setq process-buf (process-buffer arg)) + (setq command-buf (process-get arg 'command-buf)) + (setq default-dir (process-get arg 'default-dir)) + (setq section (process-get arg 'section)) + (setq arg (process-exit-status arg))) + (when (fboundp 'dired-uncache) + (dired-uncache default-dir)) + (when (buffer-live-p process-buf) + (with-current-buffer process-buf + (let ((inhibit-read-only t) + (marker (oref section start))) + (goto-char marker) + (save-excursion + (delete-char 3) + (set-marker-insertion-type marker nil) + (insert (propertize (format "%3s" arg) + 'magit-section section + 'font-lock-face (if (= arg 0) + 'magit-process-ok + 'magit-process-ng))) + (set-marker-insertion-type marker t)) + (when magit-process-finish-apply-ansi-colors + (ansi-color-apply-on-region (oref section content) + (oref section end))) + (if (= (oref section end) + (+ (line-end-position) 2)) + (save-excursion + (goto-char (1+ (line-end-position))) + (delete-char -1) + (oset section content nil)) + (let ((buf (magit-process-buffer t))) + (when (and (= arg 0) + (not (--any-p (eq (window-buffer it) buf) + (window-list)))) + (magit-section-hide section))))))) + (if (= arg 0) + ;; Unset the `mode-line-process' value upon success. + (magit-process-unset-mode-line default-dir) + ;; Otherwise process the error. + (let ((msg (magit-process-error-summary process-buf section))) + ;; Change `mode-line-process' to an error face upon failure. + (if magit-process-display-mode-line-error + (magit-process-set-mode-line-error-status + (or (magit-process-error-tooltip process-buf section) + msg)) + (magit-process-unset-mode-line default-dir)) + ;; Either signal the error, or else display the error summary in + ;; the status buffer and with a message in the echo area. + (cond + (magit-process-raise-error + (signal 'magit-git-error (list (format "%s (in %s)" msg default-dir)))) + ((not (eq msg 'suppressed)) + (when (buffer-live-p process-buf) + (with-current-buffer process-buf + (when-let ((status-buf (magit-get-mode-buffer 'magit-status-mode))) + (with-current-buffer status-buf + (setq magit-this-error msg))))) + (message "%s ... [%s buffer %s for details]" msg + (if-let ((key (and (buffer-live-p command-buf) + (with-current-buffer command-buf + (car (where-is-internal + 'magit-process-buffer)))))) + (format "Hit %s to see" (key-description key)) + "See") + (buffer-name process-buf)))))) + arg) + +(defun magit-process-display-buffer (process) + (when (process-live-p process) + (let ((buf (process-buffer process))) + (cond ((not (buffer-live-p buf))) + ((= magit-process-popup-time 0) + (if (minibufferp) + (switch-to-buffer-other-window buf) + (pop-to-buffer buf))) + ((> magit-process-popup-time 0) + (run-with-timer magit-process-popup-time nil + (lambda (p) + (when (eq (process-status p) 'run) + (let ((buf (process-buffer p))) + (when (buffer-live-p buf) + (if (minibufferp) + (switch-to-buffer-other-window buf) + (pop-to-buffer buf)))))) + process)))))) + +(defun magit--log-action (summary line list) + (let (heading lines) + (if (cdr list) + (progn (setq heading (funcall summary list)) + (setq lines (mapcar line list))) + (setq heading (funcall line (car list)))) + (with-current-buffer (magit-process-buffer t) + (goto-char (1- (point-max))) + (let ((inhibit-read-only t)) + (magit-insert-section (message) + (magit-insert-heading (concat " * " heading)) + (when lines + (dolist (line lines) + (insert line "\n")) + (insert "\n")))) + (let ((inhibit-message t)) + (when heading + (setq lines (cons heading lines))) + (message (mapconcat #'identity lines "\n")))))) + +;;; _ +(provide 'magit-process) +;;; magit-process.el ends here diff --git a/elpa/magit-20191122.2040/magit-process.elc b/elpa/magit-20191122.2040/magit-process.elc new file mode 100644 index 0000000000000000000000000000000000000000..4899a05b48bbd6daf8b4411b82b9e3fd564fed01 GIT binary patch literal 45899 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 literal 0 HcmV?d00001 diff --git a/elpa/magit-20191122.2040/magit-pull.el b/elpa/magit-20191122.2040/magit-pull.el new file mode 100644 index 00000000..6aff89f7 --- /dev/null +++ b/elpa/magit-20191122.2040/magit-pull.el @@ -0,0 +1,163 @@ +;;; magit-pull.el --- update local objects and refs -*- lexical-binding: t -*- + +;; Copyright (C) 2008-2019 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; This library implements pull commands. + +;;; Code: + +(require 'magit) + +;;; Options + +(defcustom magit-pull-or-fetch nil + "Whether `magit-pull' also offers some fetch suffixes." + :package-version '(magit . "2.91.0") + :group 'magit-commands + :type 'boolean) + +;;; Commands + +;;;###autoload (autoload 'magit-pull "magit-pull" nil t) +(define-transient-command magit-pull () + "Pull from another repository." + :man-page "git-pull" + [:description + (lambda () (if magit-pull-or-fetch "Pull arguments" "Arguments")) + ("-r" "Rebase local commits" ("-r" "--rebase"))] + [:description + (lambda () + (if-let ((branch (magit-get-current-branch))) + (concat + (propertize "Pull into " 'face 'transient-heading) + (propertize branch 'face 'magit-branch-local) + (propertize " from" 'face 'transient-heading)) + (propertize "Pull from" 'face 'transient-heading))) + ("p" magit-pull-from-pushremote) + ("u" magit-pull-from-upstream) + ("e" "elsewhere" magit-pull-branch)] + ["Fetch from" + :if-non-nil magit-pull-or-fetch + ("f" "remotes" magit-fetch-all-no-prune) + ("F" "remotes and prune" magit-fetch-all-prune)] + ["Fetch" + :if-non-nil magit-pull-or-fetch + ("o" "another branch" magit-fetch-branch) + ("s" "explicit refspec" magit-fetch-refspec) + ("m" "submodules" magit-fetch-modules)] + ["Configure" + ("r" magit-branch..rebase :if magit-get-current-branch) + ("C" "variables..." magit-branch-configure)] + (interactive) + (transient-setup 'magit-pull nil nil :scope (magit-get-current-branch))) + +(defun magit-pull-arguments () + (transient-args 'magit-pull)) + +;;;###autoload (autoload 'magit-pull-from-pushremote "magit-pull" nil t) +(define-suffix-command magit-pull-from-pushremote (args) + "Pull from the push-remote of the current branch. + +When the push-remote is not configured, then read the push-remote +from the user, set it, and then pull from it. With a prefix +argument the push-remote can be changed before pulling from it." + :if 'magit-get-current-branch + :description 'magit-pull--pushbranch-description + (interactive (list (magit-pull-arguments))) + (pcase-let ((`(,branch ,remote) + (magit--select-push-remote "pull from there"))) + (run-hooks 'magit-credential-hook) + (magit-run-git-async "pull" args remote branch))) + +(defun magit-pull--pushbranch-description () + ;; Also used by `magit-rebase-onto-pushremote'. + (let* ((branch (magit-get-current-branch)) + (target (magit-get-push-branch branch t)) + (remote (magit-get-push-remote branch)) + (v (magit--push-remote-variable branch t))) + (cond + (target) + ((member remote (magit-list-remotes)) + (format "%s, replacing non-existent" v)) + (remote + (format "%s, replacing invalid" v)) + (t + (format "%s, setting that" v))))) + +;;;###autoload (autoload 'magit-pull-from-upstream "magit-pull" nil t) +(define-suffix-command magit-pull-from-upstream (args) + "Pull from the upstream of the current branch. + +With a prefix argument or when the upstream is either not +configured or unusable, then let the user first configure +the upstream." + :if 'magit-get-current-branch + :description 'magit-pull--upstream-description + (interactive (list (magit-pull-arguments))) + (let* ((branch (or (magit-get-current-branch) + (user-error "No branch is checked out"))) + (remote (magit-get "branch" branch "remote")) + (merge (magit-get "branch" branch "merge"))) + (when (or current-prefix-arg + (not (or (magit-get-upstream-branch branch) + (magit--unnamed-upstream-p remote merge)))) + (magit-set-upstream-branch + branch (magit-read-upstream-branch + branch (format "Set upstream of %s and pull from there" branch))) + (setq remote (magit-get "branch" branch "remote")) + (setq merge (magit-get "branch" branch "merge"))) + (run-hooks 'magit-credential-hook) + (magit-run-git-with-editor "pull" args remote merge))) + +(defun magit-pull--upstream-description () + (when-let ((branch (magit-get-current-branch))) + (or (magit-get-upstream-branch branch) + (let ((remote (magit-get "branch" branch "remote")) + (merge (magit-get "branch" branch "merge")) + (u (magit--propertize-face "@{upstream}" 'bold))) + (cond + ((magit--unnamed-upstream-p remote merge) + (format "%s of %s" + (magit--propertize-face merge 'magit-branch-remote) + (magit--propertize-face remote 'bold))) + ((magit--valid-upstream-p remote merge) + (concat u ", replacing non-existent")) + ((or remote merge) + (concat u ", replacing invalid")) + (t + (concat u ", setting that"))))))) + +;;;###autoload +(defun magit-pull-branch (source args) + "Pull from a branch read in the minibuffer." + (interactive (list (magit-read-remote-branch "Pull" nil nil nil t) + (magit-pull-arguments))) + (run-hooks 'magit-credential-hook) + (pcase-let ((`(,remote . ,branch) + (magit-get-tracked source))) + (magit-run-git-with-editor "pull" args remote branch))) + +;;; _ +(provide 'magit-pull) +;;; magit-pull.el ends here diff --git a/elpa/magit-20191122.2040/magit-pull.elc b/elpa/magit-20191122.2040/magit-pull.elc new file mode 100644 index 0000000000000000000000000000000000000000..a71d10fe0517983160ebbe88a76bc70b7c7cac61 GIT binary patch literal 6144 zcmdT|ZExE~5_aswm--Lf$4=>_kq@RIQZG)FYmvZ755*mNL2`$Fhz#6{TuDSou8vE( zaf|-0D*&B$cswNOF3e ziAd9>EOerB3Mc)cnfWOxS0vJu)VfTvK2QLG|e z7D>L;rA$Hyn2Q2v)Pbmg8&~$1ds?I5sbh7Vipe0JbGWqe^*H% zDHF>C#;kOyGC!74DhlaeiXstnc+AZD>ncrsRrm{8Mk`uWdBncvzwBo^em`*gva0hW zy`bQNydPJxT*0RQ+NgPgFo8GJVgU!iFPS8(Rac8e@=@x(N7J>4K8Pi@;o_`kH`ymI z>^}?o1Mh^U%R*Iax4%eb8QiRCT3)Rs&6P@}$gzjP$x$zs3y~&5)053ET3d!GVXqL@ zPTTZt9B_%KdOp?rRR7rT3yh@h_N}aj~jew z7RI8-&X>lq7&N}z9-Lspxs|tUUHfQD$~qc@#>eZbYhgx^{tZeZ%1LQ}ZLU&Ec`A<|4N zbrhuHN@1V9_d!cZq|z$OsW*+Kj*0}Rf;j7?BAds;7`2xyT1VRir`@?ImgY3tBkyJN z`{d+=dcF2C8o-5!?oB_)EAspTvDaSEdn@NcGiV^-0XSKflu$XddA_geKQmt3qQcl<&#E$vKHeG4YM9vP~TjEWy?Rw?9?+jqnzFW6U zzA?1VA&ijIt3qa~l&qxV|BjAohmLBEVkJekTZ4p#P5{YN%b$=wJW)qPYkSs)cZ>q> zI}5)!60{`?pKBiDP)lJA(m3aigD$qWX|2Pd-QA>tW*=aWwUFsm{u>tj?iR&Bk(kW; zJC<DL^t+CF!<(941KHC*ZY{_mMd|anVghC6n)N2{tqT9{x4l?$B zN4c)%nTo4a-sV6zd)GKSSNS4YRtVbNVZ?CRjTdX1S^v-W$G5Y-#Y6Vft#xwuY0tM$ zTXPfL?=x4pX#=22?gV^f1k}@8cz|C+x9&0mkSkL_H?Rmn-Ac3z3Q^OKUj#z}JzM1T z^6g*VoqTyS+t@}StQC&Wx>PQBaqlH_5d67!zvcxs$1{B3@QeHRAI-wa1bYKrG5fQb z4|bBuh)b(pp#U+^k!M(nso-3`fj`Jzf2Gui`WR6mV-);Eq-NM1j-|Lv34N7ER*MHB zHKgA0BkEK5bTUFvY;hSn@9c+{-dGlI!w3H*{!>%iuMcnLJl9PByEqUmNNwY)1=<7& z(roA+*veXo13||INBfAu-LSUPgx`f7KnITc$U{b<8G-qB`{A)%2R`&=B|4Xyrx2pS z@BzL|yL$K#-r@hY*)_@-9-%s%guF;IbY_O&AJUt(>8-{UsfB#$F-?CNZtW9YF+5I>9MvPtm*53C7)gu_@2j?F}H!6 z+7P(fFd94!|Nm-3W2E0*85#{c%0e5YsljMi5zT=u7>yQ$mxMT4ZWN7K-cT7tTR~M` zX}*|o6@(i>h?-L2F3}qKS#D-r-|{~}_WBHW#`T+CXrnq`%7laQ8^)L59%IJD{5Du) zvY#QwJTb(K`Dt@cf>IC!2L}e>Wr3SnCfx7-{?E7PuXpoqXU*gH<6zXK+vesJEWt8v{=?B^ zZvPJdaPVN8XWxxGGa*37U@C)yXvd~+#Ldv*=J;$JT*pmpXLB)WqHr*LjKLAT>co|) j0=C@LCB +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; This library implements push commands. + +;;; Code: + +(eval-when-compile + (require 'subr-x)) + +(require 'magit) + +;;; Commands + +;;;###autoload (autoload 'magit-push "magit-push" nil t) +(define-transient-command magit-push () + "Push to another repository." + :man-page "git-push" + ["Arguments" + ("-f" "Force with lease" (nil "--force-with-lease")) + ("-F" "Force" ("-f" "--force")) + ("-h" "Disable hooks" "--no-verify") + ("-n" "Dry run" ("-n" "--dry-run")) + (5 "-u" "Set upstream" "--set-upstream") + (7 "-t" "Follow tags" "--follow-tags")] + [:if magit-get-current-branch + :description (lambda () + (format (propertize "Push %s to" 'face 'transient-heading) + (propertize (magit-get-current-branch) + 'face 'magit-branch-local))) + ("p" magit-push-current-to-pushremote) + ("u" magit-push-current-to-upstream) + ("e" "elsewhere" magit-push-current)] + ["Push" + [("o" "another branch" magit-push-other) + ("r" "explicit refspecs" magit-push-refspecs) + ("m" "matching branches" magit-push-matching)] + [("T" "a tag" magit-push-tag) + ("t" "all tags" magit-push-tags)]] + ["Configure" + ("C" "Set variables..." magit-branch-configure)]) + +(defun magit-push-arguments () + (transient-args 'magit-push)) + +(defun magit-git-push (branch target args) + (run-hooks 'magit-credential-hook) + ;; If the remote branch already exists, then we do not have to + ;; qualify the target, which we prefer to avoid doing because + ;; using the default namespace is wrong in obscure cases. + (pcase-let ((namespace (if (magit-get-tracked target) "" "refs/heads/")) + (`(,remote . ,target) + (magit-split-branch-name target))) + (magit-run-git-async "push" "-v" args remote + (format "%s:%s%s" branch namespace target)))) + +;;;###autoload (autoload 'magit-push-current-to-pushremote "magit-push" nil t) +(define-suffix-command magit-push-current-to-pushremote (args) + "Push the current branch to its push-remote. + +When the push-remote is not configured, then read the push-remote +from the user, set it, and then push to it. With a prefix +argument the push-remote can be changed before pushed to it." + :if 'magit-get-current-branch + :description 'magit-push--pushbranch-description + (interactive (list (magit-push-arguments))) + (pcase-let ((`(,branch ,remote) + (magit--select-push-remote "push there"))) + (run-hooks 'magit-credential-hook) + (magit-run-git-async "push" "-v" args remote + (format "refs/heads/%s:refs/heads/%s" + branch branch)))) ; see #3847 and #3872 + +(defun magit-push--pushbranch-description () + (let* ((branch (magit-get-current-branch)) + (target (magit-get-push-branch branch t)) + (remote (magit-get-push-remote branch)) + (v (magit--push-remote-variable branch t))) + (cond + (target) + ((member remote (magit-list-remotes)) + (format "%s, creating it" + (magit--propertize-face (concat remote "/" branch) + 'magit-branch-remote))) + (remote + (format "%s, replacing invalid" v)) + (t + (format "%s, setting that" v))))) + +;;;###autoload (autoload 'magit-push-current-to-upstream "magit-push" nil t) +(define-suffix-command magit-push-current-to-upstream (args) + "Push the current branch to its upstream branch. + +With a prefix argument or when the upstream is either not +configured or unusable, then let the user first configure +the upstream." + :if 'magit-get-current-branch + :description 'magit-push--upstream-description + (interactive (list (magit-push-arguments))) + (let* ((branch (or (magit-get-current-branch) + (user-error "No branch is checked out"))) + (remote (magit-get "branch" branch "remote")) + (merge (magit-get "branch" branch "merge"))) + (when (or current-prefix-arg + (not (or (magit-get-upstream-branch branch) + (magit--unnamed-upstream-p remote merge) + (magit--valid-upstream-p remote merge)))) + (let* ((branches (-union (--map (concat it "/" branch) + (magit-list-remotes)) + (magit-list-remote-branch-names))) + (upstream (magit-completing-read + (format "Set upstream of %s and push there" branch) + branches nil nil nil 'magit-revision-history + (or (car (member (magit-remote-branch-at-point) branches)) + (car (member "origin/master" branches))))) + (upstream (or (magit-get-tracked upstream) + (magit-split-branch-name upstream)))) + (setq remote (car upstream)) + (setq merge (cdr upstream)) + (unless (string-prefix-p "refs/" merge) + ;; User selected a non-existent remote-tracking branch. + ;; It is very likely, but not certain, that this is the + ;; correct thing to do. It is even more likely that it + ;; is what the user wants to happen. + (setq merge (concat "refs/heads/" merge)))) + (cl-pushnew "--set-upstream" args :test #'equal)) + (run-hooks 'magit-credential-hook) + (magit-run-git-async "push" "-v" args remote (concat branch ":" merge)))) + +(defun magit-push--upstream-description () + (when-let ((branch (magit-get-current-branch))) + (or (magit-get-upstream-branch branch) + (let ((remote (magit-get "branch" branch "remote")) + (merge (magit-get "branch" branch "merge")) + (u (magit--propertize-face "@{upstream}" 'bold))) + (cond + ((magit--unnamed-upstream-p remote merge) + (format "%s as %s" + (magit--propertize-face remote 'bold) + (magit--propertize-face merge 'magit-branch-remote))) + ((magit--valid-upstream-p remote merge) + (format "%s creating %s" + (magit--propertize-face remote 'magit-branch-remote) + (magit--propertize-face merge 'magit-branch-remote))) + ((or remote merge) + (concat u ", creating it and replacing invalid")) + (t + (concat u ", creating it"))))))) + +;;;###autoload +(defun magit-push-current (target args) + "Push the current branch to a branch read in the minibuffer." + (interactive + (--if-let (magit-get-current-branch) + (list (magit-read-remote-branch (format "Push %s to" it) + nil nil it 'confirm) + (magit-push-arguments)) + (user-error "No branch is checked out"))) + (magit-git-push (magit-get-current-branch) target args)) + +;;;###autoload +(defun magit-push-other (source target args) + "Push an arbitrary branch or commit somewhere. +Both the source and the target are read in the minibuffer." + (interactive + (let ((source (magit-read-local-branch-or-commit "Push"))) + (list source + (magit-read-remote-branch + (format "Push %s to" source) nil + (if (magit-local-branch-p source) + (or (magit-get-push-branch source) + (magit-get-upstream-branch source)) + (and (magit-rev-ancestor-p source "HEAD") + (or (magit-get-push-branch) + (magit-get-upstream-branch)))) + source 'confirm) + (magit-push-arguments)))) + (magit-git-push source target args)) + +(defvar magit-push-refspecs-history nil) + +;;;###autoload +(defun magit-push-refspecs (remote refspecs args) + "Push one or multiple REFSPECS to a REMOTE. +Both the REMOTE and the REFSPECS are read in the minibuffer. To +use multiple REFSPECS, separate them with commas. Completion is +only available for the part before the colon, or when no colon +is used." + (interactive + (list (magit-read-remote "Push to remote") + (split-string (magit-completing-read-multiple + "Push refspec,s" + (cons "HEAD" (magit-list-local-branch-names)) + nil nil 'magit-push-refspecs-history) + crm-default-separator t) + (magit-push-arguments))) + (run-hooks 'magit-credential-hook) + (magit-run-git-async "push" "-v" args remote refspecs)) + +;;;###autoload +(defun magit-push-matching (remote &optional args) + "Push all matching branches to another repository. +If multiple remotes exist, then read one from the user. +If just one exists, use that without requiring confirmation." + (interactive (list (magit-read-remote "Push matching branches to" nil t) + (magit-push-arguments))) + (run-hooks 'magit-credential-hook) + (magit-run-git-async "push" "-v" args remote ":")) + +;;;###autoload +(defun magit-push-tags (remote &optional args) + "Push all tags to another repository. +If only one remote exists, then push to that. Otherwise prompt +for a remote, offering the remote configured for the current +branch as default." + (interactive (list (magit-read-remote "Push tags to remote" nil t) + (magit-push-arguments))) + (run-hooks 'magit-credential-hook) + (magit-run-git-async "push" remote "--tags" args)) + +;;;###autoload +(defun magit-push-tag (tag remote &optional args) + "Push a tag to another repository." + (interactive + (let ((tag (magit-read-tag "Push tag"))) + (list tag (magit-read-remote (format "Push %s to remote" tag) nil t) + (magit-push-arguments)))) + (run-hooks 'magit-credential-hook) + (magit-run-git-async "push" remote tag args)) + +;;;###autoload +(defun magit-push-implicitly (args) + "Push somewhere without using an explicit refspec. + +This command simply runs \"git push -v [ARGS]\". ARGS are the +arguments specified in the popup buffer. No explicit refspec +arguments are used. Instead the behavior depends on at least +these Git variables: `push.default', `remote.pushDefault', +`branch..pushRemote', `branch..remote', +`branch..merge', and `remote..push'. + +The function `magit-push-implicitly--desc' attempts to predict +what this command will do. The value it returns is displayed in +the popup buffer." + (interactive (list (magit-push-arguments))) + (run-hooks 'magit-credential-hook) + (magit-run-git-async "push" "-v" args)) + +(defun magit-push-implicitly--desc () + (let ((default (magit-get "push.default"))) + (unless (equal default "nothing") + (or (when-let ((remote (or (magit-get-remote) + (magit-remote-p "origin"))) + (refspec (magit-get "remote" remote "push"))) + (format "%s using %s" + (magit--propertize-face remote 'magit-branch-remote) + (magit--propertize-face refspec 'bold))) + (--when-let (and (not (magit-get-push-branch)) + (magit-get-upstream-branch)) + (format "%s aka %s\n" + (magit-branch-set-face it) + (magit--propertize-face "@{upstream}" 'bold))) + (--when-let (magit-get-push-branch) + (format "%s aka %s\n" + (magit-branch-set-face it) + (magit--propertize-face "pushRemote" 'bold))) + (--when-let (magit-get-@{push}-branch) + (format "%s aka %s\n" + (magit-branch-set-face it) + (magit--propertize-face "@{push}" 'bold))) + (format "using %s (%s is %s)\n" + (magit--propertize-face "git push" 'bold) + (magit--propertize-face "push.default" 'bold) + (magit--propertize-face default 'bold)))))) + +;;;###autoload +(defun magit-push-to-remote (remote args) + "Push to REMOTE without using an explicit refspec. +The REMOTE is read in the minibuffer. + +This command simply runs \"git push -v [ARGS] REMOTE\". ARGS +are the arguments specified in the popup buffer. No refspec +arguments are used. Instead the behavior depends on at least +these Git variables: `push.default', `remote.pushDefault', +`branch..pushRemote', `branch..remote', +`branch..merge', and `remote..push'." + (interactive (list (magit-read-remote "Push to remote") + (magit-push-arguments))) + (run-hooks 'magit-credential-hook) + (magit-run-git-async "push" "-v" args remote)) + +(defun magit-push-to-remote--desc () + (format "using %s\n" (magit--propertize-face "git push " 'bold))) + +;;; _ +(provide 'magit-push) +;;; magit-push.el ends here diff --git a/elpa/magit-20191122.2040/magit-push.elc b/elpa/magit-20191122.2040/magit-push.elc new file mode 100644 index 0000000000000000000000000000000000000000..6368192f0777e3d2b68ebd9fef22edddd18d5833 GIT binary patch literal 12261 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 +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; This library implements support for looking at Git reflogs. + +;;; Code: + +(require 'magit-core) +(require 'magit-log) + +(eval-when-compile + (require 'subr-x)) + +;;; Options + +(defcustom magit-reflog-limit 256 + "Maximal number of entries initially shown in reflog buffers. +The limit in the current buffer can be changed using \"+\" +and \"-\"." + :package-version '(magit . "2.91.0") + :group 'magit-commands + :type 'number) + +(defcustom magit-reflog-margin + (list (nth 0 magit-log-margin) + (nth 1 magit-log-margin) + 'magit-log-margin-width nil + (nth 4 magit-log-margin)) + "Format of the margin in `magit-reflog-mode' buffers. + +The value has the form (INIT STYLE WIDTH AUTHOR AUTHOR-WIDTH). + +If INIT is non-nil, then the margin is shown initially. +STYLE controls how to format the author or committer date. + It can be one of `age' (to show the age of the commit), + `age-abbreviated' (to abbreviate the time unit to a character), + or a string (suitable for `format-time-string') to show the + actual date. Option `magit-log-margin-show-committer-date' + controls which date is being displayed. +WIDTH controls the width of the margin. This exists for forward + compatibility and currently the value should not be changed. +AUTHOR controls whether the name of the author is also shown by + default. +AUTHOR-WIDTH has to be an integer. When the name of the author + is shown, then this specifies how much space is used to do so." + :package-version '(magit . "2.9.0") + :group 'magit-log + :group 'magit-margin + :type magit-log-margin--custom-type + :initialize 'magit-custom-initialize-reset + :set-after '(magit-log-margin) + :set (apply-partially #'magit-margin-set-variable 'magit-reflog-mode)) + +;;; Faces + +(defface magit-reflog-commit '((t :foreground "green")) + "Face for commit commands in reflogs." + :group 'magit-faces) + +(defface magit-reflog-amend '((t :foreground "magenta")) + "Face for amend commands in reflogs." + :group 'magit-faces) + +(defface magit-reflog-merge '((t :foreground "green")) + "Face for merge, checkout and branch commands in reflogs." + :group 'magit-faces) + +(defface magit-reflog-checkout '((t :foreground "blue")) + "Face for checkout commands in reflogs." + :group 'magit-faces) + +(defface magit-reflog-reset '((t :foreground "red")) + "Face for reset commands in reflogs." + :group 'magit-faces) + +(defface magit-reflog-rebase '((t :foreground "magenta")) + "Face for rebase commands in reflogs." + :group 'magit-faces) + +(defface magit-reflog-cherry-pick '((t :foreground "green")) + "Face for cherry-pick commands in reflogs." + :group 'magit-faces) + +(defface magit-reflog-remote '((t :foreground "cyan")) + "Face for pull and clone commands in reflogs." + :group 'magit-faces) + +(defface magit-reflog-other '((t :foreground "cyan")) + "Face for other commands in reflogs." + :group 'magit-faces) + +;;; Commands + +;;;###autoload +(defun magit-reflog-current () + "Display the reflog of the current branch. +If `HEAD' is detached, then show the reflog for that instead." + (interactive) + (magit-reflog-setup-buffer (or (magit-get-current-branch) "HEAD"))) + +;;;###autoload +(defun magit-reflog-other (ref) + "Display the reflog of a branch or another ref." + (interactive (list (magit-read-local-branch-or-ref "Show reflog for"))) + (magit-reflog-setup-buffer ref)) + +;;;###autoload +(defun magit-reflog-head () + "Display the `HEAD' reflog." + (interactive) + (magit-reflog-setup-buffer "HEAD")) + +;;; Mode + +(defvar magit-reflog-mode-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map magit-log-mode-map) + (define-key map "\C-c\C-n" 'undefined) + (define-key map "L" 'magit-margin-settings) + map) + "Keymap for `magit-reflog-mode'.") + +(define-derived-mode magit-reflog-mode magit-mode "Magit Reflog" + "Mode for looking at Git reflog. + +This mode is documented in info node `(magit)Reflog'. + +\\\ +Type \\[magit-refresh] to refresh the current buffer. +Type \\[magit-visit-thing] or \\[magit-diff-show-or-scroll-up] \ +to visit the commit at point. + +Type \\[magit-cherry-pick] to apply the commit at point. +Type \\[magit-reset] to reset `HEAD' to the commit at point. + +\\{magit-reflog-mode-map}" + :group 'magit-log + (hack-dir-local-variables-non-file-buffer)) + +(defun magit-reflog-setup-buffer (ref) + (require 'magit) + (magit-setup-buffer #'magit-reflog-mode nil + (magit-buffer-refname ref) + (magit-buffer-log-args (list (format "-n%s" magit-reflog-limit))))) + +(defun magit-reflog-refresh-buffer () + (magit-set-header-line-format (concat "Reflog for " magit-buffer-refname)) + (magit-insert-section (reflogbuf) + (magit-git-wash (apply-partially 'magit-log-wash-log 'reflog) + "reflog" "show" "--format=%h%x00%aN%x00%gd%x00%gs" "--date=raw" + magit-buffer-log-args magit-buffer-refname "--"))) + +(cl-defmethod magit-buffer-value (&context (major-mode magit-reflog-mode)) + magit-buffer-refname) + +(defvar magit-reflog-labels + '(("commit" . magit-reflog-commit) + ("amend" . magit-reflog-amend) + ("merge" . magit-reflog-merge) + ("checkout" . magit-reflog-checkout) + ("branch" . magit-reflog-checkout) + ("reset" . magit-reflog-reset) + ("rebase" . magit-reflog-rebase) + ("cherry-pick" . magit-reflog-cherry-pick) + ("initial" . magit-reflog-commit) + ("pull" . magit-reflog-remote) + ("clone" . magit-reflog-remote) + ("autosave" . magit-reflog-commit) + ("restart" . magit-reflog-reset))) + +(defun magit-reflog-format-subject (subject) + (let* ((match (string-match magit-reflog-subject-re subject)) + (command (and match (match-string 1 subject))) + (option (and match (match-string 2 subject))) + (type (and match (match-string 3 subject))) + (label (if (string= command "commit") + (or type command) + command)) + (text (if (string= command "commit") + label + (mapconcat #'identity + (delq nil (list command option type)) + " ")))) + (format "%-16s " + (magit--propertize-face + text (or (cdr (assoc label magit-reflog-labels)) + 'magit-reflog-other))))) + +;;; _ +(provide 'magit-reflog) +;;; magit-reflog.el ends here diff --git a/elpa/magit-20191122.2040/magit-reflog.elc b/elpa/magit-20191122.2040/magit-reflog.elc new file mode 100644 index 0000000000000000000000000000000000000000..d57247251ebe016edb1770c77e9bddd35877f056 GIT binary patch literal 9998 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 +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; This library implements support for listing references in a buffer. + +;;; Code: + +(eval-when-compile + (require 'subr-x)) + +(require 'magit) + +;;; Options + +(defgroup magit-refs nil + "Inspect and manipulate Git branches and tags." + :link '(info-link "(magit)References Buffer") + :group 'magit-modes) + +(defcustom magit-refs-mode-hook nil + "Hook run after entering Magit-Refs mode." + :package-version '(magit . "2.1.0") + :group 'magit-refs + :type 'hook) + +(defcustom magit-refs-sections-hook + '(magit-insert-error-header + magit-insert-branch-description + magit-insert-local-branches + magit-insert-remote-branches + magit-insert-tags) + "Hook run to insert sections into a references buffer." + :package-version '(magit . "2.1.0") + :group 'magit-refs + :type 'hook) + +(defcustom magit-refs-show-commit-count nil + "Whether to show commit counts in Magit-Refs mode buffers. + +all Show counts for branches and tags. +branch Show counts for branches only. +nil Never show counts. + +To change the value in an existing buffer use the command +`magit-refs-show-commit-count'" + :package-version '(magit . "2.1.0") + :group 'magit-refs + :safe (lambda (val) (memq val '(all branch nil))) + :type '(choice (const all :tag "For branches and tags") + (const branch :tag "For branches only") + (const nil :tag "Never"))) +(put 'magit-refs-show-commit-count 'safe-local-variable 'symbolp) +(put 'magit-refs-show-commit-count 'permanent-local t) + +(defcustom magit-refs-pad-commit-counts nil + "Whether to pad all counts on all sides in `magit-refs-mode' buffers. + +If this is nil, then some commit counts are displayed right next +to one of the branches that appear next to the count, without any +space in between. This might look bad if the branch name faces +look too similar to `magit-dimmed'. + +If this is non-nil, then spaces are placed on both sides of all +commit counts." + :package-version '(magit . "2.12.0") + :group 'magit-refs + :type 'boolean) + +(defvar magit-refs-show-push-remote nil + "Whether to show the push-remotes of local branches. +Also show the commits that the local branch is ahead and behind +the push-target. Unfortunately there is a bug in Git that makes +this useless (the commits ahead and behind the upstream are +shown), so this isn't enabled yet.") + +(defcustom magit-refs-show-remote-prefix nil + "Whether to show the remote prefix in lists of remote branches. + +This is redundant because the name of the remote is already shown +in the heading preceding the list of its branches." + :package-version '(magit . "2.12.0") + :group 'magit-refs + :type 'boolean) + +(defcustom magit-refs-margin + (list nil + (nth 1 magit-log-margin) + 'magit-log-margin-width nil + (nth 4 magit-log-margin)) + "Format of the margin in `magit-refs-mode' buffers. + +The value has the form (INIT STYLE WIDTH AUTHOR AUTHOR-WIDTH). + +If INIT is non-nil, then the margin is shown initially. +STYLE controls how to format the author or committer date. + It can be one of `age' (to show the age of the commit), + `age-abbreviated' (to abbreviate the time unit to a character), + or a string (suitable for `format-time-string') to show the + actual date. Option `magit-log-margin-show-committer-date' + controls which date is being displayed. +WIDTH controls the width of the margin. This exists for forward + compatibility and currently the value should not be changed. +AUTHOR controls whether the name of the author is also shown by + default. +AUTHOR-WIDTH has to be an integer. When the name of the author + is shown, then this specifies how much space is used to do so." + :package-version '(magit . "2.9.0") + :group 'magit-refs + :group 'magit-margin + :safe (lambda (val) (memq val '(all branch nil))) + :type magit-log-margin--custom-type + :initialize 'magit-custom-initialize-reset + :set-after '(magit-log-margin) + :set (apply-partially #'magit-margin-set-variable 'magit-refs-mode)) + +(defcustom magit-refs-margin-for-tags nil + "Whether to show information about tags in the margin. + +This is disabled by default because it is slow if there are many +tags." + :package-version '(magit . "2.9.0") + :group 'magit-refs + :group 'magit-margin + :type 'boolean) + +(defcustom magit-refs-primary-column-width (cons 16 32) + "Width of the focus column in `magit-refs-mode' buffers. + +The primary column is the column that contains the name of the +branch that the current row is about. + +If this is an integer, then the column is that many columns wide. +Otherwise it has to be a cons-cell of two integers. The first +specifies the minimal width, the second the maximal width. In that +case the actual width is determined using the length of the names +of the shown local branches. (Remote branches and tags are not +taken into account when calculating to optimal width.)" + :package-version '(magit . "2.12.0") + :group 'magit-refs + :type '(choice (integer :tag "Constant wide") + (cons :tag "Wide constrains" + (integer :tag "Minimum") + (integer :tag "Maximum")))) + +(defcustom magit-refs-focus-column-width 5 + "Width of the focus column in `magit-refs-mode' buffers. + +The focus column is the first column, which marks one +branch (usually the current branch) as the focused branch using +\"*\" or \"@\". For each other reference, this column optionally +shows how many commits it is ahead of the focused branch and \"<\", or +if it isn't ahead then the commits it is behind and \">\", or if it +isn't behind either, then a \"=\". + +This column may also display only \"*\" or \"@\" for the focused +branch, in which case this option is ignored. Use \"L v\" to +change the verbosity of this column." + :package-version '(magit . "2.12.0") + :group 'magit-refs + :type 'integer) + +(defcustom magit-refs-filter-alist nil + "Alist controlling which refs are omitted from `magit-refs-mode' buffers. + +The purpose of this option is to forgo displaying certain refs +based on their name. If you want to not display any refs of a +certain type, then you should remove the appropriate function +from `magit-refs-sections-hook' instead. + +All keys are tried in order until one matches. Then its value +is used and subsequent elements are ignored. If the value is +non-nil, then the reference is displayed, otherwise it is not. +If no element matches, then the reference is displayed. + +A key can either be a regular expression that the refname has to +match, or a function that takes the refname as only argument and +returns a boolean. A remote branch such as \"origin/master\" is +displayed as just \"master\", however for this comparison the +former is used." + :package-version '(magit . "2.12.0") + :group 'magit-refs + :type '(alist :key-type (choice :tag "Key" regexp function) + :value-type (boolean :tag "Value" + :on "show (non-nil)" + :off "omit (nil)"))) + +(defcustom magit-visit-ref-behavior nil + "Control how `magit-visit-ref' behaves in `magit-refs-mode' buffers. + +By default `magit-visit-ref' behaves like `magit-show-commit', +in all buffers, including `magit-refs-mode' buffers. When the +type of the section at point is `commit' then \"RET\" is bound to +`magit-show-commit', and when the type is either `branch' or +`tag' then it is bound to `magit-visit-ref'. + +\"RET\" is one of Magit's most essential keys and at least by +default it should behave consistently across all of Magit, +especially because users quickly learn that it does something +very harmless; it shows more information about the thing at point +in another buffer. + +However \"RET\" used to behave differently in `magit-refs-mode' +buffers, doing surprising things, some of which cannot really be +described as \"visit this thing\". If you have grown accustomed +to such inconsistent, but to you useful, behavior, then you can +restore that by adding one or more of the below symbols to the +value of this option. But keep in mind that by doing so you +don't only introduce inconsistencies, you also lose some +functionality and might have to resort to `M-x magit-show-commit' +to get it back. + +`magit-visit-ref' looks for these symbols in the order in which +they are described here. If the presence of a symbol applies to +the current situation, then the symbols that follow do not affect +the outcome. + +`focus-on-ref' + + With a prefix argument update the buffer to show commit counts + and lists of cherry commits relative to the reference at point + instead of relative to the current buffer or `HEAD'. + + Instead of adding this symbol, consider pressing \"C-u y o RET\". + +`create-branch' + + If point is on a remote branch, then create a new local branch + with the same name, use the remote branch as its upstream, and + then check out the local branch. + + Instead of adding this symbol, consider pressing \"b c RET RET\", + like you would do in other buffers. + +`checkout-any' + + Check out the reference at point. If that reference is a tag + or a remote branch, then this results in a detached `HEAD'. + + Instead of adding this symbol, consider pressing \"b b RET\", + like you would do in other buffers. + +`checkout-branch' + + Check out the local branch at point. + + Instead of adding this symbol, consider pressing \"b b RET\", + like you would do in other buffers." + :package-version '(magit . "2.9.0") + :group 'magit-refs + :group 'magit-commands + :options '(focus-on-ref create-branch checkout-any checkout-branch) + :type '(list :convert-widget custom-hook-convert-widget)) + +;;; Mode + +(defvar magit-refs-mode-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map magit-mode-map) + (define-key map "\C-y" 'magit-refs-set-show-commit-count) + (define-key map "L" 'magit-margin-settings) + map) + "Keymap for `magit-refs-mode'.") + +(define-derived-mode magit-refs-mode magit-mode "Magit Refs" + "Mode which lists and compares references. + +This mode is documented in info node `(magit)References Buffer'. + +\\\ +Type \\[magit-refresh] to refresh the current buffer. +Type \\[magit-section-toggle] to expand or hide the section at point. +Type \\[magit-visit-thing] or \\[magit-diff-show-or-scroll-up] \ +to visit the commit or branch at point. + +Type \\[magit-branch] to see available branch commands. +Type \\[magit-merge] to merge the branch or commit at point. +Type \\[magit-cherry-pick] to apply the commit at point. +Type \\[magit-reset] to reset `HEAD' to the commit at point. + +\\{magit-refs-mode-map}" + :group 'magit-refs + (hack-dir-local-variables-non-file-buffer) + (setq imenu-create-index-function + #'magit-imenu--refs-create-index-function)) + +(defun magit-refs-setup-buffer (ref args) + (magit-setup-buffer #'magit-refs-mode nil + (magit-buffer-upstream ref) + (magit-buffer-arguments args))) + +(defun magit-refs-refresh-buffer () + (setq magit-set-buffer-margin-refresh (not (magit-buffer-margin-p))) + (unless (magit-rev-verify magit-buffer-upstream) + (setq magit-refs-show-commit-count nil)) + (magit-set-header-line-format + (format "%s %s" magit-buffer-upstream + (mapconcat #'identity magit-buffer-arguments " "))) + (magit-insert-section (branchbuf) + (magit-run-section-hook 'magit-refs-sections-hook)) + (add-hook 'kill-buffer-hook 'magit-preserve-section-visibility-cache)) + +(cl-defmethod magit-buffer-value (&context (major-mode magit-refs-mode)) + (cons magit-buffer-upstream magit-buffer-arguments)) + +;;; Commands + +;;;###autoload (autoload 'magit-show-refs "magit-refs" nil t) +(define-transient-command magit-show-refs (&optional transient) + "List and compare references in a dedicated buffer." + :man-page "git-branch" + :value 'magit-show-refs-arguments + ["Arguments" + (magit-for-each-ref:--contains) + ("=m" "Merged" "--merged=" magit-transient-read-revision) + ("-m" "Merged to HEAD" "--merged") + ("-M" "Merged to master" "--merged=master") + ("=n" "Not merged" "--no-merged=" magit-transient-read-revision) + ("-n" "Not merged to HEAD" "--no-merged") + ("-N" "Not merged to master" "--no-merged=master") + (magit-for-each-ref:--sort)] + ["Actions" + ("y" "Show refs, comparing them with HEAD" magit-show-refs-head) + ("c" "Show refs, comparing them with current branch" magit-show-refs-current) + ("o" "Show refs, comparing them with other branch" magit-show-refs-other)] + (interactive (list (or (derived-mode-p 'magit-refs-mode) + current-prefix-arg))) + (if transient + (transient-setup 'magit-show-refs) + (magit-refs-setup-buffer "HEAD" (magit-show-refs-arguments)))) + +(defun magit-show-refs-arguments () + (let (args) + (cond + ((eq current-transient-command 'magit-show-refs) + (setq args (transient-args 'magit-show-refs))) + ((eq major-mode 'magit-show-refs-mode) + (setq args magit-buffer-arguments)) + ((and (memq magit-prefix-use-buffer-arguments '(always selected)) + (when-let ((buffer (magit-get-mode-buffer + 'magit-refs-mode nil + (or (eq magit-prefix-use-buffer-arguments + 'selected) + 'all)))) + (setq args (buffer-local-value 'magit-buffer-arguments buffer)) + t))) + (t + (setq args (alist-get 'magit-show-refs transient-values)))) + args)) + +(define-infix-argument magit-for-each-ref:--contains () + :description "Contains" + :class 'transient-option + :key "-c" + :argument "--contains=" + :reader 'magit-transient-read-revision) + +(define-infix-argument magit-for-each-ref:--sort () + :description "Sort" + :class 'transient-option + :key "-s" + :argument "--sort=" + :reader 'magit-read-ref-sort) + +(defun magit-read-ref-sort (prompt initial-input _history) + (magit-completing-read prompt + '("-committerdate" "-authordate" + "committerdate" "authordate") + nil nil initial-input)) + +;;;###autoload +(defun magit-show-refs-head (&optional args) + "List and compare references in a dedicated buffer. +Compared with `HEAD'." + (interactive (list (magit-show-refs-arguments))) + (magit-refs-setup-buffer "HEAD" args)) + +;;;###autoload +(defun magit-show-refs-current (&optional args) + "List and compare references in a dedicated buffer. +Compare with the current branch or `HEAD' if it is detached." + (interactive (list (magit-show-refs-arguments))) + (magit-refs-setup-buffer (magit-get-current-branch) args)) + +;;;###autoload +(defun magit-show-refs-other (&optional ref args) + "List and compare references in a dedicated buffer. +Compared with a branch read from the user." + (interactive (list (magit-read-other-branch "Compare with") + (magit-show-refs-arguments))) + (magit-refs-setup-buffer ref args)) + +(defun magit-refs-set-show-commit-count () + "Change for which refs the commit count is shown." + (interactive) + (setq-local magit-refs-show-commit-count + (magit-read-char-case "Show commit counts for " nil + (?a "[a]ll refs" 'all) + (?b "[b]ranches only" t) + (?n "[n]othing" nil))) + (magit-refresh)) + +(defun magit-visit-ref () + "Visit the reference or revision at point in another buffer. +If there is no revision at point or with a prefix argument prompt +for a revision. + +This command behaves just like `magit-show-commit', except if +point is on a reference in a `magit-refs-mode' buffer (a buffer +listing branches and tags), in which case the behavior may be +different, but only if you have customized the option +`magit-visit-ref-behavior' (which see)." + (interactive) + (if (and (derived-mode-p 'magit-refs-mode) + (magit-section-match '(branch tag))) + (let ((ref (oref (magit-current-section) value))) + (cond (current-prefix-arg + (cond ((memq 'focus-on-ref magit-visit-ref-behavior) + (magit-refs-setup-buffer ref (magit-show-refs-arguments))) + (magit-visit-ref-behavior + ;; Don't prompt for commit to visit. + (let ((current-prefix-arg nil)) + (call-interactively #'magit-show-commit))))) + ((and (memq 'create-branch magit-visit-ref-behavior) + (magit-section-match [branch remote])) + (let ((branch (cdr (magit-split-branch-name ref)))) + (if (magit-branch-p branch) + (if (magit-rev-eq branch ref) + (magit-call-git "checkout" branch) + (setq branch (propertize branch 'face 'magit-branch-local)) + (setq ref (propertize ref 'face 'magit-branch-remote)) + (pcase (prog1 (read-char-choice (format (propertize "\ +Branch %s already exists. + [c]heckout %s as-is + [r]reset %s to %s and checkout %s + [a]bort " 'face 'minibuffer-prompt) branch branch branch ref branch) + '(?c ?r ?a)) + (message "")) ; otherwise prompt sticks + (?c (magit-call-git "checkout" branch)) + (?r (magit-call-git "checkout" "-B" branch ref)) + (?a (user-error "Abort")))) + (magit-call-git "checkout" "-b" branch ref)) + (setq magit-buffer-upstream branch) + (magit-refresh))) + ((or (memq 'checkout-any magit-visit-ref-behavior) + (and (memq 'checkout-branch magit-visit-ref-behavior) + (magit-section-match [branch local]))) + (magit-call-git "checkout" ref) + (setq magit-buffer-upstream ref) + (magit-refresh)) + (t + (call-interactively #'magit-show-commit)))) + (call-interactively #'magit-show-commit))) + +;;; Sections + +(defvar magit-remote-section-map + (let ((map (make-sparse-keymap))) + (define-key map [remap magit-delete-thing] 'magit-remote-remove) + (define-key map "R" 'magit-remote-rename) + map) + "Keymap for `remote' sections.") + +(defvar magit-branch-section-map + (let ((map (make-sparse-keymap))) + (define-key map [remap magit-visit-thing] 'magit-visit-ref) + (define-key map [remap magit-delete-thing] 'magit-branch-delete) + (define-key map "R" 'magit-branch-rename) + map) + "Keymap for `branch' sections.") + +(defvar magit-tag-section-map + (let ((map (make-sparse-keymap))) + (define-key map [remap magit-visit-thing] 'magit-visit-ref) + (define-key map [remap magit-delete-thing] 'magit-tag-delete) + map) + "Keymap for `tag' sections.") + +(defun magit-insert-branch-description () + "Insert header containing the description of the current branch. +Insert a header line with the name and description of the +current branch. The description is taken from the Git variable +`branch..description'; if that is undefined then no header +line is inserted at all." + (when-let ((branch (magit-get-current-branch)) + (desc (magit-get "branch" branch "description")) + (desc (split-string desc "\n"))) + (when (equal (car (last desc)) "") + (setq desc (butlast desc))) + (magit-insert-section (branchdesc branch t) + (magit-insert-heading branch ": " (car desc)) + (when (cdr desc) + (insert (mapconcat 'identity (cdr desc) "\n")) + (insert "\n\n"))))) + +(defun magit-insert-tags () + "Insert sections showing all tags." + (when-let ((tags (magit-git-lines "tag" "--list" "-n" magit-buffer-arguments))) + (let ((_head (magit-rev-parse "HEAD"))) + (magit-insert-section (tags) + (magit-insert-heading "Tags:") + (dolist (tag tags) + (string-match "^\\([^ \t]+\\)[ \t]+\\([^ \t\n].*\\)?" tag) + (let ((tag (match-string 1 tag)) + (msg (match-string 2 tag))) + (when (magit-refs--insert-refname-p tag) + (magit-insert-section (tag tag t) + (magit-insert-heading + (magit-refs--format-focus-column tag 'tag) + (propertize tag 'font-lock-face 'magit-tag) + (make-string (max 1 (- magit-refs-primary-column-width + (length tag))) + ?\s) + (and msg (magit-log-propertize-keywords nil msg))) + (when (and magit-refs-margin-for-tags (magit-buffer-margin-p)) + (magit-refs--format-margin tag)) + (magit-refs--insert-cherry-commits tag))))) + (insert ?\n) + (magit-make-margin-overlay nil t))))) + +(defun magit-insert-remote-branches () + "Insert sections showing all remote-tracking branches." + (dolist (remote (magit-list-remotes)) + (magit-insert-section (remote remote) + (magit-insert-heading + (let ((pull (magit-get "remote" remote "url")) + (push (magit-get "remote" remote "pushurl"))) + (format (propertize "Remote %s (%s):" + 'font-lock-face 'magit-section-heading) + (propertize remote 'font-lock-face 'magit-branch-remote) + (concat pull (and pull push ", ") push)))) + (let (head) + (dolist (line (magit-git-lines "for-each-ref" "--format=\ +%(symref:short)%00%(refname:short)%00%(refname)%00%(subject)" + (concat "refs/remotes/" remote) + magit-buffer-arguments)) + (pcase-let ((`(,head-branch ,branch ,ref ,msg) + (-replace "" nil (split-string line "\0")))) + (if head-branch + (progn (cl-assert (equal branch (concat remote "/HEAD"))) + (setq head head-branch)) + (when (magit-refs--insert-refname-p branch) + (magit-insert-section (branch branch t) + (let ((headp (equal branch head)) + (abbrev (if magit-refs-show-remote-prefix + branch + (substring branch (1+ (length remote)))))) + (magit-insert-heading + (magit-refs--format-focus-column branch) + (magit-refs--propertize-branch + abbrev ref (and headp 'magit-branch-remote-head)) + (make-string (max 1 (- magit-refs-primary-column-width + (length abbrev))) + ?\s) + (and msg (magit-log-propertize-keywords nil msg)))) + (when (magit-buffer-margin-p) + (magit-refs--format-margin branch)) + (magit-refs--insert-cherry-commits branch))))))) + (insert ?\n) + (magit-make-margin-overlay nil t)))) + +(defun magit-insert-local-branches () + "Insert sections showing all local branches." + (magit-insert-section (local nil) + (magit-insert-heading "Branches:") + (dolist (line (magit-refs--format-local-branches)) + (pcase-let ((`(,branch . ,strings) line)) + (magit-insert-section + ((eval (if branch 'branch 'commit)) + (or branch (magit-rev-parse "HEAD")) + t) + (apply #'magit-insert-heading strings) + (when (magit-buffer-margin-p) + (magit-refs--format-margin branch)) + (magit-refs--insert-cherry-commits branch)))) + (insert ?\n) + (magit-make-margin-overlay nil t))) + +(defun magit-refs--format-local-branches () + (let ((lines (-keep 'magit-refs--format-local-branch + (magit-git-lines + "for-each-ref" + (concat "--format=\ +%(HEAD)%00%(refname:short)%00%(refname)%00\ +%(upstream:short)%00%(upstream)%00%(upstream:track)%00" + (if magit-refs-show-push-remote "\ +%(push:remotename)%00%(push)%00%(push:track)%00%(subject)" + "%00%00%00%(subject)")) + "refs/heads" + magit-buffer-arguments)))) + (unless (magit-get-current-branch) + (push (magit-refs--format-local-branch + (concat "*\0\0\0\0\0\0\0\0" (magit-rev-format "%s"))) + lines)) + (setq-local magit-refs-primary-column-width + (let ((def (default-value 'magit-refs-primary-column-width))) + (if (atom def) + def + (pcase-let ((`(,min . ,max) def)) + (min max (apply #'max min (mapcar #'car lines))))))) + (mapcar (pcase-lambda (`(,_ ,branch ,focus ,branch-desc ,u:ahead ,p:ahead + ,u:behind ,upstream ,p:behind ,push ,msg)) + (list branch focus branch-desc u:ahead p:ahead + (make-string (max 1 (- magit-refs-primary-column-width + (length (concat branch-desc + u:ahead + p:ahead + u:behind)))) + ?\s) + u:behind upstream p:behind push + msg)) + lines))) + +(defun magit-refs--format-local-branch (line) + (pcase-let ((`(,head ,branch ,ref ,upstream ,u:ref ,u:track + ,push ,p:ref ,p:track ,msg) + (-replace "" nil (split-string line "\0")))) + (when (or (not branch) + (magit-refs--insert-refname-p branch)) + (let* ((headp (equal head "*")) + (pushp (and push + magit-refs-show-push-remote + (magit-rev-verify p:ref) + (not (equal p:ref u:ref)))) + (branch-desc + (if branch + (magit-refs--propertize-branch + branch ref (and headp 'magit-branch-current)) + (magit--propertize-face "(detached)" + 'font-lock-warning-face))) + (u:ahead (and u:track + (string-match "ahead \\([0-9]+\\)" u:track) + (magit--propertize-face + (concat (and magit-refs-pad-commit-counts " ") + (match-string 1 u:track) + ">") + 'magit-dimmed))) + (u:behind (and u:track + (string-match "behind \\([0-9]+\\)" u:track) + (magit--propertize-face + (concat "<" + (match-string 1 u:track) + (and magit-refs-pad-commit-counts " ")) + 'magit-dimmed))) + (p:ahead (and pushp p:track + (string-match "ahead \\([0-9]+\\)" p:track) + (magit--propertize-face + (concat (match-string 1 p:track) + ">" + (and magit-refs-pad-commit-counts " ")) + 'magit-branch-remote))) + (p:behind (and pushp p:track + (string-match "behind \\([0-9]+\\)" p:track) + (magit--propertize-face + (concat "<" + (match-string 1 p:track) + (and magit-refs-pad-commit-counts " ")) + 'magit-dimmed)))) + (list (1+ (length (concat branch-desc u:ahead p:ahead u:behind))) + branch + (magit-refs--format-focus-column branch headp) + branch-desc u:ahead p:ahead u:behind + (and upstream + (concat (if (equal u:track "[gone]") + (magit--propertize-face upstream 'error) + (magit-refs--propertize-branch upstream u:ref)) + " ")) + (and pushp + (concat p:behind + (magit--propertize-face + push 'magit-branch-remote) + " ")) + (and msg (magit-log-propertize-keywords nil msg))))))) + +(defun magit-refs--format-focus-column (ref &optional type) + (let ((focus magit-buffer-upstream) + (width (if magit-refs-show-commit-count + magit-refs-focus-column-width + 1))) + (format + (format "%%%ss " width) + (cond ((or (equal ref focus) + (and (eq type t) + (equal focus "HEAD"))) + (magit--propertize-face (concat (if (equal focus "HEAD") "@" "*") + (make-string (1- width) ?\s)) + 'magit-section-heading)) + ((if (eq type 'tag) + (eq magit-refs-show-commit-count 'all) + magit-refs-show-commit-count) + (pcase-let ((`(,behind ,ahead) + (magit-rev-diff-count magit-buffer-upstream ref))) + (magit--propertize-face + (cond ((> ahead 0) (concat "<" (number-to-string ahead))) + ((> behind 0) (concat (number-to-string behind) ">")) + (t "=")) + 'magit-dimmed))) + (t ""))))) + +(defun magit-refs--propertize-branch (branch ref &optional head-face) + (let ((face (cdr (cl-find-if (pcase-lambda (`(,re . ,_)) + (string-match-p re ref)) + magit-ref-namespaces)))) + (magit--propertize-face + branch (if head-face (list face head-face) face)))) + +(defun magit-refs--insert-refname-p (refname) + (--if-let (-first (pcase-lambda (`(,key . ,_)) + (if (functionp key) + (funcall key refname) + (string-match-p key refname))) + magit-refs-filter-alist) + (cdr it) + t)) + +(defun magit-refs--insert-cherry-commits (ref) + (magit-insert-section-body + (let ((start (point)) + (magit-insert-section--current nil)) + (magit-git-wash (apply-partially 'magit-log-wash-log 'cherry) + "cherry" "-v" (magit-abbrev-arg) magit-buffer-upstream ref) + (if (= (point) start) + (message "No cherries for %s" ref) + (magit-make-margin-overlay nil t))))) + +(defun magit-refs--format-margin (commit) + (save-excursion + (goto-char (line-beginning-position 0)) + (let ((line (magit-rev-format "%ct%cN" commit))) + (magit-log-format-margin commit + (substring line 10) + (substring line 0 10))))) + +;;; _ +(provide 'magit-refs) +;;; magit-refs.el ends here diff --git a/elpa/magit-20191122.2040/magit-refs.elc b/elpa/magit-20191122.2040/magit-refs.elc new file mode 100644 index 0000000000000000000000000000000000000000..0f4f09b4598945306ed662b2f07fa7a3e51ee5a9 GIT binary patch literal 40256 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 +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; This library implements remote commands. + +;;; Code: + +(require 'magit) + +;;; Options + +(defcustom magit-remote-add-set-remote.pushDefault 'ask-if-unset + "Whether to set the value of `remote.pushDefault' after adding a remote. + +If `ask', then always ask. If `ask-if-unset', then ask, but only +if the variable isn't set already. If nil, then don't ever set. +If the value is a string, then set without asking, provided that +the name of the added remote is equal to that string and the +variable isn't already set." + :package-version '(magit . "2.4.0") + :group 'magit-commands + :type '(choice (const :tag "ask if unset" ask-if-unset) + (const :tag "always ask" ask) + (string :tag "set if named") + (const :tag "don't set"))) + +(defcustom magit-remote-direct-configure t + "Whether the command `magit-remote' shows Git variables. +When set to nil, no variables are displayed by this transient +command, instead the sub-transient `magit-remote-configure' +has to be used to view and change remote related variables." + :package-version '(magit . "2.12.0") + :group 'magit-commands + :type 'boolean) + +(defcustom magit-prefer-push-default nil + "Whether to prefer `remote.pushDefault' over per-branch variables." + :package-version '(magit . "2.91.0") + :group 'magit-commands + :type 'boolean) + +;;; Commands + +;;;###autoload (autoload 'magit-remote "magit-remote" nil t) +(define-transient-command magit-remote (remote) + "Add, configure or remove a remote." + :man-page "git-remote" + :value '("-f") + ["Variables" + :if (lambda () + (and magit-remote-direct-configure + (oref transient--prefix scope))) + ("u" magit-remote..url) + ("U" magit-remote..fetch) + ("s" magit-remote..pushurl) + ("S" magit-remote..push) + ("O" magit-remote..tagopt)] + ["Arguments for add" + ("-f" "Fetch after add" "-f")] + ["Actions" + [("a" "Add" magit-remote-add) + ("r" "Rename" magit-remote-rename) + ("k" "Remove" magit-remote-remove)] + [("C" "Configure..." magit-remote-configure) + ("p" "Prune stale branches" magit-remote-prune) + ("P" "Prune stale refspecs" magit-remote-prune-refspecs)]] + (interactive (list (magit-get-current-remote))) + (transient-setup 'magit-remote nil nil :scope remote)) + +(defun magit-read-url (prompt &optional initial-input) + (let ((url (magit-read-string-ns prompt initial-input))) + (if (string-prefix-p "~" url) + (expand-file-name url) + url))) + +;;;###autoload +(defun magit-remote-add (remote url &optional args) + "Add a remote named REMOTE and fetch it." + (interactive (list (magit-read-string-ns "Remote name") + (magit-read-url "Remote url") + (transient-args 'magit-remote))) + (if (pcase (list magit-remote-add-set-remote.pushDefault + (magit-get "remote.pushDefault")) + (`(,(pred stringp) ,_) t) + ((or `(ask ,_) `(ask-if-unset nil)) + (y-or-n-p (format "Set `remote.pushDefault' to \"%s\"? " remote)))) + (progn (magit-call-git "remote" "add" args remote url) + (setf (magit-get "remote.pushDefault") remote) + (magit-refresh)) + (magit-run-git-async "remote" "add" args remote url))) + +;;;###autoload +(defun magit-remote-rename (old new) + "Rename the remote named OLD to NEW." + (interactive + (let ((remote (magit-read-remote "Rename remote"))) + (list remote (magit-read-string-ns (format "Rename %s to" remote))))) + (unless (string= old new) + (magit-call-git "remote" "rename" old new) + (magit-remote--cleanup-push-variables old new) + (magit-refresh))) + +;;;###autoload +(defun magit-remote-remove (remote) + "Delete the remote named REMOTE." + (interactive (list (magit-read-remote "Delete remote"))) + (magit-call-git "remote" "rm" remote) + (magit-remote--cleanup-push-variables remote) + (magit-refresh)) + +(defun magit-remote--cleanup-push-variables (remote &optional new-name) + (magit-with-toplevel + (when (equal (magit-get "remote.pushDefault") remote) + (magit-set new-name "remote.pushDefault")) + (dolist (var (magit-git-lines "config" "--name-only" + "--get-regexp" "^branch\.[^.]*\.pushRemote" + (format "^%s$" remote))) + (magit-call-git "config" (and (not new-name) "--unset") var new-name)))) + +(defconst magit--refspec-re "\\`\\(\\+\\)?\\([^:]+\\):\\(.*\\)\\'") + +;;;###autoload +(defun magit-remote-prune (remote) + "Remove stale remote-tracking branches for REMOTE." + (interactive (list (magit-read-remote "Prune stale branches of remote"))) + (magit-run-git-async "remote" "prune" remote)) + +;;;###autoload +(defun magit-remote-prune-refspecs (remote) + "Remove stale refspecs for REMOTE. + +A refspec is stale if there no longer exists at least one branch +on the remote that would be fetched due to that refspec. A stale +refspec is problematic because its existence causes Git to refuse +to fetch according to the remaining non-stale refspecs. + +If only stale refspecs remain, then offer to either delete the +remote or to replace the stale refspecs with the default refspec. + +Also remove the remote-tracking branches that were created due to +the now stale refspecs. Other stale branches are not removed." + (interactive (list (magit-read-remote "Prune refspecs of remote"))) + (let* ((tracking-refs (magit-list-remote-branches remote)) + (remote-refs (magit-remote-list-refs remote)) + (variable (format "remote.%s.fetch" remote)) + (refspecs (magit-get-all variable)) + stale) + (dolist (refspec refspecs) + (when (string-match magit--refspec-re refspec) + (let ((theirs (match-string 2 refspec)) + (ours (match-string 3 refspec))) + (unless (if (string-match "\\*" theirs) + (let ((re (replace-match ".*" t t theirs))) + (--some (string-match-p re it) remote-refs)) + (member theirs remote-refs)) + (push (cons refspec + (if (string-match "\\*" ours) + (let ((re (replace-match ".*" t t ours))) + (--filter (string-match-p re it) tracking-refs)) + (list (car (member ours tracking-refs))))) + stale))))) + (if (not stale) + (message "No stale refspecs for remote %S" remote) + (if (= (length stale) + (length refspecs)) + (magit-read-char-case + (format "All of %s's refspecs are stale. " remote) nil + (?s "replace with [d]efault refspec" + (magit-set-all + (list (format "+refs/heads/*:refs/remotes/%s/*" remote)) + variable)) + (?r "[r]emove remote" + (magit-call-git "remote" "rm" remote)) + (?a "or [a]abort" + (user-error "Abort"))) + (if (if (= (length stale) 1) + (pcase-let ((`(,refspec . ,refs) (car stale))) + (magit-confirm 'prune-stale-refspecs + (format "Prune stale refspec %s and branch %%s" refspec) + (format "Prune stale refspec %s and %%i branches" refspec) + nil refs)) + (magit-confirm 'prune-stale-refspecs nil + (format "Prune %%i stale refspecs and %i branches" + (length (cl-mapcan (lambda (s) (copy-sequence (cdr s))) + stale))) + nil + (mapcar (pcase-lambda (`(,refspec . ,refs)) + (concat refspec "\n" + (mapconcat (lambda (b) (concat " " b)) + refs "\n"))) + stale))) + (pcase-dolist (`(,refspec . ,refs) stale) + (magit-call-git "config" "--unset" variable + (regexp-quote refspec)) + (magit--log-action + (lambda (refs) + (format "Deleting %i branches" (length refs))) + (lambda (ref) + (format "Deleting branch %s (was %s)" ref + (magit-rev-parse "--short" ref))) + refs) + (dolist (ref refs) + (magit-call-git "update-ref" "-d" ref))) + (user-error "Abort"))) + (magit-refresh)))) + +;;;###autoload +(defun magit-remote-set-head (remote &optional branch) + "Set the local representation of REMOTE's default branch. +Query REMOTE and set the symbolic-ref refs/remotes//HEAD +accordingly. With a prefix argument query for the branch to be +used, which allows you to select an incorrect value if you fancy +doing that." + (interactive + (let ((remote (magit-read-remote "Set HEAD for remote"))) + (list remote + (and current-prefix-arg + (magit-read-remote-branch (format "Set %s/HEAD to" remote) + remote nil nil t))))) + (magit-run-git "remote" "set-head" remote (or branch "--auto"))) + +;;;###autoload +(defun magit-remote-unset-head (remote) + "Unset the local representation of REMOTE's default branch. +Delete the symbolic-ref \"refs/remotes//HEAD\"." + (interactive (list (magit-read-remote "Unset HEAD for remote"))) + (magit-run-git "remote" "set-head" remote "--delete")) + +;;; Configure + +;;;###autoload (autoload 'magit-remote-configure "magit-remote" nil t) +(define-transient-command magit-remote-configure (remote) + "Configure a remote." + :man-page "git-remote" + [:description + (lambda () + (concat + (propertize "Configure " 'face 'transient-heading) + (propertize (oref transient--prefix scope) 'face 'magit-branch-remote))) + ("u" magit-remote..url) + ("U" magit-remote..fetch) + ("s" magit-remote..pushurl) + ("S" magit-remote..push) + ("O" magit-remote..tagopt)] + (interactive + (list (or (and (not current-prefix-arg) + (not (and magit-remote-direct-configure + (eq current-transient-command 'magit-remote))) + (magit-get-current-remote)) + (magit--read-remote-scope)))) + (transient-setup 'magit-remote-configure nil nil :scope remote)) + +(defun magit--read-remote-scope (&optional obj) + (magit-read-remote + (if obj + (format "Set %s for remote" + (format (oref obj variable) "")) + "Configure remote"))) + +(define-infix-command magit-remote..url () + :class 'magit--git-variable:urls + :scope 'magit--read-remote-scope + :variable "remote.%s.url" + :multi-value t + :history-key 'magit-remote..*url) + +(define-infix-command magit-remote..fetch () + :class 'magit--git-variable + :scope 'magit--read-remote-scope + :variable "remote.%s.fetch" + :multi-value t) + +(define-infix-command magit-remote..pushurl () + :class 'magit--git-variable:urls + :scope 'magit--read-remote-scope + :variable "remote.%s.pushurl" + :multi-value t + :history-key 'magit-remote..*url + :seturl-arg "--push") + +(define-infix-command magit-remote..push () + :class 'magit--git-variable + :scope 'magit--read-remote-scope + :variable "remote.%s.push") + +(define-infix-command magit-remote..tagopt () + :class 'magit--git-variable:choices + :scope 'magit--read-remote-scope + :variable "remote.%s.tagOpt" + :choices '("--no-tags" "--tags")) + +;;; Transfer Utilities + +(defun magit--push-remote-variable (&optional branch short) + (unless branch + (setq branch (magit-get-current-branch))) + (magit--propertize-face + (if (or (not branch) magit-prefer-push-default) + (if short "pushDefault" "remote.pushDefault") + (if short "pushRemote" (format "branch.%s.pushRemote" branch))) + 'bold)) + +(defun magit--select-push-remote (prompt-suffix) + (let* ((branch (or (magit-get-current-branch) + (user-error "No branch is checked out"))) + (remote (magit-get-push-remote branch))) + (when (or current-prefix-arg + (not remote) + (not (member remote (magit-list-remotes)))) + (setq remote + (magit-read-remote (format "Set %s and %s" + (magit--push-remote-variable) + prompt-suffix))) + (setf (magit-get (magit--push-remote-variable branch)) remote)) + (list branch remote))) + +;;; _ +(provide 'magit-remote) +;;; magit-remote.el ends here diff --git a/elpa/magit-20191122.2040/magit-remote.elc b/elpa/magit-20191122.2040/magit-remote.elc new file mode 100644 index 0000000000000000000000000000000000000000..5610244a1f0cc658a914b2602973e44b260dbfd4 GIT binary patch literal 14859 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 literal 0 HcmV?d00001 diff --git a/elpa/magit-20191122.2040/magit-repos.el b/elpa/magit-20191122.2040/magit-repos.el new file mode 100644 index 00000000..c51a956d --- /dev/null +++ b/elpa/magit-20191122.2040/magit-repos.el @@ -0,0 +1,339 @@ +;;; magit-repos.el --- listing repositories -*- lexical-binding: t -*- + +;; Copyright (C) 2010-2019 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; This library implements support for listing repositories. This +;; includes getting a Lisp list of known repositories as well as a +;; mode for listing repositories in a buffer. + +;;; Code: + +(eval-when-compile + (require 'subr-x)) + +(require 'magit-core) + +(declare-function magit-status-setup-buffer "magit-status" (directory)) + +(defvar x-stretch-cursor) + +;;; Options + +(defcustom magit-repository-directories nil + "List of directories that are or contain Git repositories. + +Each element has the form (DIRECTORY . DEPTH). DIRECTORY has +to be a directory or a directory file-name, a string. DEPTH, +an integer, specifies the maximum depth to look for Git +repositories. If it is 0, then only add DIRECTORY itself. + +This option controls which repositories are being listed by +`magit-list-repositories'. It also affects `magit-status' +\(which see) in potentially surprising ways." + :package-version '(magit . "2.91.0") + :group 'magit-essentials + :type '(repeat (cons directory (integer :tag "Depth")))) + +(defgroup magit-repolist nil + "List repositories in a buffer." + :link '(info-link "(magit)Repository List") + :group 'magit-modes) + +(defcustom magit-repolist-mode-hook '(hl-line-mode) + "Hook run after entering Magit-Repolist mode." + :package-version '(magit . "2.9.0") + :group 'magit-repolist + :type 'hook + :get 'magit-hook-custom-get + :options '(hl-line-mode)) + +(defcustom magit-repolist-columns + '(("Name" 25 magit-repolist-column-ident nil) + ("Version" 25 magit-repolist-column-version nil) + ("BU" 3 magit-repolist-column-unpushed-to-upstream + ((:right-align t) + (:help-echo "Local changes not in upstream"))) + ("Path" 99 magit-repolist-column-path nil)) + "List of columns displayed by `magit-list-repositories'. + +Each element has the form (HEADER WIDTH FORMAT PROPS). + +HEADER is the string displayed in the header. WIDTH is the width +of the column. FORMAT is a function that is called with one +argument, the repository identification (usually its basename), +and with `default-directory' bound to the toplevel of its working +tree. It has to return a string to be inserted or nil. PROPS is +an alist that supports the keys `:right-align' and `:pad-right'. +Some entries also use `:help-echo', but `tabulated-list' does not +actually support that yet." + :package-version '(magit . "2.12.0") + :group 'magit-repolist + :type `(repeat (list :tag "Column" + (string :tag "Header Label") + (integer :tag "Column Width") + (function :tag "Inserter Function") + (repeat :tag "Properties" + (list (choice :tag "Property" + (const :right-align) + (const :pad-right) + (symbol)) + (sexp :tag "Value")))))) + +(defcustom magit-repolist-column-flag-alist + '((magit-untracked-files . "N") + (magit-unstaged-files . "U") + (magit-staged-files . "S")) + "Association list of predicates and flags for `magit-repolist-column-flag'. + +Each element is of the form (FUNCTION . FLAG). Each FUNCTION is +called with no arguments, with `default-directory' bound to the +top level of a repository working tree, until one of them returns +a non-nil value. FLAG corresponding to that function is returned +as the value of `magit-repolist-column-flag'." + :package-version '(magit . "2.91.0") + :group 'magit-repolist + :type '(alist :key-type (function :tag "Predicate Function") + :value-type (string :tag "Flag"))) + +;;; List Repositories +;;;; Command +;;;###autoload +(defun magit-list-repositories () + "Display a list of repositories. + +Use the options `magit-repository-directories' to control which +repositories are displayed." + (interactive) + (if magit-repository-directories + (with-current-buffer (get-buffer-create "*Magit Repositories*") + (magit-repolist-mode) + (magit-repolist-refresh) + (tabulated-list-print) + (switch-to-buffer (current-buffer))) + (message "You need to customize `magit-repository-directories' %s" + "before you can list repositories"))) + +;;;; Mode + +(defvar magit-repolist-mode-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map tabulated-list-mode-map) + (define-key map (if (featurep 'jkl) [return] (kbd "C-m")) + 'magit-repolist-status) + map) + "Local keymap for Magit-Repolist mode buffers.") + +(defun magit-repolist-status (&optional _button) + "Show the status for the repository at point." + (interactive) + (--if-let (tabulated-list-get-id) + (magit-status-setup-buffer (expand-file-name it)) + (user-error "There is no repository at point"))) + +(define-derived-mode magit-repolist-mode tabulated-list-mode "Repos" + "Major mode for browsing a list of Git repositories." + (setq-local x-stretch-cursor nil) + (setq tabulated-list-padding 0) + (setq tabulated-list-sort-key (cons "Path" nil)) + (setq tabulated-list-format + (vconcat (mapcar (pcase-lambda (`(,title ,width ,_fn ,props)) + (nconc (list title width t) + (-flatten props))) + magit-repolist-columns))) + (tabulated-list-init-header) + (add-hook 'tabulated-list-revert-hook 'magit-repolist-refresh nil t) + (setq imenu-prev-index-position-function + 'magit-imenu--repolist-prev-index-position-function) + (setq imenu-extract-index-name-function + 'magit-imenu--repolist-extract-index-name-function)) + +(defun magit-repolist-refresh () + (setq tabulated-list-entries + (mapcar (pcase-lambda (`(,id . ,path)) + (let ((default-directory path)) + (list path + (vconcat (--map (or (funcall (nth 2 it) id) "") + magit-repolist-columns))))) + (magit-list-repos-uniquify + (--map (cons (file-name-nondirectory (directory-file-name it)) + it) + (magit-list-repos)))))) + +;;;; Columns + +(defun magit-repolist-column-ident (id) + "Insert the identification of the repository. +Usually this is just its basename." + id) + +(defun magit-repolist-column-path (_id) + "Insert the absolute path of the repository." + (abbreviate-file-name default-directory)) + +(defun magit-repolist-column-version (_id) + "Insert a description of the repository's `HEAD' revision." + (when-let ((v (or (magit-git-string "describe" "--tags" "--dirty") + ;; If there are no tags, use the date in MELPA format. + (magit-git-string "show" "--no-patch" "--format=%cd-g%h" + "--date=format:%Y%m%d.%H%M")))) + (save-match-data + (when (string-match "-dirty\\'" v) + (magit--put-face (1+ (match-beginning 0)) (length v) 'error v)) + (if (and v (string-match "\\`[0-9]" v)) + (concat " " v) + v)))) + +(defun magit-repolist-column-branch (_id) + "Insert the current branch." + (magit-get-current-branch)) + +(defun magit-repolist-column-upstream (_id) + "Insert the upstream branch of the current branch." + (magit-get-upstream-branch)) + +(defun magit-repolist-column-flag (_id) + "Insert a flag as specified by `magit-repolist-column-flag-alist'. + +By default this indicates whether there are uncommitted changes. +- N if there is at least one untracked file. +- U if there is at least one unstaged file. +- S if there is at least one staged file. +Only one letter is shown, the first that applies." + (-some (pcase-lambda (`(,fun . ,flag)) + (and (funcall fun) flag)) + magit-repolist-column-flag-alist)) + +(defun magit-repolist-column-unpulled-from-upstream (_id) + "Insert number of upstream commits not in the current branch." + (--when-let (magit-get-upstream-branch) + (let ((n (cadr (magit-rev-diff-count "HEAD" it)))) + (magit--propertize-face + (number-to-string n) (if (> n 0) 'bold 'shadow))))) + +(defun magit-repolist-column-unpulled-from-pushremote (_id) + "Insert number of commits in the push branch but not the current branch." + (--when-let (magit-get-push-branch nil t) + (let ((n (cadr (magit-rev-diff-count "HEAD" it)))) + (magit--propertize-face + (number-to-string n) (if (> n 0) 'bold 'shadow))))) + +(defun magit-repolist-column-unpushed-to-upstream (_id) + "Insert number of commits in the current branch but not its upstream." + (--when-let (magit-get-upstream-branch) + (let ((n (car (magit-rev-diff-count "HEAD" it)))) + (magit--propertize-face + (number-to-string n) (if (> n 0) 'bold 'shadow))))) + +(defun magit-repolist-column-unpushed-to-pushremote (_id) + "Insert number of commits in the current branch but not its push branch." + (--when-let (magit-get-push-branch nil t) + (let ((n (car (magit-rev-diff-count "HEAD" it)))) + (magit--propertize-face + (number-to-string n) (if (> n 0) 'bold 'shadow))))) + +(defun magit-repolist-column-branches (_id) + "Insert number of branches." + (let ((n (length (magit-list-local-branches)))) + (magit--propertize-face (number-to-string n) (if (> n 1) 'bold 'shadow)))) + +(defun magit-repolist-column-stashes (_id) + "Insert number of stashes." + (let ((n (length (magit-list-stashes)))) + (magit--propertize-face (number-to-string n) (if (> n 0) 'bold 'shadow)))) + +;;; Read Repository + +(defun magit-read-repository (&optional read-directory-name) + "Read a Git repository in the minibuffer, with completion. + +The completion choices are the basenames of top-levels of +repositories found in the directories specified by option +`magit-repository-directories'. In case of name conflicts +the basenames are prefixed with the name of the respective +parent directories. The returned value is the actual path +to the selected repository. + +If READ-DIRECTORY-NAME is non-nil or no repositories can be +found based on the value of `magit-repository-directories', +then read an arbitrary directory using `read-directory-name' +instead." + (if-let ((repos (and (not read-directory-name) + magit-repository-directories + (magit-repos-alist)))) + (let ((reply (magit-completing-read "Git repository" repos))) + (file-name-as-directory + (or (cdr (assoc reply repos)) + (if (file-directory-p reply) + (expand-file-name reply) + (user-error "Not a repository or a directory: %s" reply))))) + (file-name-as-directory + (read-directory-name "Git repository: " + (or (magit-toplevel) default-directory))))) + +(defun magit-list-repos () + (cl-mapcan (pcase-lambda (`(,dir . ,depth)) + (magit-list-repos-1 dir depth)) + magit-repository-directories)) + +(defun magit-list-repos-1 (directory depth) + (cond ((file-readable-p (expand-file-name ".git" directory)) + (list (file-name-as-directory directory))) + ((and (> depth 0) (magit-file-accessible-directory-p directory)) + (--mapcat (and (file-directory-p it) + (magit-list-repos-1 it (1- depth))) + (directory-files directory t + directory-files-no-dot-files-regexp t))))) + +(defun magit-list-repos-uniquify (alist) + (let (result (dict (make-hash-table :test 'equal))) + (dolist (a (delete-dups alist)) + (puthash (car a) (cons (cdr a) (gethash (car a) dict)) dict)) + (maphash + (lambda (key value) + (if (= (length value) 1) + (push (cons key (car value)) result) + (setq result + (append result + (magit-list-repos-uniquify + (--map (cons (concat + key "\\" + (file-name-nondirectory + (directory-file-name + (substring it 0 (- (1+ (length key))))))) + it) + value)))))) + dict) + result)) + +(defun magit-repos-alist () + (magit-list-repos-uniquify + (--map (cons (file-name-nondirectory (directory-file-name it)) it) + (magit-list-repos)))) + +;;; _ +(provide 'magit-repos) +;;; magit-repos.el ends here diff --git a/elpa/magit-20191122.2040/magit-repos.elc b/elpa/magit-20191122.2040/magit-repos.elc new file mode 100644 index 0000000000000000000000000000000000000000..52d30892b8f3bc5114ef67f4bfec18f26fb1842c GIT binary patch literal 14542 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 literal 0 HcmV?d00001 diff --git a/elpa/magit-20191122.2040/magit-reset.el b/elpa/magit-20191122.2040/magit-reset.el new file mode 100644 index 00000000..e16e9b20 --- /dev/null +++ b/elpa/magit-20191122.2040/magit-reset.el @@ -0,0 +1,127 @@ +;;; magit-reset.el --- reset fuctionality -*- lexical-binding: t -*- + +;; Copyright (C) 2010-2019 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; This library implements reset commands. + +;;; Code: + +(require 'magit) + +;;;###autoload (autoload 'magit-reset "magit" nil t) +(define-transient-command magit-reset () + "Reset the `HEAD', index and/or worktree to a previous state." + :man-page "git-reset" + ["Reset" + ("m" "mixed (HEAD and index)" magit-reset-mixed) + ("s" "soft (HEAD only)" magit-reset-soft) + ("h" "hard (HEAD, index and files)" magit-reset-hard) + ("i" "index (only)" magit-reset-index) + ("w" "worktree (only)" magit-reset-worktree) + "" + ("f" "a file" magit-file-checkout)]) + +;;;###autoload +(defun magit-reset-mixed (commit) + "Reset the `HEAD' and index to COMMIT, but not the working tree. +\n(git reset --mixed COMMIT)" + (interactive (list (magit-reset-read-branch-or-commit "Reset %s to"))) + (magit-reset-internal "--mixed" commit)) + +;;;###autoload +(defun magit-reset-soft (commit) + "Reset the `HEAD' to COMMIT, but not the index and working tree. +\n(git reset --soft REVISION)" + (interactive (list (magit-reset-read-branch-or-commit "Soft reset %s to"))) + (magit-reset-internal "--soft" commit)) + +;;;###autoload +(defun magit-reset-hard (commit) + "Reset the `HEAD', index, and working tree to COMMIT. +\n(git reset --hard REVISION)" + (interactive (list (magit-reset-read-branch-or-commit + (concat (magit--propertize-face "Hard" 'bold) + " reset %s to")))) + (magit-reset-internal "--hard" commit)) + +;;;###autoload +(defun magit-reset-index (commit) + "Reset the index to COMMIT. +Keep the `HEAD' and working tree as-is, so if COMMIT refers to the +head this effectively unstages all changes. +\n(git reset COMMIT .)" + (interactive (list (magit-read-branch-or-commit "Reset index to"))) + (magit-reset-internal nil commit ".")) + +;;;###autoload +(defun magit-reset-worktree (commit) + "Reset the worktree to COMMIT. +Keep the `HEAD' and index as-is." + (interactive (list (magit-read-branch-or-commit "Reset worktree to"))) + (magit-wip-commit-before-change nil " before reset") + (magit-with-temp-index commit nil + (magit-call-git "checkout-index" "--all" "--force")) + (magit-wip-commit-after-apply nil " after reset") + (magit-refresh)) + +;;;###autoload +(defun magit-reset-quickly (commit &optional hard) + "Reset the `HEAD' and index to COMMIT, and possibly the working tree. +With a prefix argument reset the working tree otherwise don't. +\n(git reset --mixed|--hard COMMIT)" + (interactive (list (magit-reset-read-branch-or-commit + (if current-prefix-arg + (concat (magit--propertize-face "Hard" 'bold) + " reset %s to") + "Reset %s to")) + current-prefix-arg)) + (magit-reset-internal (if hard "--hard" "--mixed") commit)) + +(defun magit-reset-read-branch-or-commit (prompt) + "Prompt for and return a ref to reset HEAD to. + +PROMPT is a format string, where either the current branch name +or \"detached head\" will be substituted for %s." + (magit-read-branch-or-commit + (format prompt (or (magit-get-current-branch) "detached head")))) + +(defun magit-reset-internal (arg commit &optional path) + (when (and (not (member arg '("--hard" nil))) + (equal (magit-rev-parse commit) + (magit-rev-parse "HEAD~"))) + (with-temp-buffer + (magit-git-insert "show" "-s" "--format=%B" "HEAD") + (when git-commit-major-mode + (funcall git-commit-major-mode)) + (git-commit-setup-font-lock) + (git-commit-save-message))) + (let ((cmd (if (and (equal commit "HEAD") (not arg)) "unstage" "reset"))) + (magit-wip-commit-before-change nil (concat " before " cmd)) + (magit-run-git "reset" arg commit "--" path) + (when (equal cmd "unstage") + (magit-wip-commit-after-apply nil " after unstage")))) + +;;; _ +(provide 'magit-reset) +;;; magit-reset.el ends here diff --git a/elpa/magit-20191122.2040/magit-reset.elc b/elpa/magit-20191122.2040/magit-reset.elc new file mode 100644 index 0000000000000000000000000000000000000000..bcf61ab8884e7de7f04a5db2c1ec21110d617b59 GIT binary patch literal 5544 zcmb_g`)}LG5q2CT&8cYnW3TNGH>Tr83QQj#de{jLsN=Y?(aS|}jP?M_xKiZG;#nkh zBxT2kqJMk8nO#~>8xB$fvZ&?mymn^3Z};`#_XmGmTU)EWe*KybvSb{OR3ty*ln#?1 zEa*z*MVzJNwRe1Za~+pM3PvN!#$}wuzXl~<7dth1c{+>>8bAt73RO^alLko~Qj~>7 znaAlxv5mKRQBn{^DxzC0?%s~Kw|Knc_Ws9%<6{bkK^}x9 zOxzarK^jq!Q5dAuS2W6kIVHxGf>e-?VwF=l#6-{6dJ%#z`eOsW^siQ{)pPaBB+eDR zNP>&FY}D$J8U&*_D9nhRt3s8udFGJS^Bo5tccbSy9gEJ&JV=XJrKOE2lQD@1z2KZY zO5+iK&LOmaQz|>mA~h8PK^{K-X3uk3sz}Cn6Q9=NU>k#-o-Y$!eDlY9zA(%6G1|nS z7&o4jvj$=Fv2obF_)6JXI=Z2f29p%OvAsx`NdiA4xyU*Zm&>7|e;*z0zkRWd#gY0% z*za$%oUXI{vdopDGNXXTxw?w8NkIjcs~wA`QL*uE5PzB(F$1r{EJ-+fUg5tz4lWQE zL|=z)PQoa-$>2!+%$<=EW}``xQvFq=iZG8+7^oO+wbh_{eRgg!8L$cUSC{IBti+=E zMM?Y#g@M01d&(YaUmKWM89B49w#;up$=y1NMIA*pC|QNk!NI>vJWst}`fyP?YEm4~ z(r30x8bfiHCSG>Grg%}4P6GDhJ{M%x{gSU2CEsS$y^^b05N=ub?Z9ABeju^H==_#) z=d{D23NMjkjYi|VaZbC9+UDO}r%j7RFwG6l`-2bf-yffDQy@5Gn~%XE{uF1n0Jc+#4n- zm6OAN9)CRk@WTV+Bx^o9OuT9~N}cBJmq+O%SGwNvg;4D+CzL7GZAq-z+?nRrVirlQ ze`a`O&1Z*)SIvaSbDHhd;Q=rSj3F<9UER;fDV@N;h-|F#GX7QBgCGPD9ISDU`HIS6Tm;w!71iG{U;?P-}B_xxRF z_4X|7$34|u1#(*8o!R=X+V5<7t_roObdE6x=K-DWR`N6w!h(=dZSHqMdsS(s!FYuA;2RTM@FchMWTWSM4kx7NKF4YddLH4yMZfcdHGcZj0*))JX1eNTy&hF9R@%$V)i;2m39P9 z8lp4Su*BY3sq6rD!q#HEM>|E{)r9` zPscyJJ^b;fzaM{ph_yQYA=-=t&#E|z)*;&PPQDS~5c*9rKo#Z`aiqYd$5|0`3fS6| zrA-Y6I1$*vc#PI&k^Gw9O_N&Z$pJaWa*1?zMUI3^&i_76xH2*uD8=)`COhc_d41? zdE2;?&Eb?8Uc%nZvzF^?KKF>5$XA@z+?c#x%8%Y-uJoA#7dnAW#a|1ml1Kx3=QB3+p8JCk1Z`hoz3eU98 zyZ3r^kfz`!M}2g6hf&FCOA7cstGZUu(OfOWxTvRGsM4VOAbwV-Z|+k(2n)klubV{tnF*P;uR;)(_sl&WjHkBbZB ztwk>xHecQWi?GRYIB{B%MI3keiR-CFDAWQq{$3)*jRwA{GU)`{0Up3_vWj7bQ@UjX ztYEv&y6?8$;1}BpQ>T8)-4~{yX^gV)a_&`t%ccZaDK|WZK0}5SaRpirqZ!rge3EKR kwC!qWM!+gatJDI<90Oy`PP4_uP)EnQ0$9%7^)+h$1J{tG&Hw-a literal 0 HcmV?d00001 diff --git a/elpa/magit-20191122.2040/magit-section.el b/elpa/magit-20191122.2040/magit-section.el new file mode 100644 index 00000000..72ae432f --- /dev/null +++ b/elpa/magit-20191122.2040/magit-section.el @@ -0,0 +1,1666 @@ +;;; magit-section.el --- section functionality -*- lexical-binding: t -*- + +;; Copyright (C) 2010-2019 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; This library implements "sections" as used in all Magit buffers. +;; If you have used Magit before, then you probably know what that +;; means, otherwise think "read-only Org-Mode for Git", kinda. + +;;; Code: + +(require 'cl-lib) +(require 'dash) +(require 'eieio) + +(eval-when-compile + (require 'benchmark) + (require 'subr-x)) + +(require 'magit-utils) + +(declare-function magit-maybe-make-margin-overlay "magit-margin" ()) +(declare-function magit-repository-local-get "magit-mode" + (key &optional default repository)) +(declare-function magit-repository-local-set "magit-mode" + (key value &optional repository)) +(defvar magit-keep-region-overlay) +(defvar magit-refresh-verbose) + +;;; Options + +(defgroup magit-section nil + "Expandable sections." + :link '(info-link "(magit)Sections") + :group 'magit) + +(defcustom magit-section-show-child-count t + "Whether to append the number of children to section headings. +This only applies to sections for which doing so makes sense." + :package-version '(magit . "2.1.0") + :group 'magit-section + :type 'boolean) + +(defcustom magit-section-movement-hook + '(magit-hunk-set-window-start + magit-log-maybe-update-revision-buffer + magit-log-maybe-show-more-commits) + "Hook run by `magit-section-goto'. +That function in turn is used by all section movement commands." + :package-version '(magit . "2.3.0") + :group 'magit-section + :type 'hook + :options '(magit-hunk-set-window-start + magit-status-maybe-update-revision-buffer + magit-status-maybe-update-stash-buffer + magit-status-maybe-update-blob-buffer + magit-log-maybe-update-revision-buffer + magit-log-maybe-update-blob-buffer + magit-log-maybe-show-more-commits + magit-stashes-maybe-update-stash-buffer)) + +(defcustom magit-section-highlight-hook + '(magit-diff-highlight + magit-section-highlight + magit-section-highlight-selection) + "Functions used to highlight the current section. +Each function is run with the current section as only argument +until one of them returns non-nil." + :package-version '(magit . "2.1.0") + :group 'magit-section + :type 'hook + :options '(magit-diff-highlight + magit-section-highlight + magit-section-highlight-selection)) + +(defcustom magit-section-unhighlight-hook + '(magit-diff-unhighlight) + "Functions used to unhighlight the previously current section. +Each function is run with the current section as only argument +until one of them returns non-nil. Most sections are properly +unhighlighted without requiring a specialized unhighlighter, +diff-related sections being the only exception." + :package-version '(magit . "2.1.0") + :group 'magit-section + :type 'hook + :options '(magit-diff-unhighlight)) + +(defcustom magit-section-set-visibility-hook + '(magit-diff-expansion-threshold + magit-section-cached-visibility) + "Hook used to set the initial visibility of a section. +Stop at the first function that returns non-nil. The returned +value should be `show', `hide' or nil. If no function returns +non-nil, determine the visibility as usual, i.e. use the +hardcoded section specific default (see `magit-insert-section')." + :package-version '(magit . "2.4.0") + :group 'magit-section + :type 'hook + :options '(magit-diff-expansion-threshold + magit-section-cached-visibility)) + +(defcustom magit-section-cache-visibility t + "Whether to cache visibility of sections. + +Sections always retain their visibility state when they are being +recreated during a refresh. But if a section disappears and then +later reappears again, then this option controls whether this is +the case. + +If t, then cache the visibility of all sections. If a list of +section types, then only do so for matching sections. If nil, +then don't do so for any sections." + :package-version '(magit . "2.12.0") + :group 'magit-section + :type '(choice (const :tag "Don't cache visibility" nil) + (const :tag "Cache visibility of all sections" t) + (repeat :tag "Cache visibility for section types" symbol))) + +(defcustom magit-section-initial-visibility-alist + '((stashes . hide)) + "Alist controlling the initial visibility of sections. + +Each element maps a section type or lineage to the initial +visibility state for such sections. The state has to be one of +`show' or `hide', or a function that returns one of these symbols. +A function is called with the section as the only argument. + +Use the command `magit-describe-section' to determine a section's +lineage or type. The vector in the output is the section lineage +and the type is the first element of that vector. Wildcards can +be used, see `magit-section-match'. + +Currently this option is only used to override hardcoded defaults, +but in the future it will also be used set the defaults. + +An entry whose key is `magit-status-initial-section' specifies +the visibility of the section `magit-status-goto-initial-section' +jumps to. This does not only override defaults, but also other +entries of this alist." + :package-version '(magit . "2.12.0") + :group 'magit-section + :type '(alist :key-type (sexp :tag "Section type/lineage") + :value-type (choice (const hide) + (const show) + function))) + +(defcustom magit-section-visibility-indicator + (if (window-system) + '(magit-fringe-bitmap> . magit-fringe-bitmapv) + '("…" . t)) + "Whether and how to indicate that a section can be expanded/collapsed. + +If nil, then don't show any indicators. +Otherwise the value has to have one of these two forms: + +\(EXPANDABLE-BITMAP . COLLAPSIBLE-BITMAP) + + Both values have to be variables whose values are fringe + bitmaps. In this case every section that can be expanded or + collapsed gets an indicator in the left fringe. + + To provide extra padding around the indicator, set + `left-fringe-width' in `magit-mode-hook'. + +\(STRING . BOOLEAN) + + In this case STRING (usually an ellipsis) is shown at the end + of the heading of every collapsed section. Expanded sections + get no indicator. The cdr controls whether the appearance of + these ellipsis take section highlighting into account. Doing + so might potentially have an impact on performance, while not + doing so is kinda ugly." + :package-version '(magit . "2.91.0") + :group 'magit-section + :type '(choice (const :tag "No indicators" nil) + (cons :tag "Use +- fringe indicators" + (const magit-fringe-bitmap+) + (const magit-fringe-bitmap-)) + (cons :tag "Use >v fringe indicators" + (const magit-fringe-bitmap>) + (const magit-fringe-bitmapv)) + (cons :tag "Use bold >v fringe indicators)" + (const magit-fringe-bitmap-bold>) + (const magit-fringe-bitmap-boldv)) + (cons :tag "Use custom fringe indicators" + (variable :tag "Expandable bitmap variable") + (variable :tag "Collapsible bitmap variable")) + (cons :tag "Use ellipses at end of headings" + (string :tag "Ellipsis" "…") + (choice :tag "Use face kludge" + (const :tag "Yes (potentially slow)" t) + (const :tag "No (kinda ugly)" nil))))) + +(defface magit-section-highlight + `((((class color) (background light)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :background "grey95") + (((class color) (background dark)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :background "grey20")) + "Face for highlighting the current section." + :group 'magit-faces) + +(defface magit-section-heading + `((((class color) (background light)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "DarkGoldenrod4" + :weight bold) + (((class color) (background dark)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "LightGoldenrod2" + :weight bold)) + "Face for section headings." + :group 'magit-faces) + +(defface magit-section-secondary-heading + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :weight bold)) + "Face for section headings of some secondary headings." + :group 'magit-faces) + +(defface magit-section-heading-selection + `((((class color) (background light)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "salmon4") + (((class color) (background dark)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "LightSalmon3")) + "Face for selected section headings." + :group 'magit-faces) + +;;; Classes + +(defvar magit--current-section-hook nil + "Internal variable used for `magit-explain-section'.") + +(defvar magit--section-type-alist + '( + (file . magit-file-section) + (hunk . magit-hunk-section) + (module . magit-module-section) + )) + +(defclass magit-section () + ((keymap :initform nil :allocation :class) + (type :initform nil :initarg :type) + (value :initform nil :initarg :value) + (start :initform nil :initarg :start) + (content :initform nil) + (end :initform nil) + (hidden :initform nil) + (washer :initform nil) + (process :initform nil) + (heading-highlight-face :initform nil) + (inserter :initform (symbol-value 'magit--current-section-hook)) + (parent :initform nil :initarg :parent) + (children :initform nil))) + +(defclass magit-file-section (magit-section) + ((source :initform nil) + (header :initform nil))) + +(defclass magit-hunk-section (magit-section) + ((refined :initform nil) + (combined :initform nil) + (from-range :initform nil) + (from-ranges :initform nil) + (to-range :initform nil) + (about :initform nil))) + +(defclass magit-module-section (magit-file-section) + ()) + +;;; Core + +(defvar-local magit-root-section nil + "The root section in the current buffer. +All other sections are descendants of this section. The value +of this variable is set by `magit-insert-section' and you should +never modify it.") +(put 'magit-root-section 'permanent-local t) + +(defun magit-current-section () + "Return the section at point." + (or (get-text-property (point) 'magit-section) magit-root-section)) + +(defun magit-section-ident (section) + "Return an unique identifier for SECTION. +The return value has the form ((TYPE . VALUE)...)." + (with-slots (type value parent) section + (cons (cons type + (cond ((eieio-object-p value) + (magit-section-ident-value value)) + ((not (memq type '(unpulled unpushed))) value) + ((string-match-p "@{upstream}" value) value) + ;; Unfortunately Git chokes on "@{push}" when + ;; the value of `push.default' does not allow a + ;; 1:1 mapping. Arbitrary commands may consult + ;; the section value so we cannot use "@{push}". + ;; But `unpushed' and `unpulled' sections should + ;; keep their identity when switching branches + ;; so we have to use another value here. + ((string-match-p "\\`\\.\\." value) "..@{push}") + (t "@{push}.."))) + (and parent + (magit-section-ident parent))))) + +(cl-defgeneric magit-section-ident-value (VALUE) + "Return a constant representation of VALUE. +VALUE is the value of a `magit-section' object. If that is an +object itself, then that is not suitable to be used to identify +the section because two objects may represent the same thing but +not be equal. If possible a method should be added for such +objects, which returns a value that is equal. Otherwise the +catch-all method is used, which just returns the argument +itself.") + +(cl-defmethod magit-section-ident-value (arg) arg) + +(defun magit-get-section (ident &optional root) + "Return the section identified by IDENT. +IDENT has to be a list as returned by `magit-section-ident'." + (setq ident (reverse ident)) + (let ((section (or root magit-root-section))) + (when (eq (car (pop ident)) + (oref section type)) + (while (and ident + (pcase-let* ((`(,type . ,value) (car ident)) + (value (magit-section-ident-value value))) + (setq section + (cl-find-if (lambda (section) + (and (eq (oref section type) type) + (equal (magit-section-ident-value + (oref section value)) + value))) + (oref section children))))) + (pop ident)) + section))) + +(defun magit-section-lineage (section) + "Return the lineage of SECTION. +The return value has the form (TYPE...)." + (cons (oref section type) + (when-let ((parent (oref section parent))) + (magit-section-lineage parent)))) + +(defvar magit-insert-section--current nil "For internal use only.") +(defvar magit-insert-section--parent nil "For internal use only.") +(defvar magit-insert-section--oldroot nil "For internal use only.") + +;;; Commands +;;;; Movement + +(defun magit-section-forward () + "Move to the beginning of the next visible section." + (interactive) + (if (eobp) + (user-error "No next section") + (let ((section (magit-current-section))) + (if (oref section parent) + (let ((next (and (not (oref section hidden)) + (not (= (oref section end) + (1+ (point)))) + (car (oref section children))))) + (while (and section (not next)) + (unless (setq next (car (magit-section-siblings section 'next))) + (setq section (oref section parent)))) + (if next + (magit-section-goto next) + (user-error "No next section"))) + (magit-section-goto 1))))) + +(defun magit-section-backward () + "Move to the beginning of the current or the previous visible section. +When point is at the beginning of a section then move to the +beginning of the previous visible section. Otherwise move to +the beginning of the current section." + (interactive) + (if (bobp) + (user-error "No previous section") + (let ((section (magit-current-section)) children) + (cond + ((and (= (point) + (1- (oref section end))) + (setq children (oref section children))) + (magit-section-goto (car (last children)))) + ((and (oref section parent) + (not (= (point) + (oref section start)))) + (magit-section-goto section)) + (t + (let ((prev (car (magit-section-siblings section 'prev)))) + (if prev + (while (and (not (oref prev hidden)) + (setq children (oref prev children))) + (setq prev (car (last children)))) + (setq prev (oref section parent))) + (cond (prev + (magit-section-goto prev)) + ((oref section parent) + (user-error "No previous section")) + ;; Eob special cases. + ((not (get-text-property (1- (point)) 'invisible)) + (magit-section-goto -1)) + (t + (goto-char (previous-single-property-change + (1- (point)) 'invisible)) + (forward-line -1) + (magit-section-goto (magit-current-section)))))))))) + +(defun magit-section-up () + "Move to the beginning of the parent section." + (interactive) + (--if-let (oref (magit-current-section) parent) + (magit-section-goto it) + (user-error "No parent section"))) + +(defun magit-section-forward-sibling () + "Move to the beginning of the next sibling section. +If there is no next sibling section, then move to the parent." + (interactive) + (let ((current (magit-current-section))) + (if (oref current parent) + (--if-let (car (magit-section-siblings current 'next)) + (magit-section-goto it) + (magit-section-forward)) + (magit-section-goto 1)))) + +(defun magit-section-backward-sibling () + "Move to the beginning of the previous sibling section. +If there is no previous sibling section, then move to the parent." + (interactive) + (let ((current (magit-current-section))) + (if (oref current parent) + (--if-let (car (magit-section-siblings current 'prev)) + (magit-section-goto it) + (magit-section-backward)) + (magit-section-goto -1)))) + +(defun magit-section-goto (arg) + (if (integerp arg) + (progn (forward-line arg) + (setq arg (magit-current-section))) + (goto-char (oref arg start))) + (run-hook-with-args 'magit-section-movement-hook arg)) + +(defun magit-section-set-window-start (section) + "Ensure the beginning of SECTION is visible." + (unless (pos-visible-in-window-p (oref section end)) + (set-window-start (selected-window) (oref section start)))) + +(defun magit-hunk-set-window-start (section) + "When SECTION is a `hunk', ensure that its beginning is visible. +It the SECTION has a different type, then do nothing." + (when (magit-hunk-section-p section) + (magit-section-set-window-start section))) + +(defmacro magit-define-section-jumper (name heading type &optional value) + "Define an interactive function to go some section. +Together TYPE and VALUE identify the section. +HEADING is the displayed heading of the section." + (declare (indent defun)) + `(defun ,name (&optional expand) ,(format "\ +Jump to the section \"%s\". +With a prefix argument also expand it." heading) + (interactive "P") + (--if-let (magit-get-section + (cons (cons ',type ,value) + (magit-section-ident magit-root-section))) + (progn (goto-char (oref it start)) + (when expand + (with-local-quit (magit-section-show it)) + (recenter 0))) + (message ,(format "Section \"%s\" wasn't found" heading))))) + +;;;; Visibility + +(defun magit-section-show (section) + "Show the body of the current section." + (interactive (list (magit-current-section))) + (oset section hidden nil) + (magit-section--maybe-wash section) + (when-let ((beg (oref section content))) + (remove-overlays beg (oref section end) 'invisible t)) + (magit-section-maybe-update-visibility-indicator section) + (magit-section-maybe-cache-visibility section) + (dolist (child (oref section children)) + (if (oref child hidden) + (magit-section-hide child) + (magit-section-show child)))) + +(defun magit-section--maybe-wash (section) + (when-let ((washer (oref section washer))) + (oset section washer nil) + (let ((inhibit-read-only t) + (magit-insert-section--parent section) + (content (oref section content))) + (save-excursion + (if (and content (< content (oref section end))) + (funcall washer section) ; already partially washed (hunk) + (goto-char (oref section end)) + (oset section content (point-marker)) + (funcall washer) + (oset section end (point-marker))))) + (magit-section-update-highlight))) + +(defun magit-section-hide (section) + "Hide the body of the current section." + (interactive (list (magit-current-section))) + (if (eq section magit-root-section) + (user-error "Cannot hide root section") + (oset section hidden t) + (when-let ((beg (oref section content))) + (let ((end (oref section end))) + (remove-overlays beg end 'invisible t) + (let ((o (make-overlay beg end))) + (overlay-put o 'evaporate t) + (overlay-put o 'invisible t)))) + (magit-section-maybe-update-visibility-indicator section) + (magit-section-maybe-cache-visibility section))) + +(defun magit-section-toggle (section) + "Toggle visibility of the body of the current section." + (interactive (list (magit-current-section))) + (if (eq section magit-root-section) + (user-error "Cannot hide root section") + (goto-char (oref section start)) + (if (oref section hidden) + (magit-section-show section) + (magit-section-hide section)))) + +(defun magit-section-toggle-children (section) + "Toggle visibility of bodies of children of the current section." + (interactive (list (magit-current-section))) + (goto-char (oref section start)) + (let* ((children (oref section children)) + (show (--any-p (oref it hidden) children))) + (dolist (c children) + (oset c hidden show))) + (magit-section-show section)) + +(defun magit-section-show-children (section &optional depth) + "Recursively show the bodies of children of the current section. +With a prefix argument show children that deep and hide deeper +children." + (interactive (list (magit-current-section))) + (magit-section-show-children-1 section depth) + (magit-section-show section)) + +(defun magit-section-show-children-1 (section &optional depth) + (dolist (child (oref section children)) + (oset child hidden nil) + (if depth + (if (> depth 0) + (magit-section-show-children-1 child (1- depth)) + (magit-section-hide child)) + (magit-section-show-children-1 child)))) + +(defun magit-section-hide-children (section) + "Recursively hide the bodies of children of the current section." + (interactive (list (magit-current-section))) + (mapc 'magit-section-hide (oref section children))) + +(defun magit-section-show-headings (section) + "Recursively show headings of children of the current section. +Only show the headings, previously shown text-only bodies are +hidden." + (interactive (list (magit-current-section))) + (magit-section-show-headings-1 section) + (magit-section-show section)) + +(defun magit-section-show-headings-1 (section) + (dolist (child (oref section children)) + (oset child hidden nil) + (when (or (oref child children) + (not (oref child content))) + (magit-section-show-headings-1 child)))) + +(defun magit-section-cycle (section) + "Cycle visibility of current section and its children." + (interactive (list (magit-current-section))) + (goto-char (oref section start)) + (if (oref section hidden) + (progn (magit-section-show section) + (magit-section-hide-children section)) + (let ((children (oref section children))) + (cond ((and (--any-p (oref it hidden) children) + (--any-p (oref it children) children)) + (magit-section-show-headings section)) + ((-any-p 'magit-section-hidden-body children) + (magit-section-show-children section)) + (t + (magit-section-hide section)))))) + +(defun magit-section-cycle-global () + "Cycle visibility of all sections in the current buffer." + (interactive) + (let ((children (oref magit-root-section children))) + (cond ((and (--any-p (oref it hidden) children) + (--any-p (oref it children) children)) + (magit-section-show-headings magit-root-section)) + ((-any-p 'magit-section-hidden-body children) + (magit-section-show-children magit-root-section)) + (t + (mapc 'magit-section-hide children))))) + +(defun magit-section-cycle-diffs () + "Cycle visibility of diff-related sections in the current buffer." + (interactive) + (when-let ((sections + (cond ((derived-mode-p 'magit-status-mode) + (--mapcat + (when it + (when (oref it hidden) + (magit-section-show it)) + (oref it children)) + (list (magit-get-section '((staged) (status))) + (magit-get-section '((unstaged) (status)))))) + ((derived-mode-p 'magit-diff-mode) + (-filter #'magit-file-section-p + (oref magit-root-section children)))))) + (if (--any-p (oref it hidden) sections) + (dolist (s sections) + (magit-section-show s) + (magit-section-hide-children s)) + (let ((children (--mapcat (oref it children) sections))) + (cond ((and (--any-p (oref it hidden) children) + (--any-p (oref it children) children)) + (mapc 'magit-section-show-headings sections)) + ((-any-p 'magit-section-hidden-body children) + (mapc 'magit-section-show-children sections)) + (t + (mapc 'magit-section-hide sections))))))) + +(defun magit-section-hidden-body (section &optional pred) + (--if-let (oref section children) + (funcall (or pred '-any-p) 'magit-section-hidden-body it) + (and (oref section content) + (oref section hidden)))) + +(defun magit-section-invisible-p (section) + "Return t if the SECTION's body is invisible. +When the body of an ancestor of SECTION is collapsed then +SECTION's body (and heading) obviously cannot be visible." + (or (oref section hidden) + (--when-let (oref section parent) + (magit-section-invisible-p it)))) + +(defun magit-section-show-level (level) + "Show surrounding sections up to LEVEL. +If LEVEL is negative, show up to the absolute value. +Sections at higher levels are hidden." + (if (< level 0) + (let ((s (magit-current-section))) + (setq level (- level)) + (while (> (1- (length (magit-section-ident s))) level) + (setq s (oref s parent)) + (goto-char (oref s start))) + (magit-section-show-children magit-root-section (1- level))) + (cl-do* ((s (magit-current-section) + (oref s parent)) + (i (1- (length (magit-section-ident s))) + (cl-decf i))) + ((cond ((< i level) (magit-section-show-children s (- level i 1)) t) + ((= i level) (magit-section-hide s) t)) + (magit-section-goto s))))) + +(defun magit-section-show-level-1 () + "Show surrounding sections on first level." + (interactive) + (magit-section-show-level 1)) + +(defun magit-section-show-level-1-all () + "Show all sections on first level." + (interactive) + (magit-section-show-level -1)) + +(defun magit-section-show-level-2 () + "Show surrounding sections up to second level." + (interactive) + (magit-section-show-level 2)) + +(defun magit-section-show-level-2-all () + "Show all sections up to second level." + (interactive) + (magit-section-show-level -2)) + +(defun magit-section-show-level-3 () + "Show surrounding sections up to third level." + (interactive) + (magit-section-show-level 3)) + +(defun magit-section-show-level-3-all () + "Show all sections up to third level." + (interactive) + (magit-section-show-level -3)) + +(defun magit-section-show-level-4 () + "Show surrounding sections up to fourth level." + (interactive) + (magit-section-show-level 4)) + +(defun magit-section-show-level-4-all () + "Show all sections up to fourth level." + (interactive) + (magit-section-show-level -4)) + +;;;; Auxiliary + +(defun magit-describe-section-briefly (section &optional ident) + "Show information about the section at point. +With a prefix argument show the section identity instead of the +section lineage. This command is intended for debugging purposes." + (interactive (list (magit-current-section) current-prefix-arg)) + (let ((str (format "#<%s %S %S %s-%s>" + (eieio-object-class section) + (let ((val (oref section value))) + (cond ((stringp val) + (substring-no-properties val)) + ((and (eieio-object-p val) + (fboundp 'cl-prin1-to-string)) + (cl-prin1-to-string val)) + (t + val))) + (if ident + (magit-section-ident section) + (apply #'vector (magit-section-lineage section))) + (when-let ((m (oref section start))) + (marker-position m)) + (when-let ((m (oref section end))) + (marker-position m))))) + (if (called-interactively-p 'any) + (message "%s" str) + str))) + +(cl-defmethod cl-print-object ((section magit-section) stream) + "Print `magit-describe-section' result of SECTION." + ;; Used by debug and edebug as of Emacs 26. + (princ (magit-describe-section-briefly section) stream)) + +(defun magit-describe-section (section &optional interactive-p) + "Show information about the section at point." + (interactive (list (magit-current-section) t)) + (let ((inserter-section section)) + (while (and inserter-section (not (oref inserter-section inserter))) + (setq inserter-section (oref inserter-section parent))) + (when (and inserter-section (oref inserter-section inserter)) + (setq section inserter-section))) + (pcase (oref section inserter) + (`((,hook ,fun) . ,src-src) + (help-setup-xref `(magit-describe-section ,section) interactive-p) + (with-help-window (help-buffer) + (with-current-buffer standard-output + (insert (format-message + "%s\n is inserted by `%s'\n from `%s'" + (magit-describe-section-briefly section) + (make-text-button (symbol-name fun) nil + :type 'help-function + 'help-args (list fun)) + (make-text-button (symbol-name hook) nil + :type 'help-variable + 'help-args (list hook)))) + (pcase-dolist (`(,hook ,fun) src-src) + (insert (format-message + ",\n called by `%s'\n from `%s'" + (make-text-button (symbol-name fun) nil + :type 'help-function + 'help-args (list fun)) + (make-text-button (symbol-name hook) nil + :type 'help-variable + 'help-args (list hook))))) + (insert ".\n\n") + (insert + (format-message + "`%s' is " + (make-text-button (symbol-name fun) nil + :type 'help-function 'help-args (list fun)))) + (describe-function-1 fun)))) + (_ (message "%s, inserter unknown" + (magit-describe-section-briefly section))))) + +;;; Match + +(cl-defun magit-section-match + (condition &optional (section (magit-current-section))) + "Return t if SECTION matches CONDITION. + +SECTION defaults to the section at point. If SECTION is not +specified and there also is no section at point, then return +nil. + +CONDITION can take the following forms: + (CONDITION...) matches if any of the CONDITIONs matches. + [CLASS...] matches if the section's class is the same + as the first CLASS or a subclass of that; + the section's parent class matches the + second CLASS; and so on. + [* CLASS...] matches sections that match [CLASS...] and + also recursively all their child sections. + CLASS matches if the section's class is the same + as CLASS or a subclass of that; regardless + of the classes of the parent sections. + +Each CLASS should be a class symbol, identifying a class that +derives from `magit-section'. For backward compatibility CLASS +can also be a \"type symbol\". A section matches such a symbol +if the value of its `type' slot is `eq'. If a type symbol has +an entry in `magit--section-type-alist', then a section also +matches that type if its class is a subclass of the class that +corresponds to the type as per that alist. + +Note that it is not necessary to specify the complete section +lineage as printed by `magit-describe-section-briefly', unless +of course you want to be that precise." + (and section (magit-section-match-1 condition section))) + +(defun magit-section-match-1 (condition section) + (cl-assert condition) + (and section + (if (listp condition) + (--first (magit-section-match-1 it section) condition) + (magit-section-match-2 (if (symbolp condition) + (list condition) + (cl-coerce condition 'list)) + section)))) + +(defun magit-section-match-2 (condition section) + (if (eq (car condition) '*) + (or (magit-section-match-2 (cdr condition) section) + (when-let ((parent (oref section parent))) + (magit-section-match-2 condition parent))) + (and (let ((c (car condition))) + (if (class-p c) + (cl-typep section c) + (if-let ((class (cdr (assq c magit--section-type-alist)))) + (cl-typep section class) + (eq (oref section type) c)))) + (or (not (setq condition (cdr condition))) + (when-let ((parent (oref section parent))) + (magit-section-match-2 condition parent)))))) + +(defun magit-section-value-if (condition &optional section) + "If the section at point matches CONDITION, then return its value. + +If optional SECTION is non-nil then test whether that matches +instead. If there is no section at point and SECTION is nil, +then return nil. If the section does not match, then return +nil. + +See `magit-section-match' for the forms CONDITION can take." + (when-let ((section (or section (magit-current-section)))) + (and (magit-section-match condition section) + (oref section value)))) + +(defmacro magit-section-when (condition &rest body) + "If the section at point matches CONDITION, evaluate BODY. + +If the section matches, then evaluate BODY forms sequentially +with `it' bound to the section and return the value of the last +form. If there are no BODY forms, then return the value of the +section. If the section does not match or if there is no section +at point, then return nil. + +See `magit-section-match' for the forms CONDITION can take." + (declare (obsolete + "instead use `magit-section-match' or `magit-section-value-if'." + "Magit 2.90.0") + (indent 1) + (debug (sexp body))) + `(--when-let (magit-current-section) + ;; Quoting CONDITION here often leads to double-quotes, which + ;; isn't an issue because `magit-section-match-1' implicitly + ;; deals with that. We shouldn't force users of this function + ;; to not quote CONDITION because that would needlessly break + ;; backward compatibility. + (when (magit-section-match ',condition it) + ,@(or body '((oref it value)))))) + +(defmacro magit-section-case (&rest clauses) + "Choose among clauses on the type of the section at point. + +Each clause looks like (CONDITION BODY...). The type of the +section is compared against each CONDITION; the BODY forms of the +first match are evaluated sequentially and the value of the last +form is returned. Inside BODY the symbol `it' is bound to the +section at point. If no clause succeeds or if there is no +section at point, return nil. + +See `magit-section-match' for the forms CONDITION can take. +Additionally a CONDITION of t is allowed in the final clause, and +matches if no other CONDITION match, even if there is no section +at point." + (declare (indent 0) + (debug (&rest (sexp body)))) + `(let* ((it (magit-current-section))) + (cond ,@(mapcar (lambda (clause) + `(,(or (eq (car clause) t) + `(and it + (magit-section-match-1 ',(car clause) it))) + ,@(cdr clause))) + clauses)))) + +(defun magit-section-match-assoc (section alist) + "Return the value associated with SECTION's type or lineage in ALIST." + (-some (pcase-lambda (`(,key . ,val)) + (and (magit-section-match-1 key section) val)) + alist)) + +;;; Create + +(defvar magit-insert-section-hook nil + "Hook run after `magit-insert-section's BODY. +Avoid using this hook and only ever do so if you know +what you are doing and are sure there is no other way.") + +(defmacro magit-insert-section (&rest args) + "Insert a section at point. + +TYPE is the section type, a symbol. Many commands that act on +the current section behave differently depending on that type. +Also if a variable `magit-TYPE-section-map' exists, then use +that as the text-property `keymap' of all text belonging to the +section (but this may be overwritten in subsections). TYPE can +also have the form `(eval FORM)' in which case FORM is evaluated +at runtime. + +Optional VALUE is the value of the section, usually a string +that is required when acting on the section. + +When optional HIDE is non-nil collapse the section body by +default, i.e. when first creating the section, but not when +refreshing the buffer. Else expand it by default. This can be +overwritten using `magit-section-set-visibility-hook'. When a +section is recreated during a refresh, then the visibility of +predecessor is inherited and HIDE is ignored (but the hook is +still honored). + +BODY is any number of forms that actually insert the section's +heading and body. Optional NAME, if specified, has to be a +symbol, which is then bound to the struct of the section being +inserted. + +Before BODY is evaluated the `start' of the section object is set +to the value of `point' and after BODY was evaluated its `end' is +set to the new value of `point'; BODY is responsible for moving +`point' forward. + +If it turns out inside BODY that the section is empty, then +`magit-cancel-section' can be used to abort and remove all traces +of the partially inserted section. This can happen when creating +a section by washing Git's output and Git didn't actually output +anything this time around. + +\(fn [NAME] (TYPE &optional VALUE HIDE) &rest BODY)" + (declare (indent defun) + (debug ([&optional symbolp] + (&or [("eval" symbolp) &optional form form] + [symbolp &optional form form]) + body))) + (let ((tp (cl-gensym "type")) + (s* (and (symbolp (car args)) + (pop args))) + (s (cl-gensym "section"))) + `(let* ((,tp ,(let ((type (nth 0 (car args)))) + (if (eq (car-safe type) 'eval) + (cadr type) + `',type))) + (,s (funcall (if (class-p ,tp) + ,tp + (or (cdr (assq ,tp magit--section-type-alist)) + 'magit-section)) + :type + (if (class-p ,tp) + (or (car (rassq ,tp magit--section-type-alist)) + (error "BUG: No entry for %s in %s" ,tp + 'magit--section-type-alist)) + ,tp) + :value ,(nth 1 (car args)) + :start (point-marker) + :parent magit-insert-section--parent))) + (oset ,s hidden + (if-let ((value (run-hook-with-args-until-success + 'magit-section-set-visibility-hook ,s))) + (eq value 'hide) + (if-let ((incarnation (and magit-insert-section--oldroot + (magit-get-section + (magit-section-ident ,s) + magit-insert-section--oldroot)))) + (oref incarnation hidden) + (if-let ((value (magit-section-match-assoc + ,s magit-section-initial-visibility-alist))) + (progn + (when (functionp value) + (setq value (funcall value ,s))) + (eq value 'hide)) + ,(nth 2 (car args)))))) + (let ((magit-insert-section--current ,s) + (magit-insert-section--parent ,s) + (magit-insert-section--oldroot + (or magit-insert-section--oldroot + (unless magit-insert-section--parent + (prog1 magit-root-section + (setq magit-root-section ,s)))))) + (catch 'cancel-section + ,@(if s* + `((let ((,s* ,s)) + ,@(cdr args))) + (cdr args)) + ;; `magit-insert-section-hook' should *not* be run with + ;; `magit-run-section-hook' because it's a hook that runs + ;; on section insertion, not a section inserting hook. + (run-hooks 'magit-insert-section-hook) + (magit-insert-child-count ,s) + (set-marker-insertion-type (oref ,s start) t) + (let* ((end (oset ,s end (point-marker))) + (class-map (oref-default ,s keymap)) + (magit-map (intern (format "magit-%s-section-map" + (oref ,s type)))) + (forge-map (intern (format "forge-%s-section-map" + (oref ,s type)))) + (map (or (and class-map (symbol-value class-map)) + (and (boundp magit-map) (symbol-value magit-map)) + (and (boundp forge-map) (symbol-value forge-map))))) + (save-excursion + (goto-char (oref ,s start)) + (while (< (point) end) + (let ((next (or (next-single-property-change + (point) 'magit-section) + end))) + (unless (get-text-property (point) 'magit-section) + (put-text-property (point) next 'magit-section ,s) + (when map + (put-text-property (point) next 'keymap map))) + (goto-char next))))) + (if (eq ,s magit-root-section) + (let ((magit-section-cache-visibility nil)) + (magit-section-show ,s)) + (oset (oref ,s parent) children + (nconc (oref (oref ,s parent) children) + (list ,s))))) + ,s)))) + +(defun magit-cancel-section () + (when magit-insert-section--current + (if (not (oref magit-insert-section--current parent)) + (insert "(empty)\n") + (delete-region (oref magit-insert-section--current start) + (point)) + (setq magit-insert-section--current nil) + (throw 'cancel-section nil)))) + +(defun magit-insert-heading (&rest args) + "Insert the heading for the section currently being inserted. + +This function should only be used inside `magit-insert-section'. + +When called without any arguments, then just set the `content' +slot of the object representing the section being inserted to +a marker at `point'. The section should only contain a single +line when this function is used like this. + +When called with arguments ARGS, which have to be strings, or +nil, then insert those strings at point. The section should not +contain any text before this happens and afterwards it should +again only contain a single line. If the `face' property is set +anywhere inside any of these strings, then insert all of them +unchanged. Otherwise use the `magit-section-heading' face for +all inserted text. + +The `content' property of the section struct is the end of the +heading (which lasts from `start' to `content') and the beginning +of the the body (which lasts from `content' to `end'). If the +value of `content' is nil, then the section has no heading and +its body cannot be collapsed. If a section does have a heading, +then its height must be exactly one line, including a trailing +newline character. This isn't enforced, you are responsible for +getting it right. The only exception is that this function does +insert a newline character if necessary." + (declare (indent defun)) + (when args + (let ((heading (apply #'concat args))) + (insert (if (or (text-property-not-all 0 (length heading) + 'font-lock-face nil heading) + (text-property-not-all 0 (length heading) + 'face nil heading)) + heading + (propertize heading 'font-lock-face 'magit-section-heading))))) + (unless (bolp) + (insert ?\n)) + (magit-maybe-make-margin-overlay) + (oset magit-insert-section--current content (point-marker))) + +(defmacro magit-insert-section-body (&rest body) + "Use BODY to insert the section body, once the section is expanded. +If the section is expanded when it is created, then this is +like `progn'. Otherwise BODY isn't evaluated until the section +is explicitly expanded." + (declare (indent 0)) + (let ((f (cl-gensym)) + (s (cl-gensym))) + `(let ((,f (lambda () ,@body)) + (,s magit-insert-section--current)) + (if (oref ,s hidden) + (oset ,s washer + (lambda () + (funcall ,f) + (magit-section-maybe-remove-visibility-indicator ,s))) + (funcall ,f))))) + +(defun magit-insert-headers (hook) + (let* ((header-sections nil) + (magit-insert-section-hook + (cons (lambda () + (push magit-insert-section--current + header-sections)) + (if (listp magit-insert-section-hook) + magit-insert-section-hook + (list magit-insert-section-hook))))) + (magit-run-section-hook hook) + (when header-sections + (insert "\n") + ;; Make the first header into the parent of the rest. + (when (cdr header-sections) + (cl-callf nreverse header-sections) + (let* ((1st-header (pop header-sections)) + (header-parent (oref 1st-header parent))) + (oset header-parent children (list 1st-header)) + (oset 1st-header children header-sections) + (oset 1st-header content (oref (car header-sections) start)) + (oset 1st-header end (oref (car (last header-sections)) end)) + (dolist (sub-header header-sections) + (oset sub-header parent 1st-header))))))) + +(defun magit-insert-child-count (section) + "Modify SECTION's heading to contain number of child sections. + +If `magit-section-show-child-count' is non-nil and the SECTION +has children and its heading ends with \":\", then replace that +with \" (N)\", where N is the number of child sections. + +This function is called by `magit-insert-section' after that has +evaluated its BODY. Admittedly that's a bit of a hack." + ;; This has to be fast, not pretty! + (let (content count) + (when (and magit-section-show-child-count + (setq count (length (oref section children))) + (> count 0) + (setq content (oref section content)) + (eq (char-before (1- content)) ?:)) + (save-excursion + (goto-char (- content 2)) + (insert (format " (%s)" count)) + (delete-char 1))))) + +;;; Update + +(defvar-local magit-section-highlight-overlays nil) +(defvar-local magit-section-highlighted-section nil) +(defvar-local magit-section-highlighted-sections nil) +(defvar-local magit-section-unhighlight-sections nil) + +(defun magit-section-update-region (_) + "When the region is a valid section-selection, highlight them all." + ;; At least that's what it does conceptually. In actuality it just + ;; returns a list of those sections, and it doesn't even matter if + ;; this is a member of `magit-region-highlight-hook'. It probably + ;; should be removed, but I want to make sure before removing it. + (magit-region-sections)) + +(defun magit-section-update-highlight () + (let ((section (magit-current-section))) + (unless (eq section magit-section-highlighted-section) + (let ((inhibit-read-only t) + (deactivate-mark nil) + (selection (magit-region-sections))) + (mapc #'delete-overlay magit-section-highlight-overlays) + (setq magit-section-highlight-overlays nil) + (setq magit-section-unhighlight-sections + magit-section-highlighted-sections) + (setq magit-section-highlighted-sections nil) + (unless (eq section magit-root-section) + (run-hook-with-args-until-success + 'magit-section-highlight-hook section selection)) + (dolist (s magit-section-unhighlight-sections) + (run-hook-with-args-until-success + 'magit-section-unhighlight-hook s selection)) + (restore-buffer-modified-p nil) + (unless (eq magit-section-highlighted-section section) + (setq magit-section-highlighted-section + (and (not (oref section hidden)) + section))))) + (magit-section-maybe-paint-visibility-ellipses))) + +(defun magit-section-highlight (section selection) + "Highlight SECTION and if non-nil all sections in SELECTION. +This function works for any section but produces undesirable +effects for diff related sections, which by default are +highlighted using `magit-diff-highlight'. Return t." + (when-let ((face (oref section heading-highlight-face))) + (dolist (section (or selection (list section))) + (magit-section-make-overlay + (oref section start) + (or (oref section content) + (oref section end)) + face))) + (cond (selection + (magit-section-make-overlay (oref (car selection) start) + (oref (car (last selection)) end) + 'magit-section-highlight) + (magit-section-highlight-selection nil selection)) + (t + (magit-section-make-overlay (oref section start) + (oref section end) + 'magit-section-highlight))) + t) + +(defun magit-section-highlight-selection (_ selection) + "Highlight the section-selection region. +If SELECTION is non-nil, then it is a list of sections selected by +the region. The headings of these sections are then highlighted. + +This is a fallback for people who don't want to highlight the +current section and therefore removed `magit-section-highlight' +from `magit-section-highlight-hook'. + +This function is necessary to ensure that a representation of +such a region is visible. If neither of these functions were +part of the hook variable, then such a region would be +invisible." + (when (and selection + (not (and (eq this-command 'mouse-drag-region)))) + (dolist (section selection) + (magit-section-make-overlay (oref section start) + (or (oref section content) + (oref section end)) + 'magit-section-heading-selection)) + t)) + +(defun magit-section-make-overlay (start end face) + ;; Yes, this doesn't belong here. But the alternative of + ;; spreading this hack across the code base is even worse. + (when (and magit-keep-region-overlay + (memq face '(magit-section-heading-selection + magit-diff-file-heading-selection + magit-diff-hunk-heading-selection))) + (setq face (list :foreground (face-foreground face)))) + (let ((ov (make-overlay start end nil t))) + (overlay-put ov 'font-lock-face face) + (overlay-put ov 'evaporate t) + (push ov magit-section-highlight-overlays) + ov)) + +(defun magit-section-goto-successor (section line char arg) + (let ((ident (magit-section-ident section))) + (--if-let (magit-get-section ident) + (let ((start (oref it start))) + (goto-char start) + (unless (eq it magit-root-section) + (ignore-errors + (forward-line line) + (forward-char char)) + (unless (eq (magit-current-section) it) + (goto-char start)))) + (or (and (magit-hunk-section-p section) + (when-let ((parent (magit-get-section + (magit-section-ident + (oref section parent))))) + (let* ((children (oref parent children)) + (siblings (magit-section-siblings section 'prev)) + (previous (nth (length siblings) children))) + (if (not arg) + (--when-let (or previous (car (last children))) + (magit-section-goto it) + t) + (when previous + (magit-section-goto previous)) + (if (and (stringp arg) + (re-search-forward arg (oref parent end) t)) + (goto-char (match-beginning 0)) + (goto-char (oref (car (last children)) end)) + (forward-line -1) + (while (looking-at "^ ") (forward-line -1)) + (while (looking-at "^[-+]") (forward-line -1)) + (forward-line)))))) + (goto-char (--if-let (magit-section-goto-successor-1 section) + (if (eq (oref it type) 'button) + (point-min) + (oref it start)) + (point-min))))))) + +(defun magit-section-goto-successor-1 (section) + (or (--when-let (pcase (oref section type) + (`staged 'unstaged) + (`unstaged 'staged) + (`unpushed 'unpulled) + (`unpulled 'unpushed)) + (magit-get-section `((,it) (status)))) + (--when-let (car (magit-section-siblings section 'next)) + (magit-get-section (magit-section-ident it))) + (--when-let (car (magit-section-siblings section 'prev)) + (magit-get-section (magit-section-ident it))) + (--when-let (oref section parent) + (or (magit-get-section (magit-section-ident it)) + (magit-section-goto-successor-1 it))))) + +;;; Visibility + +(defvar-local magit-section-visibility-cache nil) +(put 'magit-section-visibility-cache 'permanent-local t) + +(defun magit-section-cached-visibility (section) + "Set SECTION's visibility to the cached value." + (cdr (assoc (magit-section-ident section) + magit-section-visibility-cache))) + +(cl-defun magit-section-cache-visibility + (&optional (section magit-insert-section--current)) + ;; Emacs 25's `alist-get' lacks TESTFN. + (let* ((id (magit-section-ident section)) + (elt (assoc id magit-section-visibility-cache)) + (val (if (oref section hidden) 'hide 'show))) + (if elt + (setcdr elt val) + (push (cons id val) magit-section-visibility-cache)))) + +(cl-defun magit-section-maybe-cache-visibility + (&optional (section magit-insert-section--current)) + (when (or (eq magit-section-cache-visibility t) + (memq (oref section type) + magit-section-cache-visibility)) + (magit-section-cache-visibility section))) + +(defun magit-preserve-section-visibility-cache () + (when (derived-mode-p 'magit-status-mode 'magit-refs-mode) + (magit-repository-local-set + (cons major-mode 'magit-section-visibility-cache) + magit-section-visibility-cache))) + +(defun magit-restore-section-visibility-cache (mode) + (setq magit-section-visibility-cache + (magit-repository-local-get + (cons mode 'magit-section-visibility-cache)))) + +(defun magit-section-maybe-update-visibility-indicator (section) + (when magit-section-visibility-indicator + (let ((beg (oref section start)) + (cnt (oref section content)) + (end (oref section end))) + (when (and cnt (or (not (= cnt end)) (oref section washer))) + (let ((eoh (save-excursion + (goto-char beg) + (line-end-position)))) + (cond + ((symbolp (car-safe magit-section-visibility-indicator)) + ;; It would make more sense to put the overlay only on the + ;; location we actually don't put it on, but then inserting + ;; before that location (while taking care not to mess with + ;; the overlay) would cause the fringe bitmap to disappear + ;; (but not other effects of the overlay). + (let ((ov (magit--overlay-at (1+ beg) 'magit-vis-indicator 'fringe))) + (unless ov + (setq ov (make-overlay (1+ beg) eoh)) + (overlay-put ov 'evaporate t) + (overlay-put ov 'magit-vis-indicator 'fringe)) + (overlay-put + ov 'before-string + (propertize "fringe" 'display + (list 'left-fringe + (if (oref section hidden) + (car magit-section-visibility-indicator) + (cdr magit-section-visibility-indicator)) + (face-foreground 'fringe)))))) + ((stringp (car-safe magit-section-visibility-indicator)) + (let ((ov (magit--overlay-at (1- eoh) 'magit-vis-indicator 'eoh))) + (cond ((oref section hidden) + (unless ov + (setq ov (make-overlay (1- eoh) eoh)) + (overlay-put ov 'evaporate t) + (overlay-put ov 'magit-vis-indicator 'eoh)) + (overlay-put ov 'after-string + (car magit-section-visibility-indicator))) + (ov + (delete-overlay ov))))))))))) + +(defvar-local magit--ellipses-sections nil) + +(defun magit-section-maybe-paint-visibility-ellipses () + ;; This is needed because we hide the body instead of "the body + ;; except the final newline and additionally the newline before + ;; the body"; otherwise we could use `buffer-invisibility-spec'. + (when (stringp (car-safe magit-section-visibility-indicator)) + (let* ((sections (append magit--ellipses-sections + (setq magit--ellipses-sections + (or (magit-region-sections) + (list (magit-current-section)))))) + (beg (--map (oref it start) sections)) + (end (--map (oref it end) sections))) + (when (region-active-p) + ;; This ensures that the region face is removed from ellipses + ;; when the region becomes inactive, but fails to ensure that + ;; all ellipses within the active region use the region face, + ;; because the respective overlay has not yet been updated at + ;; this time. The magit-selection face is always applied. + (push (region-beginning) beg) + (push (region-end) end)) + (setq beg (apply #'min beg)) + (setq end (apply #'max end)) + (dolist (ov (overlays-in beg end)) + (when (eq (overlay-get ov 'magit-vis-indicator) 'eoh) + (overlay-put + ov 'after-string + (propertize + (car magit-section-visibility-indicator) 'font-lock-face + (let ((pos (overlay-start ov))) + (delq nil (nconc (--map (overlay-get it 'font-lock-face) + (overlays-at pos)) + (list (get-char-property + pos 'font-lock-face)))))))))))) + +(defun magit-section-maybe-remove-visibility-indicator (section) + (when (and magit-section-visibility-indicator + (= (oref section content) + (oref section end))) + (dolist (o (overlays-in (oref section start) + (save-excursion + (goto-char (oref section start)) + (1+ (line-end-position))))) + (when (overlay-get o 'magit-vis-indicator) + (delete-overlay o))))) + +;;; Utilities + +(cl-defun magit-section-selected-p (section &optional (selection nil sselection)) + (and (not (eq section magit-root-section)) + (or (eq section (magit-current-section)) + (memq section (if sselection + selection + (setq selection (magit-region-sections)))) + (--when-let (oref section parent) + (magit-section-selected-p it selection))))) + +(defun magit-section-parent-value (section) + (when-let ((parent (oref section parent))) + (oref parent value))) + +(defun magit-section-siblings (section &optional direction) + "Return a list of the sibling sections of SECTION. + +If optional DIRECTION is `prev', then return siblings that come +before SECTION. If it is `next', then return siblings that come +after SECTION. For all other values, return all siblings +excluding SECTION itself." + (when-let ((parent (oref section parent))) + (let ((siblings (oref parent children))) + (pcase direction + (`prev (cdr (member section (reverse siblings)))) + (`next (cdr (member section siblings))) + (_ (remq section siblings)))))) + +(defun magit-region-values (&optional condition multiple) + "Return a list of the values of the selected sections. + +Return the values that themselves would be returned by +`magit-region-sections' (which see)." + (--map (oref it value) + (magit-region-sections condition multiple))) + +(defun magit-region-sections (&optional condition multiple) + "Return a list of the selected sections. + +When the region is active and constitutes a valid section +selection, then return a list of all selected sections. This is +the case when the region begins in the heading of a section and +ends in the heading of the same section or in that of a sibling +section. If optional MULTIPLE is non-nil, then the region cannot +begin and end in the same section. + +When the selection is not valid, then return nil. In this case, +most commands that can act on the selected sections will instead +act on the section at point. + +When the region looks like it would in any other buffer then +the selection is invalid. When the selection is valid then the +region uses the `magit-section-highlight' face. This does not +apply to diffs where things get a bit more complicated, but even +here if the region looks like it usually does, then that's not +a valid selection as far as this function is concerned. + +If optional CONDITION is non-nil, then the selection not only +has to be valid; all selected sections additionally have to match +CONDITION, or nil is returned. See `magit-section-match' for the +forms CONDITION can take." + (when (region-active-p) + (let* ((rbeg (region-beginning)) + (rend (region-end)) + (sbeg (get-text-property rbeg 'magit-section)) + (send (get-text-property rend 'magit-section))) + (when (and send + (not (eq send magit-root-section)) + (not (and multiple (eq send sbeg)))) + (let ((siblings (cons sbeg (magit-section-siblings sbeg 'next))) + sections) + (when (and (memq send siblings) + (magit-section-position-in-heading-p sbeg rbeg) + (magit-section-position-in-heading-p send rend)) + (while siblings + (push (car siblings) sections) + (when (eq (pop siblings) send) + (setq siblings nil))) + (setq sections (nreverse sections)) + (when (or (not condition) + (--all-p (magit-section-match condition it) sections)) + sections))))))) + +(defun magit-section-position-in-heading-p (&optional section pos) + "Return t if POSITION is inside the heading of SECTION. +POSITION defaults to point and SECTION defaults to the +current section." + (unless section + (setq section (magit-current-section))) + (unless pos + (setq pos (point))) + (and section + (>= pos (oref section start)) + (< pos (or (oref section content) + (oref section end))) + t)) + +(defun magit-section-internal-region-p (&optional section) + "Return t if the region is active and inside SECTION's body. +If optional SECTION is nil, use the current section." + (and (region-active-p) + (or section (setq section (magit-current-section))) + (let ((beg (get-text-property (region-beginning) 'magit-section))) + (and (eq beg (get-text-property (region-end) 'magit-section)) + (eq beg section))) + (not (or (magit-section-position-in-heading-p section (region-beginning)) + (magit-section-position-in-heading-p section (region-end)))) + t)) + +(defun magit-section--backward-protected () + "Move to the beginning of the current or the previous visible section. +Same as `magit-section-backward' but for non-interactive use. +Suppress `magit-section-movement-hook', and return a boolean to +indicate whether a section was found, instead of raising an error +if not." + (condition-case nil + (let ((magit-section-movement-hook nil)) + (magit-section-backward) + t) + (user-error nil))) + +(defun magit-section--backward-find (predicate) + "Move to the first previous section satisfying PREDICATE. +PREDICATE does not take any parameter and should not move +point." + (let (found) + (while (and (setq found (magit-section--backward-protected)) + (not (funcall predicate)))) + found)) + +(defun magit-wash-sequence (function) + "Repeatedly call FUNCTION until it returns nil or eob is reached. +FUNCTION has to move point forward or return nil." + (while (and (not (eobp)) (funcall function)))) + +(defun magit-add-section-hook (hook function &optional at append local) + "Add to the value of section hook HOOK the function FUNCTION. + +Add FUNCTION at the beginning of the hook list unless optional +APPEND is non-nil, in which case FUNCTION is added at the end. +If FUNCTION already is a member, then move it to the new location. + +If optional AT is non-nil and a member of the hook list, then +add FUNCTION next to that instead. Add before or after AT, or +replace AT with FUNCTION depending on APPEND. If APPEND is the +symbol `replace', then replace AT with FUNCTION. For any other +non-nil value place FUNCTION right after AT. If nil, then place +FUNCTION right before AT. If FUNCTION already is a member of the +list but AT is not, then leave FUNCTION where ever it already is. + +If optional LOCAL is non-nil, then modify the hook's buffer-local +value rather than its global value. This makes the hook local by +copying the default value. That copy is then modified. + +HOOK should be a symbol. If HOOK is void, it is first set to nil. +HOOK's value must not be a single hook function. FUNCTION should +be a function that takes no arguments and inserts one or multiple +sections at point, moving point forward. FUNCTION may choose not +to insert its section(s), when doing so would not make sense. It +should not be abused for other side-effects. To remove FUNCTION +again use `remove-hook'." + (unless (boundp hook) + (error "Cannot add function to undefined hook variable %s" hook)) + (or (default-boundp hook) (set-default hook nil)) + (let ((value (if local + (if (local-variable-p hook) + (symbol-value hook) + (unless (local-variable-if-set-p hook) + (make-local-variable hook)) + (copy-sequence (default-value hook))) + (default-value hook)))) + (if at + (when (setq at (member at value)) + (setq value (delq function value)) + (cond ((eq append 'replace) + (setcar at function)) + (append + (push function (cdr at))) + (t + (push (car at) (cdr at)) + (setcar at function)))) + (setq value (delq function value))) + (unless (member function value) + (setq value (if append + (append value (list function)) + (cons function value)))) + (when (eq append 'replace) + (setq value (delq at value))) + (if local + (set hook value) + (set-default hook value)))) + +(defun magit-run-section-hook (hook &rest args) + "Run HOOK with ARGS, warning about invalid entries." + (let ((entries (symbol-value hook))) + (unless (listp entries) + (setq entries (list entries))) + (--when-let (-remove #'functionp entries) + (message "`%s' contains entries that are no longer valid. +%s\nUsing standard value instead. Please re-configure hook variable." + hook + (mapconcat (lambda (sym) (format " `%s'" sym)) it "\n")) + (sit-for 5) + (setq entries (eval (car (get hook 'standard-value))))) + (dolist (entry entries) + (let ((magit--current-section-hook (cons (list hook entry) + magit--current-section-hook))) + (if magit-refresh-verbose + (message " %-50s %s" entry + (benchmark-elapse (apply entry args))) + (apply entry args)))))) + +;;; _ +(provide 'magit-section) +;;; magit-section.el ends here diff --git a/elpa/magit-20191122.2040/magit-section.elc b/elpa/magit-20191122.2040/magit-section.elc new file mode 100644 index 0000000000000000000000000000000000000000..bf2772de7a4d996de7566554b0cf2641f351c2ec GIT binary patch literal 62655 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 O|6DesV!q3b(*FzPuqA&0 literal 0 HcmV?d00001 diff --git a/elpa/magit-20191122.2040/magit-sequence.el b/elpa/magit-20191122.2040/magit-sequence.el new file mode 100644 index 00000000..fb7ff892 --- /dev/null +++ b/elpa/magit-20191122.2040/magit-sequence.el @@ -0,0 +1,1029 @@ +;;; magit-sequence.el --- history manipulation in Magit -*- lexical-binding: t -*- + +;; Copyright (C) 2011-2019 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; Support for Git commands that replay commits and help the user make +;; changes along the way. Supports `cherry-pick', `revert', `rebase', +;; `rebase--interactive' and `am'. + +;;; Code: + +(eval-when-compile + (require 'subr-x)) + +(require 'magit) + +;; For `magit-rebase--todo'. +(declare-function git-rebase-current-line "git-rebase" ()) +(eval-when-compile + (cl-pushnew 'action-type eieio--known-slot-names) + (cl-pushnew 'action eieio--known-slot-names) + (cl-pushnew 'action-options eieio--known-slot-names) + (cl-pushnew 'target eieio--known-slot-names)) + +;;; Options +;;;; Faces + +(defface magit-sequence-pick + '((t :inherit default)) + "Face used in sequence sections." + :group 'magit-faces) + +(defface magit-sequence-stop + '((((class color) (background light)) :foreground "DarkOliveGreen4") + (((class color) (background dark)) :foreground "DarkSeaGreen2")) + "Face used in sequence sections." + :group 'magit-faces) + +(defface magit-sequence-part + '((((class color) (background light)) :foreground "Goldenrod4") + (((class color) (background dark)) :foreground "LightGoldenrod2")) + "Face used in sequence sections." + :group 'magit-faces) + +(defface magit-sequence-head + '((((class color) (background light)) :foreground "SkyBlue4") + (((class color) (background dark)) :foreground "LightSkyBlue1")) + "Face used in sequence sections." + :group 'magit-faces) + +(defface magit-sequence-drop + '((((class color) (background light)) :foreground "IndianRed") + (((class color) (background dark)) :foreground "IndianRed")) + "Face used in sequence sections." + :group 'magit-faces) + +(defface magit-sequence-done + '((t :inherit magit-hash)) + "Face used in sequence sections." + :group 'magit-faces) + +(defface magit-sequence-onto + '((t :inherit magit-sequence-done)) + "Face used in sequence sections." + :group 'magit-faces) + +(defface magit-sequence-exec + '((t :inherit magit-hash)) + "Face used in sequence sections." + :group 'magit-faces) + +;;; Common + +;;;###autoload +(defun magit-sequencer-continue () + "Resume the current cherry-pick or revert sequence." + (interactive) + (if (magit-sequencer-in-progress-p) + (if (magit-anything-unstaged-p t) + (user-error "Cannot continue due to unstaged changes") + (magit-run-git-sequencer + (if (magit-revert-in-progress-p) "revert" "cherry-pick") "--continue")) + (user-error "No cherry-pick or revert in progress"))) + +;;;###autoload +(defun magit-sequencer-skip () + "Skip the stopped at commit during a cherry-pick or revert sequence." + (interactive) + (if (magit-sequencer-in-progress-p) + (progn (magit-call-git "reset" "--hard") + (magit-sequencer-continue)) + (user-error "No cherry-pick or revert in progress"))) + +;;;###autoload +(defun magit-sequencer-abort () + "Abort the current cherry-pick or revert sequence. +This discards all changes made since the sequence started." + (interactive) + (if (magit-sequencer-in-progress-p) + (magit-run-git-sequencer + (if (magit-revert-in-progress-p) "revert" "cherry-pick") "--abort") + (user-error "No cherry-pick or revert in progress"))) + +(defun magit-sequencer-in-progress-p () + (or (magit-cherry-pick-in-progress-p) + (magit-revert-in-progress-p))) + +;;; Cherry-Pick + +(defvar magit-perl-executable "perl" + "The Perl executable.") + +;;;###autoload (autoload 'magit-cherry-pick "magit-sequence" nil t) +(define-transient-command magit-cherry-pick () + "Apply or transplant commits." + :man-page "git-cherry-pick" + :value '("--ff") + :incompatible '(("--ff" "-x")) + ["Arguments" + :if-not magit-sequencer-in-progress-p + (magit-cherry-pick:--mainline) + ("=s" magit-merge:--strategy) + ("-F" "Attempt fast-forward" "--ff") + ("-x" "Reference cherry in commit message" "-x") + ("-e" "Edit commit messages" ("-e" "--edit")) + ("-s" "Add Signed-off-by lines" ("-s" "--signoff")) + (5 magit:--gpg-sign)] + [:if-not magit-sequencer-in-progress-p + ["Apply here" + ("A" "Pick" magit-cherry-copy) + ("a" "Apply" magit-cherry-apply) + ("h" "Harvest" magit-cherry-harvest)] + ["Apply elsewhere" + ("d" "Donate" magit-cherry-donate) + ("n" "Spinout" magit-cherry-spinout) + ("s" "Spinoff" magit-cherry-spinoff)]] + ["Actions" + :if magit-sequencer-in-progress-p + ("A" "Continue" magit-sequencer-continue) + ("s" "Skip" magit-sequencer-skip) + ("a" "Abort" magit-sequencer-abort)]) + +(define-infix-argument magit-cherry-pick:--mainline () + :description "Replay merge relative to parent" + :class 'transient-option + :shortarg "-m" + :argument "--mainline=" + :reader 'transient-read-number-N+) + +(defun magit-cherry-pick-read-args (prompt) + (list (or (nreverse (magit-region-values 'commit)) + (magit-read-other-branch-or-commit prompt)) + (transient-args 'magit-cherry-pick))) + +(defun magit--cherry-move-read-args (verb away fn) + (declare (indent defun)) + (let ((commits (or (nreverse (magit-region-values 'commit)) + (list (funcall (if away + 'magit-read-branch-or-commit + 'magit-read-other-branch-or-commit) + (format "%s cherry" (capitalize verb)))))) + (current (magit-get-current-branch))) + (unless current + (user-error "Cannot %s cherries while HEAD is detached" verb)) + (let ((reachable (magit-rev-ancestor-p (car commits) current)) + (msg "Cannot %s cherries that %s reachable from HEAD")) + (pcase (list away reachable) + (`(nil t) (user-error msg verb "are")) + (`(t nil) (user-error msg verb "are not")))) + `(,commits + ,@(funcall fn commits) + ,(transient-args 'magit-cherry-pick)))) + +(defun magit--cherry-spinoff-read-args (verb) + (magit--cherry-move-read-args verb t + (lambda (commits) + (magit-branch-read-args + (format "Create branch from %s cherries" (length commits)) + (magit-get-upstream-branch))))) + +;;;###autoload +(defun magit-cherry-copy (commits &optional args) + "Copy COMMITS from another branch onto the current branch. +Prompt for a commit, defaulting to the commit at point. If +the region selects multiple commits, then pick all of them, +without prompting." + (interactive (magit-cherry-pick-read-args "Cherry-pick")) + (magit--cherry-pick commits args)) + +;;;###autoload +(defun magit-cherry-apply (commits &optional args) + "Apply the changes in COMMITS but do not commit them. +Prompt for a commit, defaulting to the commit at point. If +the region selects multiple commits, then apply all of them, +without prompting." + (interactive (magit-cherry-pick-read-args "Apply changes from commit")) + (magit--cherry-pick commits (cons "--no-commit" (remove "--ff" args)))) + +;;;###autoload +(defun magit-cherry-harvest (commits branch &optional args) + "Move COMMITS from another BRANCH onto the current branch. +Remove the COMMITS from BRANCH and stay on the current branch. +If a conflict occurs, then you have to fix that and finish the +process manually." + (interactive + (magit--cherry-move-read-args "harvest" nil + (lambda (commits) + (list (let ((branches (magit-list-containing-branches (car commits)))) + (pcase (length branches) + (0 nil) + (1 (car branches)) + (_ (magit-completing-read + (format "Remove %s cherries from branch" (length commits)) + branches nil t)))))))) + (magit--cherry-move commits branch (magit-get-current-branch) args nil t)) + +;;;###autoload +(defun magit-cherry-donate (commits branch &optional args) + "Move COMMITS from the current branch onto another existing BRANCH. +Remove COMMITS from the current branch and stay on that branch. +If a conflict occurs, then you have to fix that and finish the +process manually." + (interactive + (magit--cherry-move-read-args "donate" t + (lambda (commits) + (list (magit-read-other-branch (format "Move %s cherries to branch" + (length commits))))))) + (magit--cherry-move commits (magit-get-current-branch) branch args)) + +;;;###autoload +(defun magit-cherry-spinout (commits branch start-point &optional args) + "Move COMMITS from the current branch onto a new BRANCH. +Remove COMMITS from the current branch and stay on that branch. +If a conflict occurs, then you have to fix that and finish the +process manually." + (interactive (magit--cherry-spinoff-read-args "spinout")) + (magit--cherry-move commits (magit-get-current-branch) branch args + start-point)) + +;;;###autoload +(defun magit-cherry-spinoff (commits branch start-point &optional args) + "Move COMMITS from the current branch onto a new BRANCH. +Remove COMMITS from the current branch and checkout BRANCH. +If a conflict occurs, then you have to fix that and finish +the process manually." + (interactive (magit--cherry-spinoff-read-args "spinoff")) + (magit--cherry-move commits (magit-get-current-branch) branch args + start-point t)) + +(defun magit--cherry-move (commits src dst args + &optional start-point checkout-dst) + (let ((current (magit-get-current-branch))) + (unless (magit-branch-p dst) + (let ((magit-process-raise-error t)) + (magit-call-git "branch" dst start-point)) + (--when-let (magit-get-indirect-upstream-branch start-point) + (magit-call-git "branch" "--set-upstream-to" it dst))) + (unless (equal dst current) + (let ((magit-process-raise-error t)) + (magit-call-git "checkout" dst))) + (if (not src) ; harvest only + (magit--cherry-pick commits args) + (let ((tip (car (last commits))) + (keep (concat (car commits) "^"))) + (magit--cherry-pick commits args) + (set-process-sentinel + magit-this-process + (lambda (process event) + (when (memq (process-status process) '(exit signal)) + (if (> (process-exit-status process) 0) + (magit-process-sentinel process event) + (process-put process 'inhibit-refresh t) + (magit-process-sentinel process event) + (cond + ((magit-rev-equal tip src) + (magit-call-git "update-ref" + "-m" (format "reset: moving to %s" keep) + (magit-ref-fullname src) + keep tip) + (if (not checkout-dst) + (magit-run-git "checkout" src) + (magit-refresh))) + (t + (magit-git "checkout" src) + (let ((process-environment process-environment)) + (push (format "%s=%s -i -ne '/^pick (%s)/ or print'" + "GIT_SEQUENCE_EDITOR" + magit-perl-executable + (mapconcat #'magit-rev-abbrev commits "|")) + process-environment) + (magit-run-git-sequencer "rebase" "-i" keep)) + (when checkout-dst + (set-process-sentinel + magit-this-process + (lambda (process event) + (when (memq (process-status process) '(exit signal)) + (if (> (process-exit-status process) 0) + (magit-process-sentinel process event) + (process-put process 'inhibit-refresh t) + (magit-process-sentinel process event) + (magit-run-git "checkout" dst)))))))))))))))) + +(defun magit--cherry-pick (commits args &optional revert) + (let ((command (if revert "revert" "cherry-pick"))) + (when (stringp commits) + (setq commits (if (string-match-p "\\.\\." commits) + (split-string commits "\\.\\.") + (list commits)))) + (magit-run-git-sequencer + (if revert "revert" "cherry-pick") + (pcase-let ((`(,merge ,non-merge) + (-separate 'magit-merge-commit-p commits))) + (cond + ((not merge) + (--remove (string-prefix-p "--mainline=" it) args)) + (non-merge + (user-error "Cannot %s merge and non-merge commits at once" + command)) + ((--first (string-prefix-p "--mainline=" it) args) + args) + (t + (cons (format "--mainline=%s" + (read-number "Replay merges relative to parent: ")) + args)))) + commits))) + +(defun magit-cherry-pick-in-progress-p () + ;; .git/sequencer/todo does not exist when there is only one commit left. + (file-exists-p (magit-git-dir "CHERRY_PICK_HEAD"))) + +;;; Revert + +;;;###autoload (autoload 'magit-revert "magit-sequence" nil t) +(define-transient-command magit-revert () + "Revert existing commits, with or without creating new commits." + :man-page "git-revert" + :value '("--edit") + ["Arguments" + :if-not magit-sequencer-in-progress-p + (magit-cherry-pick:--mainline) + ("-e" "Edit commit message" ("-e" "--edit")) + ("-E" "Don't edit commit message" "--no-edit") + ("=s" magit-merge:--strategy) + ("-s" "Add Signed-off-by lines" ("-s" "--signoff")) + (5 magit:--gpg-sign)] + ["Actions" + :if-not magit-sequencer-in-progress-p + ("V" "Revert commit(s)" magit-revert-and-commit) + ("v" "Revert changes" magit-revert-no-commit)] + ["Actions" + :if magit-sequencer-in-progress-p + ("V" "Continue" magit-sequencer-continue) + ("s" "Skip" magit-sequencer-skip) + ("a" "Abort" magit-sequencer-abort)]) + +(defun magit-revert-read-args (prompt) + (list (or (magit-region-values 'commit) + (magit-read-branch-or-commit prompt)) + (transient-args 'magit-revert))) + +;;;###autoload +(defun magit-revert-and-commit (commit &optional args) + "Revert COMMIT by creating a new commit. +Prompt for a commit, defaulting to the commit at point. If +the region selects multiple commits, then revert all of them, +without prompting." + (interactive (magit-revert-read-args "Revert commit")) + (magit--cherry-pick commit args t)) + +;;;###autoload +(defun magit-revert-no-commit (commit &optional args) + "Revert COMMIT by applying it in reverse to the worktree. +Prompt for a commit, defaulting to the commit at point. If +the region selects multiple commits, then revert all of them, +without prompting." + (interactive (magit-revert-read-args "Revert changes")) + (magit--cherry-pick commit (cons "--no-commit" args) t)) + +(defun magit-revert-in-progress-p () + ;; .git/sequencer/todo does not exist when there is only one commit left. + (file-exists-p (magit-git-dir "REVERT_HEAD"))) + +;;; Patch + +;;;###autoload (autoload 'magit-am "magit-sequence" nil t) +(define-transient-command magit-am () + "Apply patches received by email." + :man-page "git-am" + :value '("--3way") + ["Arguments" + :if-not magit-am-in-progress-p + ("-3" "Fall back on 3way merge" ("-3" "--3way")) + (magit-apply:-p) + ("-c" "Remove text before scissors line" ("-c" "--scissors")) + ("-k" "Inhibit removal of email cruft" ("-k" "--keep")) + ("-b" "Limit removal of email cruft" "--keep-non-patch") + ("-d" "Use author date as committer date" "--committer-date-is-author-date") + ("-D" "Use committer date as author date" "--ignore-date") + ("-s" "Add Signed-off-by lines" ("-s" "--signoff")) + (5 magit:--gpg-sign)] + ["Apply" + :if-not magit-am-in-progress-p + ("m" "maildir" magit-am-apply-maildir) + ("w" "patches" magit-am-apply-patches) + ("a" "plain patch" magit-patch-apply)] + ["Actions" + :if magit-am-in-progress-p + ("w" "Continue" magit-am-continue) + ("s" "Skip" magit-am-skip) + ("a" "Abort" magit-am-abort)]) + +(defun magit-am-arguments () + (transient-args 'magit-am)) + +(define-infix-argument magit-apply:-p () + :description "Remove leading slashes from paths" + :class 'transient-option + :argument "-p" + :reader 'transient-read-number-N+) + +;;;###autoload +(defun magit-am-apply-patches (&optional files args) + "Apply the patches FILES." + (interactive (list (or (magit-region-values 'file) + (list (let ((default (magit-file-at-point))) + (read-file-name + (if default + (format "Apply patch (%s): " default) + "Apply patch: ") + nil default)))) + (magit-am-arguments))) + (magit-run-git-sequencer "am" args "--" + (--map (magit-convert-filename-for-git + (expand-file-name it)) + files))) + +;;;###autoload +(defun magit-am-apply-maildir (&optional maildir args) + "Apply the patches from MAILDIR." + (interactive (list (read-file-name "Apply mbox or Maildir: ") + (magit-am-arguments))) + (magit-run-git-sequencer "am" args (magit-convert-filename-for-git + (expand-file-name maildir)))) + +;;;###autoload +(defun magit-am-continue () + "Resume the current patch applying sequence." + (interactive) + (if (magit-am-in-progress-p) + (if (magit-anything-unstaged-p t) + (error "Cannot continue due to unstaged changes") + (magit-run-git-sequencer "am" "--continue")) + (user-error "Not applying any patches"))) + +;;;###autoload +(defun magit-am-skip () + "Skip the stopped at patch during a patch applying sequence." + (interactive) + (if (magit-am-in-progress-p) + (magit-run-git-sequencer "am" "--skip") + (user-error "Not applying any patches"))) + +;;;###autoload +(defun magit-am-abort () + "Abort the current patch applying sequence. +This discards all changes made since the sequence started." + (interactive) + (if (magit-am-in-progress-p) + (magit-run-git "am" "--abort") + (user-error "Not applying any patches"))) + +(defun magit-am-in-progress-p () + (file-exists-p (magit-git-dir "rebase-apply/applying"))) + +;;; Rebase + +;;;###autoload (autoload 'magit-rebase "magit-sequence" nil t) +(define-transient-command magit-rebase () + "Transplant commits and/or modify existing commits." + :man-page "git-rebase" + ["Arguments" + :if-not magit-rebase-in-progress-p + ("-k" "Keep empty commits" "--keep-empty") + ("-p" "Preserve merges" ("-p" "--preserve-merges")) + ("-d" "Lie about committer date" "--committer-date-is-author-date") + ("-a" "Autosquash" "--autosquash") + ("-A" "Autostash" "--autostash") + ("-i" "Interactive" ("-i" "--interactive")) + ("-h" "Disable hooks" "--no-verify") + (5 magit:--gpg-sign) + (5 "-r" "Rebase merges" "--rebase-merges=" magit-rebase-merges-select-mode)] + [:if-not magit-rebase-in-progress-p + :description (lambda () + (format (propertize "Rebase %s onto" 'face 'transient-heading) + (propertize (or (magit-get-current-branch) "HEAD") + 'face 'magit-branch-local))) + ("p" magit-rebase-onto-pushremote) + ("u" magit-rebase-onto-upstream) + ("e" "elsewhere" magit-rebase-branch)] + ["Rebase" + :if-not magit-rebase-in-progress-p + [("i" "interactively" magit-rebase-interactive) + ("s" "a subset" magit-rebase-subset)] + [("m" "to modify a commit" magit-rebase-edit-commit) + ("w" "to reword a commit" magit-rebase-reword-commit) + ("k" "to remove a commit" magit-rebase-remove-commit) + ("f" "to autosquash" magit-rebase-autosquash) + (6 "t" "to change dates" magit-reshelve-since)]] + ["Actions" + :if magit-rebase-in-progress-p + ("r" "Continue" magit-rebase-continue) + ("s" "Skip" magit-rebase-skip) + ("e" "Edit" magit-rebase-edit) + ("a" "Abort" magit-rebase-abort)]) + +(defun magit-rebase-merges-select-mode (&rest _ignore) + (magit-read-char-case nil t + (?n "[n]o-rebase-cousins" "no-rebase-cousins") + (?r "[r]ebase-cousins" "rebase-cousins"))) + +(defun magit-rebase-arguments () + (transient-args 'magit-rebase)) + +(defun magit-git-rebase (target args) + (magit-run-git-sequencer "rebase" args target)) + +;;;###autoload (autoload 'magit-rebase-onto-pushremote "magit-sequence" nil t) +(define-suffix-command magit-rebase-onto-pushremote (args) + "Rebase the current branch onto its push-remote branch. + +When the push-remote is not configured, then read the push-remote +from the user, set it, and then rebase onto it. With a prefix +argument the push-remote can be changed before rebasing onto to +it." + :if 'magit-get-current-branch + :description 'magit-pull--pushbranch-description + (interactive (list (magit-rebase-arguments))) + (pcase-let ((`(,branch ,remote) + (magit--select-push-remote "rebase onto that"))) + (magit-git-rebase (concat remote "/" branch) args))) + +;;;###autoload (autoload 'magit-rebase-onto-upstream "magit-sequence" nil t) +(define-suffix-command magit-rebase-onto-upstream (args) + "Rebase the current branch onto its upstream branch. + +With a prefix argument or when the upstream is either not +configured or unusable, then let the user first configure +the upstream." + :if 'magit-get-current-branch + :description 'magit-rebase--upstream-description + (interactive (list (magit-rebase-arguments))) + (let* ((branch (or (magit-get-current-branch) + (user-error "No branch is checked out"))) + (upstream (magit-get-upstream-branch branch))) + (when (or current-prefix-arg (not upstream)) + (setq upstream + (magit-read-upstream-branch + branch (format "Set upstream of %s and rebase onto that" branch))) + (magit-set-upstream-branch branch upstream)) + (magit-git-rebase upstream args))) + +(defun magit-rebase--upstream-description () + (when-let ((branch (magit-get-current-branch))) + (or (magit-get-upstream-branch branch) + (let ((remote (magit-get "branch" branch "remote")) + (merge (magit-get "branch" branch "merge")) + (u (magit--propertize-face "@{upstream}" 'bold))) + (cond + ((magit--unnamed-upstream-p remote merge) + (concat u ", replacing unnamed")) + ((magit--valid-upstream-p remote merge) + (concat u ", replacing non-existent")) + ((or remote merge) + (concat u ", replacing invalid")) + (t + (concat u ", setting that"))))))) + +;;;###autoload +(defun magit-rebase-branch (target args) + "Rebase the current branch onto a branch read in the minibuffer. +All commits that are reachable from `HEAD' but not from the +selected branch TARGET are being rebased." + (interactive (list (magit-read-other-branch-or-commit "Rebase onto") + (magit-rebase-arguments))) + (message "Rebasing...") + (magit-git-rebase target args) + (message "Rebasing...done")) + +;;;###autoload +(defun magit-rebase-subset (newbase start args) + "Rebase a subset of the current branch's history onto a new base. +Rebase commits from START to `HEAD' onto NEWBASE. +START has to be selected from a list of recent commits." + (interactive (list (magit-read-other-branch-or-commit + "Rebase subset onto" nil + (magit-get-upstream-branch)) + nil + (magit-rebase-arguments))) + (if start + (progn (message "Rebasing...") + (magit-run-git-sequencer "rebase" "--onto" newbase start args) + (message "Rebasing...done")) + (magit-log-select + `(lambda (commit) + (magit-rebase-subset ,newbase (concat commit "^") (list ,@args))) + (concat "Type %p on a commit to rebase it " + "and commits above it onto " newbase ",")))) + +(defun magit-rebase-interactive-1 + (commit args message &optional editor delay-edit-confirm noassert confirm) + (declare (indent 2)) + (when commit + (if (eq commit :merge-base) + (setq commit (--if-let (magit-get-upstream-branch) + (magit-git-string "merge-base" it "HEAD") + nil)) + (unless (magit-rev-ancestor-p commit "HEAD") + (user-error "%s isn't an ancestor of HEAD" commit)) + (if (magit-commit-parents commit) + (setq commit (concat commit "^")) + (setq args (cons "--root" args))))) + (when (and commit (not noassert)) + (setq commit (magit-rebase-interactive-assert + commit delay-edit-confirm + (--some (string-prefix-p "--rebase-merges" it) args)))) + (if (and commit (not confirm)) + (let ((process-environment process-environment)) + (when editor + (push (concat "GIT_SEQUENCE_EDITOR=" + (if (functionp editor) + (funcall editor commit) + editor)) + process-environment)) + (magit-run-git-sequencer "rebase" "-i" args + (unless (member "--root" args) commit))) + (magit-log-select + `(lambda (commit) + (magit-rebase-interactive-1 commit (list ,@args) + ,message ,editor ,delay-edit-confirm ,noassert)) + message))) + +(defvar magit--rebase-published-symbol nil) +(defvar magit--rebase-public-edit-confirmed nil) + +(defun magit-rebase-interactive-assert + (since &optional delay-edit-confirm rebase-merges) + (let* ((commit (magit-rebase--target-commit since)) + (branches (magit-list-publishing-branches commit))) + (setq magit--rebase-public-edit-confirmed + (delete (magit-toplevel) magit--rebase-public-edit-confirmed)) + (when (and branches + (or (not delay-edit-confirm) + ;; The user might have stopped at a published commit + ;; merely to add new commits *after* it. Try not to + ;; ask users whether they really want to edit public + ;; commits, when they don't actually intend to do so. + (not (--all-p (magit-rev-equal it commit) branches)))) + (let ((m1 "Some of these commits have already been published to ") + (m2 ".\nDo you really want to modify them")) + (magit-confirm (or magit--rebase-published-symbol 'rebase-published) + (concat m1 "%s" m2) + (concat m1 "%i public branches" m2) + nil branches)) + (push (magit-toplevel) magit--rebase-public-edit-confirmed))) + (if (and (magit-git-lines "rev-list" "--merges" (concat since "..HEAD")) + (not rebase-merges)) + (magit-read-char-case "Proceed despite merge in rebase range? " nil + (?c "[c]ontinue" since) + (?s "[s]elect other" nil) + (?a "[a]bort" (user-error "Quit"))) + since)) + +(defun magit-rebase--target-commit (since) + (if (string-suffix-p "^" since) + ;; If SINCE is "REV^", then the user selected + ;; "REV", which is the first commit that will + ;; be replaced. (from^..to] <=> [from..to] + (substring since 0 -1) + ;; The "--root" argument is being used. + since)) + +;;;###autoload +(defun magit-rebase-interactive (commit args) + "Start an interactive rebase sequence." + (interactive (list (magit-commit-at-point) + (magit-rebase-arguments))) + (magit-rebase-interactive-1 commit args + "Type %p on a commit to rebase it and all commits above it," + nil t)) + +;;;###autoload +(defun magit-rebase-autosquash (args) + "Combine squash and fixup commits with their intended targets." + (interactive (list (magit-rebase-arguments))) + (magit-rebase-interactive-1 :merge-base + (nconc (list "--autosquash" "--keep-empty") args) + "Type %p on a commit to squash into it and then rebase as necessary," + "true" nil t)) + +;;;###autoload +(defun magit-rebase-edit-commit (commit args) + "Edit a single older commit using rebase." + (interactive (list (magit-commit-at-point) + (magit-rebase-arguments))) + (magit-rebase-interactive-1 commit args + "Type %p on a commit to edit it," + (apply-partially #'magit-rebase--perl-editor 'edit) + t)) + +;;;###autoload +(defun magit-rebase-reword-commit (commit args) + "Reword a single older commit using rebase." + (interactive (list (magit-commit-at-point) + (magit-rebase-arguments))) + (magit-rebase-interactive-1 commit args + "Type %p on a commit to reword its message," + (apply-partially #'magit-rebase--perl-editor 'reword))) + +;;;###autoload +(defun magit-rebase-remove-commit (commit args) + "Remove a single older commit using rebase." + (interactive (list (magit-commit-at-point) + (magit-rebase-arguments))) + (magit-rebase-interactive-1 commit args + "Type %p on a commit to remove it," + (apply-partially #'magit-rebase--perl-editor 'remove) + nil nil t)) + +(defun magit-rebase--perl-editor (action since) + (let ((commit (magit-rev-abbrev (magit-rebase--target-commit since)))) + (format "%s -i -p -e '++$x if not $x and s/^pick %s/%s %s/'" + magit-perl-executable + commit + (cl-case action + (edit "edit") + (remove "# pick") + (reword "reword") + (t (error "unknown action: %s" action))) + commit))) + +;;;###autoload +(defun magit-rebase-continue (&optional noedit) + "Restart the current rebasing operation. +In some cases this pops up a commit message buffer for you do +edit. With a prefix argument the old message is reused as-is." + (interactive "P") + (if (magit-rebase-in-progress-p) + (if (magit-anything-unstaged-p t) + (user-error "Cannot continue rebase with unstaged changes") + (when (and (magit-anything-staged-p) + (file-exists-p (magit-git-dir "rebase-merge")) + (not (member (magit-toplevel) + magit--rebase-public-edit-confirmed))) + (magit-commit-amend-assert)) + (if noedit + (let ((process-environment process-environment)) + (push "GIT_EDITOR=true" process-environment) + (magit-run-git-async (magit--rebase-resume-command) "--continue") + (set-process-sentinel magit-this-process + #'magit-sequencer-process-sentinel) + magit-this-process) + (magit-run-git-sequencer (magit--rebase-resume-command) "--continue"))) + (user-error "No rebase in progress"))) + +;;;###autoload +(defun magit-rebase-skip () + "Skip the current commit and restart the current rebase operation." + (interactive) + (unless (magit-rebase-in-progress-p) + (user-error "No rebase in progress")) + (magit-run-git-sequencer (magit--rebase-resume-command) "--skip")) + +;;;###autoload +(defun magit-rebase-edit () + "Edit the todo list of the current rebase operation." + (interactive) + (unless (magit-rebase-in-progress-p) + (user-error "No rebase in progress")) + (magit-run-git-sequencer "rebase" "--edit-todo")) + +;;;###autoload +(defun magit-rebase-abort () + "Abort the current rebase operation, restoring the original branch." + (interactive) + (unless (magit-rebase-in-progress-p) + (user-error "No rebase in progress")) + (magit-confirm 'abort-rebase "Abort this rebase") + (magit-run-git (magit--rebase-resume-command) "--abort")) + +(defun magit-rebase-in-progress-p () + "Return t if a rebase is in progress." + (or (file-exists-p (magit-git-dir "rebase-merge")) + (file-exists-p (magit-git-dir "rebase-apply/onto")))) + +(defun magit--rebase-resume-command () + (if (file-exists-p (magit-git-dir "rebase-recursive")) "rbr" "rebase")) + +;;; Sections + +(defun magit-insert-sequencer-sequence () + "Insert section for the on-going cherry-pick or revert sequence. +If no such sequence is in progress, do nothing." + (let ((picking (magit-cherry-pick-in-progress-p))) + (when (or picking (magit-revert-in-progress-p)) + (magit-insert-section (sequence) + (magit-insert-heading (if picking "Cherry Picking" "Reverting")) + (when-let ((lines + (cdr (magit-file-lines (magit-git-dir "sequencer/todo"))))) + (dolist (line (nreverse lines)) + (when (string-match + "^\\(pick\\|revert\\) \\([^ ]+\\) \\(.*\\)$" line) + (magit-bind-match-strings (cmd hash msg) line + (magit-insert-section (commit hash) + (insert (propertize cmd 'font-lock-face 'magit-sequence-pick) + " " (propertize hash 'font-lock-face 'magit-hash) + " " msg "\n")))))) + (magit-sequence-insert-sequence + (magit-file-line (magit-git-dir (if picking + "CHERRY_PICK_HEAD" + "REVERT_HEAD"))) + (magit-file-line (magit-git-dir "sequencer/head"))) + (insert "\n"))))) + +(defun magit-insert-am-sequence () + "Insert section for the on-going patch applying sequence. +If no such sequence is in progress, do nothing." + (when (magit-am-in-progress-p) + (magit-insert-section (rebase-sequence) + (magit-insert-heading "Applying patches") + (let ((patches (nreverse (magit-rebase-patches))) + patch commit) + (while patches + (setq patch (pop patches)) + (setq commit (magit-commit-p + (cadr (split-string (magit-file-line patch))))) + (cond ((and commit patches) + (magit-sequence-insert-commit + "pick" commit 'magit-sequence-pick)) + (patches + (magit-sequence-insert-am-patch + "pick" patch 'magit-sequence-pick)) + (commit + (magit-sequence-insert-sequence commit "ORIG_HEAD")) + (t + (magit-sequence-insert-am-patch + "stop" patch 'magit-sequence-stop) + (magit-sequence-insert-sequence nil "ORIG_HEAD"))))) + (insert ?\n)))) + +(defun magit-sequence-insert-am-patch (type patch face) + (magit-insert-section (file patch) + (let ((title + (with-temp-buffer + (insert-file-contents patch nil nil 4096) + (unless (re-search-forward "^Subject: " nil t) + (goto-char (point-min))) + (buffer-substring (point) (line-end-position))))) + (insert (propertize type 'font-lock-face face) + ?\s (propertize (file-name-nondirectory patch) + 'font-lock-face 'magit-hash) + ?\s title + ?\n)))) + +(defun magit-insert-rebase-sequence () + "Insert section for the on-going rebase sequence. +If no such sequence is in progress, do nothing." + (when (magit-rebase-in-progress-p) + (let* ((interactive (file-directory-p (magit-git-dir "rebase-merge"))) + (dir (if interactive "rebase-merge/" "rebase-apply/")) + (name (-> (concat dir "head-name") magit-git-dir magit-file-line)) + (onto (-> (concat dir "onto") magit-git-dir magit-file-line)) + (onto (or (magit-rev-name onto name) + (magit-rev-name onto "refs/heads/*") onto)) + (name (or (magit-rev-name name "refs/heads/*") name))) + (magit-insert-section (rebase-sequence) + (magit-insert-heading (format "Rebasing %s onto %s" name onto)) + (if interactive + (magit-rebase-insert-merge-sequence onto) + (magit-rebase-insert-apply-sequence onto)) + (insert ?\n))))) + +(defun magit-rebase--todo () + "Return `git-rebase-action' instances for remaining rebase actions. +These are ordered in that the same way they'll be sorted in the +status buffer (i.e. the reverse of how they will be applied)." + (let ((comment-start (or (magit-get "core.commentChar") "#")) + lines) + (with-temp-buffer + (insert-file-contents (magit-git-dir "rebase-merge/git-rebase-todo")) + (while (not (eobp)) + (let ((ln (git-rebase-current-line))) + (when (oref ln action-type) + (push ln lines))) + (forward-line))) + lines)) + +(defun magit-rebase-insert-merge-sequence (onto) + (dolist (line (magit-rebase--todo)) + (with-slots (action-type action action-options target) line + (pcase action-type + (`commit + (magit-sequence-insert-commit action target 'magit-sequence-pick)) + ((or (or `exec `label) + (and `merge (guard (not action-options)))) + (insert (propertize action 'font-lock-face 'magit-sequence-onto) "\s" + (propertize target 'font-lock-face 'git-rebase-label) "\n")) + (`merge + (if-let ((hash (and (string-match "-[cC] \\([^ ]+\\)" action-options) + (match-string 1 action-options)))) + (magit-insert-section (commit hash) + (magit-insert-heading + (propertize "merge" 'font-lock-face 'magit-sequence-pick) + "\s" + (magit-format-rev-summary hash) "\n")) + (error "failed to parse merge message hash")))))) + (magit-sequence-insert-sequence + (magit-file-line (magit-git-dir "rebase-merge/stopped-sha")) + onto + (--when-let (magit-file-lines (magit-git-dir "rebase-merge/done")) + (cadr (split-string (car (last it))))))) + +(defun magit-rebase-insert-apply-sequence (onto) + (let ((rewritten + (--map (car (split-string it)) + (magit-file-lines (magit-git-dir "rebase-apply/rewritten")))) + (stop (magit-file-line (magit-git-dir "rebase-apply/original-commit")))) + (dolist (patch (nreverse (cdr (magit-rebase-patches)))) + (let ((hash (cadr (split-string (magit-file-line patch))))) + (unless (or (member hash rewritten) + (equal hash stop)) + (magit-sequence-insert-commit "pick" hash 'magit-sequence-pick))))) + (magit-sequence-insert-sequence + (magit-file-line (magit-git-dir "rebase-apply/original-commit")) + onto)) + +(defun magit-rebase-patches () + (directory-files (magit-git-dir "rebase-apply") t "^[0-9]\\{4\\}$")) + +(defun magit-sequence-insert-sequence (stop onto &optional orig) + (let ((head (magit-rev-parse "HEAD")) done) + (setq onto (if onto (magit-rev-parse onto) head)) + (setq done (magit-git-lines "log" "--format=%H" (concat onto "..HEAD"))) + (when (and stop (not (member (magit-rev-parse stop) done))) + (let ((id (magit-patch-id stop))) + (--if-let (--first (equal (magit-patch-id it) id) done) + (setq stop it) + (cond + ((--first (magit-rev-equal it stop) done) + ;; The commit's testament has been executed. + (magit-sequence-insert-commit "void" stop 'magit-sequence-drop)) + ;; The faith of the commit is still undecided... + ((magit-anything-unmerged-p) + ;; ...and time travel isn't for the faint of heart. + (magit-sequence-insert-commit "join" stop 'magit-sequence-part)) + ((magit-anything-modified-p t) + ;; ...and the dust hasn't settled yet... + (magit-sequence-insert-commit + (let* ((magit--refresh-cache nil) + (staged (magit-commit-tree "oO" nil "HEAD")) + (unstaged (magit-commit-worktree "oO" "--reset"))) + (cond + ;; ...but we could end up at the same tree just by committing. + ((or (magit-rev-equal staged stop) + (magit-rev-equal unstaged stop)) "goal") + ;; ...but the changes are still there, untainted. + ((or (equal (magit-patch-id staged) id) + (equal (magit-patch-id unstaged) id)) "same") + ;; ...and some changes are gone and/or others were added. + (t "work"))) + stop 'magit-sequence-part)) + ;; The commit is definitely gone... + ((--first (magit-rev-equal it stop) done) + ;; ...but all of its changes are still in effect. + (magit-sequence-insert-commit "poof" stop 'magit-sequence-drop)) + (t + ;; ...and some changes are gone and/or other changes were added. + (magit-sequence-insert-commit "gone" stop 'magit-sequence-drop))) + (setq stop nil)))) + (dolist (rev done) + (apply 'magit-sequence-insert-commit + (cond ((equal rev stop) + ;; ...but its reincarnation lives on. + ;; Or it didn't die in the first place. + (list (if (and (equal rev head) + (equal (magit-patch-id rev) + (magit-patch-id orig))) + "stop" ; We haven't done anything yet. + "like") ; There are new commits. + rev (if (equal rev head) + 'magit-sequence-head + 'magit-sequence-stop))) + ((equal rev head) + (list "done" rev 'magit-sequence-head)) + (t + (list "done" rev 'magit-sequence-done))))) + (magit-sequence-insert-commit "onto" onto + (if (equal onto head) + 'magit-sequence-head + 'magit-sequence-onto)))) + +(defun magit-sequence-insert-commit (type hash face) + (magit-insert-section (commit hash) + (magit-insert-heading + (propertize type 'font-lock-face face) "\s" + (magit-format-rev-summary hash) "\n"))) + +;;; _ +(provide 'magit-sequence) +;;; magit-sequence.el ends here diff --git a/elpa/magit-20191122.2040/magit-sequence.elc b/elpa/magit-20191122.2040/magit-sequence.elc new file mode 100644 index 0000000000000000000000000000000000000000..2f2a5b79755447ce88a33e11ddea4bdd9d826e82 GIT binary patch literal 52139 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

JQGVk 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 y|7E^->9BgoeDVL8+2Y%^OIV>-Z6tAm&KgL +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; Support for Git stashes. + +;;; Code: + +(eval-when-compile + (require 'subr-x)) + +(require 'magit) +(require 'magit-reflog) + +;;; Options + +(defgroup magit-stash nil + "List stashes and show stash diffs." + :group 'magit-modes) + +;;;; Diff options + +(defcustom magit-stash-sections-hook + '(magit-insert-stash-notes + magit-insert-stash-worktree + magit-insert-stash-index + magit-insert-stash-untracked) + "Hook run to insert sections into stash diff buffers." + :package-version '(magit . "2.1.0") + :group 'magit-stash + :type 'hook) + +;;;; Log options + +(defcustom magit-stashes-margin + (list (nth 0 magit-log-margin) + (nth 1 magit-log-margin) + 'magit-log-margin-width nil + (nth 4 magit-log-margin)) + "Format of the margin in `magit-stashes-mode' buffers. + +The value has the form (INIT STYLE WIDTH AUTHOR AUTHOR-WIDTH). + +If INIT is non-nil, then the margin is shown initially. +STYLE controls how to format the author or committer date. + It can be one of `age' (to show the age of the commit), + `age-abbreviated' (to abbreviate the time unit to a character), + or a string (suitable for `format-time-string') to show the + actual date. Option `magit-log-margin-show-committer-date' + controls which date is being displayed. +WIDTH controls the width of the margin. This exists for forward + compatibility and currently the value should not be changed. +AUTHOR controls whether the name of the author is also shown by + default. +AUTHOR-WIDTH has to be an integer. When the name of the author + is shown, then this specifies how much space is used to do so." + :package-version '(magit . "2.9.0") + :group 'magit-stash + :group 'magit-margin + :type magit-log-margin--custom-type + :initialize 'magit-custom-initialize-reset + :set-after '(magit-log-margin) + :set (apply-partially #'magit-margin-set-variable 'magit-stashes-mode)) + +;;; Commands + +;;;###autoload (autoload 'magit-stash "magit-stash" nil t) +(define-transient-command magit-stash () + "Stash uncommitted changes." + :man-page "git-stash" + ["Arguments" + ("-u" "Also save untracked files" ("-u" "--include-untracked")) + ("-a" "Also save untracked and ignored files" ("-a" "--all"))] + [["Stash" + ("z" "both" magit-stash-both) + ("i" "index" magit-stash-index) + ("w" "worktree" magit-stash-worktree) + ("x" "keeping index" magit-stash-keep-index)] + ["Snapshot" + ("Z" "both" magit-snapshot-both) + ("I" "index" magit-snapshot-index) + ("W" "worktree" magit-snapshot-worktree) + ("r" "to wip ref" magit-wip-commit)] + ["Use" + ("a" "Apply" magit-stash-apply) + ("p" "Pop" magit-stash-pop) + ("k" "Drop" magit-stash-drop)] + ["Inspect" + ("l" "List" magit-stash-list) + ("v" "Show" magit-stash-show)] + ["Transform" + ("b" "Branch" magit-stash-branch) + ("B" "Branch here" magit-stash-branch-here) + ("f" "Format patch" magit-stash-format-patch)]]) + +(defun magit-stash-arguments () + (transient-args 'magit-stash)) + +;;;###autoload +(defun magit-stash-both (message &optional include-untracked) + "Create a stash of the index and working tree. +Untracked files are included according to infix arguments. +One prefix argument is equivalent to `--include-untracked' +while two prefix arguments are equivalent to `--all'." + (interactive (magit-stash-read-args)) + (magit-stash-save message t t include-untracked t)) + +;;;###autoload +(defun magit-stash-index (message) + "Create a stash of the index only. +Unstaged and untracked changes are not stashed. The stashed +changes are applied in reverse to both the index and the +worktree. This command can fail when the worktree is not clean. +Applying the resulting stash has the inverse effect." + (interactive (list (magit-stash-read-message))) + (magit-stash-save message t nil nil t 'worktree)) + +;;;###autoload +(defun magit-stash-worktree (message &optional include-untracked) + "Create a stash of unstaged changes in the working tree. +Untracked files are included according to infix arguments. +One prefix argument is equivalent to `--include-untracked' +while two prefix arguments are equivalent to `--all'." + (interactive (magit-stash-read-args)) + (magit-stash-save message nil t include-untracked t 'index)) + +;;;###autoload +(defun magit-stash-keep-index (message &optional include-untracked) + "Create a stash of the index and working tree, keeping index intact. +Untracked files are included according to infix arguments. +One prefix argument is equivalent to `--include-untracked' +while two prefix arguments are equivalent to `--all'." + (interactive (magit-stash-read-args)) + (magit-stash-save message t t include-untracked t 'index)) + +(defun magit-stash-read-args () + (list (magit-stash-read-message) + (magit-stash-read-untracked))) + +(defun magit-stash-read-untracked () + (let ((prefix (prefix-numeric-value current-prefix-arg)) + (args (magit-stash-arguments))) + (cond ((or (= prefix 16) (member "--all" args)) 'all) + ((or (= prefix 4) (member "--include-untracked" args)) t)))) + +(defun magit-stash-read-message () + (let* ((default (format "On %s: " + (or (magit-get-current-branch) "(no branch)"))) + (input (magit-read-string "Stash message" default))) + (if (equal input default) + (concat default (magit-rev-format "%h %s")) + input))) + +;;;###autoload +(defun magit-snapshot-both (&optional include-untracked) + "Create a snapshot of the index and working tree. +Untracked files are included according to infix arguments. +One prefix argument is equivalent to `--include-untracked' +while two prefix arguments are equivalent to `--all'." + (interactive (magit-snapshot-read-args)) + (magit-snapshot-save t t include-untracked t)) + +;;;###autoload +(defun magit-snapshot-index () + "Create a snapshot of the index only. +Unstaged and untracked changes are not stashed." + (interactive) + (magit-snapshot-save t nil nil t)) + +;;;###autoload +(defun magit-snapshot-worktree (&optional include-untracked) + "Create a snapshot of unstaged changes in the working tree. +Untracked files are included according to infix arguments. +One prefix argument is equivalent to `--include-untracked' +while two prefix arguments are equivalent to `--all'." + (interactive (magit-snapshot-read-args)) + (magit-snapshot-save nil t include-untracked t)) + +(defun magit-snapshot-read-args () + (list (magit-stash-read-untracked))) + +(defun magit-snapshot-save (index worktree untracked &optional refresh) + (magit-stash-save (concat "WIP on " (magit-stash-summary)) + index worktree untracked refresh t)) + +;;;###autoload +(defun magit-stash-apply (stash) + "Apply a stash to the working tree. +Try to preserve the stash index. If that fails because there +are staged changes, apply without preserving the stash index." + (interactive (list (magit-read-stash "Apply stash"))) + (if (= (magit-call-git "stash" "apply" "--index" stash) 0) + (magit-refresh) + (magit-run-git "stash" "apply" stash))) + +(defun magit-stash-pop (stash) + "Apply a stash to the working tree and remove it from stash list. +Try to preserve the stash index. If that fails because there +are staged changes, apply without preserving the stash index +and forgo removing the stash." + (interactive (list (magit-read-stash "Pop stash"))) + (if (= (magit-call-git "stash" "apply" "--index" stash) 0) + (magit-stash-drop stash) + (magit-run-git "stash" "apply" stash))) + +;;;###autoload +(defun magit-stash-drop (stash) + "Remove a stash from the stash list. +When the region is active offer to drop all contained stashes." + (interactive + (list (--if-let (magit-region-values 'stash) + (magit-confirm 'drop-stashes nil "Drop %i stashes" nil it) + (magit-read-stash "Drop stash")))) + (dolist (stash (if (listp stash) + (nreverse (prog1 stash (setq stash (car stash)))) + (list stash))) + (message "Deleted refs/%s (was %s)" stash + (magit-rev-parse "--short" stash)) + (magit-call-git "rev-parse" stash) + (magit-call-git "reflog" "delete" "--updateref" "--rewrite" stash)) + (when-let ((ref (and (string-match "\\(.+\\)@{[0-9]+}$" stash) + (match-string 1 stash)))) + (unless (string-match "^refs/" ref) + (setq ref (concat "refs/" ref))) + (unless (magit-rev-verify (concat ref "@{0}")) + (magit-run-git "update-ref" "-d" ref))) + (magit-refresh)) + +;;;###autoload +(defun magit-stash-clear (ref) + "Remove all stashes saved in REF's reflog by deleting REF." + (interactive (let ((ref (or (magit-section-value-if 'stashes) "refs/stash"))) + (magit-confirm t (format "Drop all stashes in %s" ref)) + (list ref))) + (magit-run-git "update-ref" "-d" ref)) + +;;;###autoload +(defun magit-stash-branch (stash branch) + "Create and checkout a new BRANCH from STASH." + (interactive (list (magit-read-stash "Branch stash") + (magit-read-string-ns "Branch name"))) + (magit-run-git "stash" "branch" branch stash)) + +;;;###autoload +(defun magit-stash-branch-here (stash branch) + "Create and checkout a new BRANCH and apply STASH. +The branch is created using `magit-branch-and-checkout', using the +current branch or `HEAD' as the start-point." + (interactive (list (magit-read-stash "Branch stash") + (magit-read-string-ns "Branch name"))) + (let ((inhibit-magit-refresh t)) + (magit-branch-and-checkout branch (or (magit-get-current-branch) "HEAD"))) + (magit-stash-apply stash)) + +;;;###autoload +(defun magit-stash-format-patch (stash) + "Create a patch from STASH" + (interactive (list (magit-read-stash "Create patch from stash"))) + (with-temp-file (magit-rev-format "0001-%f.patch" stash) + (magit-git-insert "stash" "show" "-p" stash)) + (magit-refresh)) + +;;; Plumbing + +(defun magit-stash-save (message index worktree untracked + &optional refresh keep noerror ref) + (if (or (and index (magit-staged-files t)) + (and worktree (magit-unstaged-files t)) + (and untracked (magit-untracked-files (eq untracked 'all)))) + (magit-with-toplevel + (magit-stash-store message (or ref "refs/stash") + (magit-stash-create message index worktree untracked)) + (if (eq keep 'worktree) + (with-temp-buffer + (magit-git-insert "diff" "--cached") + (magit-run-git-with-input + "apply" "--reverse" "--cached" "--ignore-space-change" "-") + (magit-run-git-with-input + "apply" "--reverse" "--ignore-space-change" "-")) + (unless (eq keep t) + (if (eq keep 'index) + (magit-call-git "checkout" "--" ".") + (magit-call-git "reset" "--hard" "HEAD" "--")) + (when untracked + (magit-call-git "clean" "--force" "-d" + (and (eq untracked 'all) "-x"))))) + (when refresh + (magit-refresh))) + (unless noerror + (user-error "No %s changes to save" (cond ((not index) "unstaged") + ((not worktree) "staged") + (t "local")))))) + +(defun magit-stash-store (message ref commit) + (magit-update-ref ref message commit t)) + +(defun magit-stash-create (message index worktree untracked) + (unless (magit-rev-parse "--verify" "HEAD") + (error "You do not have the initial commit yet")) + (let ((magit-git-global-arguments (nconc (list "-c" "commit.gpgsign=false") + magit-git-global-arguments)) + (default-directory (magit-toplevel)) + (summary (magit-stash-summary)) + (head "HEAD")) + (when (and worktree (not index)) + (setq head (or (magit-commit-tree "pre-stash index" nil "HEAD") + (error "Cannot save the current index state")))) + (or (setq index (magit-commit-tree (concat "index on " summary) nil head)) + (error "Cannot save the current index state")) + (and untracked + (setq untracked (magit-untracked-files (eq untracked 'all))) + (setq untracked (magit-with-temp-index nil nil + (or (and (magit-update-files untracked) + (magit-commit-tree + (concat "untracked files on " summary))) + (error "Cannot save the untracked files"))))) + (magit-with-temp-index index "-m" + (when worktree + (or (magit-update-files (magit-git-items "diff" "-z" "--name-only" head)) + (error "Cannot save the current worktree state"))) + (or (magit-commit-tree message nil head index untracked) + (error "Cannot save the current worktree state"))))) + +(defun magit-stash-summary () + (concat (or (magit-get-current-branch) "(no branch)") + ": " (magit-rev-format "%h %s"))) + +;;; Sections + +(defvar magit-stashes-section-map + (let ((map (make-sparse-keymap))) + (define-key map [remap magit-delete-thing] 'magit-stash-clear) + map) + "Keymap for `stashes' section.") + +(defvar magit-stash-section-map + (let ((map (make-sparse-keymap))) + (define-key map [remap magit-visit-thing] 'magit-stash-show) + (define-key map [remap magit-delete-thing] 'magit-stash-drop) + (define-key map "a" 'magit-stash-apply) + (define-key map "A" 'magit-stash-pop) + map) + "Keymap for `stash' sections.") + +(magit-define-section-jumper magit-jump-to-stashes + "Stashes" stashes "refs/stash") + +(cl-defun magit-insert-stashes (&optional (ref "refs/stash") + (heading "Stashes:")) + "Insert `stashes' section showing reflog for \"refs/stash\". +If optional REF is non-nil, show reflog for that instead. +If optional HEADING is non-nil, use that as section heading +instead of \"Stashes:\"." + (let ((verified (magit-rev-verify ref)) + (autostash + (and (magit-rebase-in-progress-p) + (magit-file-line + (magit-git-dir + (-> (if (file-directory-p (magit-git-dir "rebase-merge")) + "rebase-merge/autostash" + "rebase-apply/autostash"))))))) + (when (or autostash verified) + (magit-insert-section (stashes ref) + (magit-insert-heading heading) + (when autostash + (pcase-let ((`(,author ,date ,msg) + (split-string + (car (magit-git-lines + "show" "-q" "--format=%aN%x00%at%x00%s" + autostash)) + "\0"))) + (magit-insert-section (stash autostash) + (insert (propertize "AUTOSTASH" 'font-lock-face 'magit-hash)) + (insert " " msg "\n") + (save-excursion + (backward-char) + (magit-log-format-margin autostash author date))))) + (if verified + (magit-git-wash (apply-partially 'magit-log-wash-log 'stash) + "reflog" "--format=%gd%x00%aN%x00%at%x00%gs" ref) + (insert ?\n) + (save-excursion + (backward-char) + (magit-make-margin-overlay))))))) + +;;; List Stashes + +;;;###autoload +(defun magit-stash-list () + "List all stashes in a buffer." + (interactive) + (magit-stashes-setup-buffer)) + +(define-derived-mode magit-stashes-mode magit-reflog-mode "Magit Stashes" + "Mode for looking at lists of stashes." + :group 'magit-log + (hack-dir-local-variables-non-file-buffer)) + +(defun magit-stashes-setup-buffer () + (magit-setup-buffer #'magit-stashes-mode nil + (magit-buffer-refname "refs/stash"))) + +(defun magit-stashes-refresh-buffer () + (magit-insert-section (stashesbuf) + (magit-insert-heading (if (equal magit-buffer-refname "refs/stash") + "Stashes:" + (format "Stashes [%s]:" magit-buffer-refname))) + (magit-git-wash (apply-partially 'magit-log-wash-log 'stash) + "reflog" "--format=%gd%x00%aN%x00%at%x00%gs" magit-buffer-refname))) + +(cl-defmethod magit-buffer-value (&context (major-mode magit-stashes-mode)) + magit-buffer-refname) + +(defvar magit--update-stash-buffer nil) + +(defun magit-stashes-maybe-update-stash-buffer (&optional _) + "When moving in the stashes buffer, update the stash buffer. +If there is no stash buffer in the same frame, then do nothing." + (when (derived-mode-p 'magit-stashes-mode) + (magit--maybe-update-stash-buffer))) + +(defun magit--maybe-update-stash-buffer () + (when-let ((stash (magit-section-value-if 'stash)) + (buffer (magit-get-mode-buffer 'magit-stash-mode nil t))) + (if magit--update-stash-buffer + (setq magit--update-stash-buffer (list stash buffer)) + (setq magit--update-stash-buffer (list stash buffer)) + (run-with-idle-timer + magit-update-other-window-delay nil + (let ((args (with-current-buffer buffer + (let ((magit-direct-use-buffer-arguments 'selected)) + (magit-show-commit--arguments))))) + (lambda () + (pcase-let ((`(,stash ,buf) magit--update-stash-buffer)) + (setq magit--update-stash-buffer nil) + (when (buffer-live-p buf) + (let ((magit-display-buffer-noselect t)) + (apply #'magit-stash-show stash args)))) + (setq magit--update-stash-buffer nil))))))) + +;;; Show Stash + +;;;###autoload +(defun magit-stash-show (stash &optional args files) + "Show all diffs of a stash in a buffer." + (interactive (cons (or (and (not current-prefix-arg) + (magit-stash-at-point)) + (magit-read-stash "Show stash")) + (pcase-let ((`(,args ,files) + (magit-diff-arguments 'magit-stash-mode))) + (list (delete "--stat" args) files)))) + (magit-stash-setup-buffer stash args files)) + +(define-derived-mode magit-stash-mode magit-diff-mode "Magit Stash" + "Mode for looking at individual stashes." + :group 'magit-diff + (hack-dir-local-variables-non-file-buffer)) + +(defun magit-stash-setup-buffer (stash args files) + (magit-setup-buffer #'magit-stash-mode nil + (magit-buffer-revision stash) + (magit-buffer-range (format "%s^..%s" stash stash)) + (magit-buffer-diff-args args) + (magit-buffer-diff-files files))) + +(defun magit-stash-refresh-buffer () + (magit-set-header-line-format + (concat (capitalize magit-buffer-revision) " " + (propertize (magit-rev-format "%s" magit-buffer-revision) + 'font-lock-face + (list :weight 'normal :foreground + (face-attribute 'default :foreground))))) + (setq magit-buffer-revision-hash (magit-rev-parse magit-buffer-revision)) + (magit-insert-section (stash) + (magit-run-section-hook 'magit-stash-sections-hook))) + +(cl-defmethod magit-buffer-value (&context (major-mode magit-stash-mode)) + magit-buffer-revision) + +(defun magit-stash-insert-section (commit range message &optional files) + (magit-insert-section (commit commit) + (magit-insert-heading message) + (magit--insert-diff "diff" range "-p" "--no-prefix" magit-buffer-diff-args + "--" (or files magit-buffer-diff-files)))) + +(defun magit-insert-stash-notes () + "Insert section showing notes for a stash. +This shows the notes for stash@{N} but not for the other commits +that make up the stash." + (magit-insert-section section (note) + (magit-insert-heading "Notes") + (magit-git-insert "notes" "show" magit-buffer-revision) + (if (= (point) + (oref section content)) + (magit-cancel-section) + (insert "\n")))) + +(defun magit-insert-stash-index () + "Insert section showing staged changes of the stash." + (magit-stash-insert-section + (format "%s^2" magit-buffer-revision) + (format "%s^..%s^2" magit-buffer-revision magit-buffer-revision) + "Staged")) + +(defun magit-insert-stash-worktree () + "Insert section showing unstaged changes of the stash." + (magit-stash-insert-section + magit-buffer-revision + (format "%s^2..%s" magit-buffer-revision magit-buffer-revision) + "Unstaged")) + +(defun magit-insert-stash-untracked () + "Insert section showing the untracked files commit of the stash." + (let ((stash magit-buffer-revision) + (rev (concat magit-buffer-revision "^3"))) + (when (magit-rev-verify rev) + (magit-stash-insert-section (format "%s^3" stash) + (format "%s^..%s^3" stash stash) + "Untracked files" + (magit-git-items "ls-tree" "-z" "--name-only" + "-r" "--full-tree" rev))))) + +;;; _ +(provide 'magit-stash) +;;; magit-stash.el ends here diff --git a/elpa/magit-20191122.2040/magit-stash.elc b/elpa/magit-20191122.2040/magit-stash.elc new file mode 100644 index 0000000000000000000000000000000000000000..38c33acd97be91de113d0642be730803c96f4fb0 GIT binary patch literal 35517 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 literal 0 HcmV?d00001 diff --git a/elpa/magit-20191122.2040/magit-status.el b/elpa/magit-20191122.2040/magit-status.el new file mode 100644 index 00000000..fc0059e3 --- /dev/null +++ b/elpa/magit-20191122.2040/magit-status.el @@ -0,0 +1,793 @@ +;;; magit-status.el --- the grand overview -*- lexical-binding: t -*- + +;; Copyright (C) 2010-2019 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; This library implements the status buffer. + +;;; Code: + +(eval-when-compile + (require 'subr-x)) + +(require 'magit) + +;;; Options + +(defgroup magit-status nil + "Inspect and manipulate Git repositories." + :link '(info-link "(magit)Status Buffer") + :group 'magit-modes) + +(defcustom magit-status-mode-hook nil + "Hook run after entering Magit-Status mode." + :group 'magit-status + :type 'hook) + +(defcustom magit-status-headers-hook + '(magit-insert-error-header + magit-insert-diff-filter-header + magit-insert-head-branch-header + magit-insert-upstream-branch-header + magit-insert-push-branch-header + magit-insert-tags-header) + "Hook run to insert headers into the status buffer. + +This hook is run by `magit-insert-status-headers', which in turn +has to be a member of `magit-status-sections-hook' to be used at +all." + :package-version '(magit . "2.1.0") + :group 'magit-status + :type 'hook + :options '(magit-insert-error-header + magit-insert-diff-filter-header + magit-insert-repo-header + magit-insert-remote-header + magit-insert-head-branch-header + magit-insert-upstream-branch-header + magit-insert-push-branch-header + magit-insert-tags-header)) + +(defcustom magit-status-sections-hook + '(magit-insert-status-headers + magit-insert-merge-log + magit-insert-rebase-sequence + magit-insert-am-sequence + magit-insert-sequencer-sequence + magit-insert-bisect-output + magit-insert-bisect-rest + magit-insert-bisect-log + magit-insert-untracked-files + magit-insert-unstaged-changes + magit-insert-staged-changes + magit-insert-stashes + magit-insert-unpushed-to-pushremote + magit-insert-unpushed-to-upstream-or-recent + magit-insert-unpulled-from-pushremote + magit-insert-unpulled-from-upstream) + "Hook run to insert sections into a status buffer." + :package-version '(magit . "2.12.0") + :group 'magit-status + :type 'hook) + +(defcustom magit-status-initial-section '(1) + "The section point is placed on when a status buffer is created. + +When such a buffer is merely being refreshed or being shown again +after it was merely buried, then this option has no effect. + +If this is nil, then point remains on the very first section as +usual. Otherwise it has to be a list of integers and section +identity lists. The members of that list are tried in order +until a matching section is found. + +An integer means to jump to the nth section, 1 for example +jumps over the headings. To get a section's \"identity list\" +use \\[universal-argument] \\[magit-describe-section-briefly]. + +If, for example, you want to jump to the commits that haven't +been pulled from the upstream, or else the second section, then +use: (((unpulled . \"..@{upstream}\") (status)) 1). + +See option `magit-section-initial-visibility-alist' for how to +control the initial visibility of the jumped to section." + :package-version '(magit . "2.90.0") + :group 'magit-status + :type '(choice (const :tag "as usual" nil) + (repeat (choice (number :tag "nth top-level section") + (sexp :tag "section identity"))))) + +(defcustom magit-status-goto-file-position nil + "Whether to go to position corresponding to file position. + +If this is non-nil and the current buffer is visiting a file, +then `magit-status' tries to go to the position in the status +buffer that corresponds to the position in the file-visiting +buffer. This jumps into either the diff of unstaged changes +or the diff of staged changes. + +If the previously current buffer does not visit a file, or if +the file has neither unstaged nor staged changes then this has +no effect. + +The command `magit-status-here' tries to go to that position, +regardless of the value of this option." + :package-version '(magit . "2.91.0") + :group 'magit-status + :type 'boolean) + +(defcustom magit-status-show-hashes-in-headers nil + "Whether headers in the status buffer show hashes. +The functions which respect this option are +`magit-insert-head-branch-header', +`magit-insert-upstream-branch-header', and +`magit-insert-push-branch-header'." + :package-version '(magit . "2.4.0") + :group 'magit-status + :type 'boolean) + +(defcustom magit-status-margin + (list nil + (nth 1 magit-log-margin) + 'magit-log-margin-width nil + (nth 4 magit-log-margin)) + "Format of the margin in `magit-status-mode' buffers. + +The value has the form (INIT STYLE WIDTH AUTHOR AUTHOR-WIDTH). + +If INIT is non-nil, then the margin is shown initially. +STYLE controls how to format the author or committer date. + It can be one of `age' (to show the age of the commit), + `age-abbreviated' (to abbreviate the time unit to a character), + or a string (suitable for `format-time-string') to show the + actual date. Option `magit-log-margin-show-committer-date' + controls which date is being displayed. +WIDTH controls the width of the margin. This exists for forward + compatibility and currently the value should not be changed. +AUTHOR controls whether the name of the author is also shown by + default. +AUTHOR-WIDTH has to be an integer. When the name of the author + is shown, then this specifies how much space is used to do so." + :package-version '(magit . "2.9.0") + :group 'magit-status + :group 'magit-margin + :type magit-log-margin--custom-type + :initialize 'magit-custom-initialize-reset + :set-after '(magit-log-margin) + :set (apply-partially #'magit-margin-set-variable 'magit-status-mode)) + +;;; Commands + +;;;###autoload +(defun magit-init (directory) + "Initialize a Git repository, then show its status. + +If the directory is below an existing repository, then the user +has to confirm that a new one should be created inside. If the +directory is the root of the existing repository, then the user +has to confirm that it should be reinitialized. + +Non-interactively DIRECTORY is (re-)initialized unconditionally." + (interactive + (let ((directory (file-name-as-directory + (expand-file-name + (read-directory-name "Create repository in: "))))) + (when-let ((toplevel (magit-toplevel directory))) + (setq toplevel (expand-file-name toplevel)) + (unless (y-or-n-p (if (file-equal-p toplevel directory) + (format "Reinitialize existing repository %s? " + directory) + (format "%s is a repository. Create another in %s? " + toplevel directory))) + (user-error "Abort"))) + (list directory))) + ;; `git init' does not understand the meaning of "~"! + (magit-call-git "init" (magit-convert-filename-for-git + (expand-file-name directory))) + (magit-status-setup-buffer directory)) + +;;;###autoload +(defun magit-status (&optional directory cache) + "Show the status of the current Git repository in a buffer. + +If the current directory isn't located within a Git repository, +then prompt for an existing repository or an arbitrary directory, +depending on option `magit-repository-directories', and show the +status of the selected repository instead. + +* If that option specifies any existing repositories, then offer + those for completion and show the status buffer for the + selected one. + +* Otherwise read an arbitrary directory using regular file-name + completion. If the selected directory is the top-level of an + existing working tree, then show the status buffer for that. + +* Otherwise offer to initialize the selected directory as a new + repository. After creating the repository show its status + buffer. + +These fallback behaviors can also be forced using one or more +prefix arguments: + +* With two prefix arguments (or more precisely a numeric prefix + value of 16 or greater) read an arbitrary directory and act on + it as described above. The same could be accomplished using + the command `magit-init'. + +* With a single prefix argument read an existing repository, or + if none can be found based on `magit-repository-directories', + then fall back to the same behavior as with two prefix + arguments." + (interactive + (let ((magit--refresh-cache (list (cons 0 0)))) + (list (and (or current-prefix-arg (not (magit-toplevel))) + (magit-read-repository + (>= (prefix-numeric-value current-prefix-arg) 16))) + magit--refresh-cache))) + (let ((magit--refresh-cache (or cache (list (cons 0 0))))) + (if directory + (let ((toplevel (magit-toplevel directory))) + (setq directory (file-name-as-directory + (expand-file-name directory))) + (if (and toplevel (file-equal-p directory toplevel)) + (magit-status-setup-buffer directory) + (when (y-or-n-p + (if toplevel + (format "%s is a repository. Create another in %s? " + toplevel directory) + (format "Create repository in %s? " directory))) + ;; Creating a new repository invalidates cached values. + (setq magit--refresh-cache nil) + (magit-init directory)))) + (magit-status-setup-buffer default-directory)))) + +(put 'magit-status 'interactive-only 'magit-status-setup-buffer) + +;;;###autoload +(defalias 'magit 'magit-status + "An alias for `magit-status' for better discoverability. + +Instead of invoking this alias for `magit-status' using +\"M-x magit RET\", you should bind a key to `magit-status' +and read the info node `(magit)Getting Started', which +also contains other useful hints.") + +;;;###autoload +(defun magit-status-here () + "Like `magit-status' but with non-nil `magit-status-goto-file-position'." + (interactive) + (let ((magit-status-goto-file-position t)) + (call-interactively #'magit-status))) + +(put 'magit-status-here 'interactive-only 'magit-status-setup-buffer) + +(defvar magit--remotes-using-recent-git nil) + +(defun magit--tramp-asserts (directory) + (when-let ((remote (file-remote-p directory))) + (unless (member remote magit--remotes-using-recent-git) + (if-let ((version (let ((default-directory directory)) + (magit-git-version)))) + (if (version<= magit--minimal-git version) + (push version magit--remotes-using-recent-git) + (display-warning 'magit (format "\ +Magit requires Git >= %s, but on %s the version is %s. + +If multiple Git versions are installed on the host, then the +problem might be that TRAMP uses the wrong executable. + +First check the value of `magit-git-executable'. Its value is +used when running git locally as well as when running it on a +remote host. The default value is \"git\", except on Windows +where an absolute path is used for performance reasons. + +If the value already is just \"git\" but TRAMP never-the-less +doesn't use the correct executable, then consult the info node +`(tramp)Remote programs'.\n" magit--minimal-git remote version) :error)) + (display-warning 'magit (format "\ +Magit cannot find Git on %s. + +First check the value of `magit-git-executable'. Its value is +used when running git locally as well as when running it on a +remote host. The default value is \"git\", except on Windows +where an absolute path is used for performance reasons. + +If the value already is just \"git\" but TRAMP never-the-less +doesn't find the executable, then consult the info node +`(tramp)Remote programs'.\n" remote) :error))))) + +;;; Mode + +(defvar magit-status-mode-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map magit-mode-map) + (define-key map "jz" 'magit-jump-to-stashes) + (define-key map "jt" 'magit-jump-to-tracked) + (define-key map "jn" 'magit-jump-to-untracked) + (define-key map "ju" 'magit-jump-to-unstaged) + (define-key map "js" 'magit-jump-to-staged) + (define-key map "jfu" 'magit-jump-to-unpulled-from-upstream) + (define-key map "jfp" 'magit-jump-to-unpulled-from-pushremote) + (define-key map "jpu" 'magit-jump-to-unpushed-to-upstream) + (define-key map "jpp" 'magit-jump-to-unpushed-to-pushremote) + (define-key map "ja" 'magit-jump-to-assume-unchanged) + (define-key map "jw" 'magit-jump-to-skip-worktree) + (define-key map [remap dired-jump] 'magit-dired-jump) + map) + "Keymap for `magit-status-mode'.") + +(define-derived-mode magit-status-mode magit-mode "Magit" + "Mode for looking at Git status. + +This mode is documented in info node `(magit)Status Buffer'. + +\\\ +Type \\[magit-refresh] to refresh the current buffer. +Type \\[magit-section-toggle] to expand or hide the section at point. +Type \\[magit-visit-thing] to visit the change or commit at point. + +Type \\[magit-dispatch] to invoke major commands. + +Staging and applying changes is documented in info node +`(magit)Staging and Unstaging' and info node `(magit)Applying'. + +\\Type \ +\\[magit-apply] to apply the change at point, \ +\\[magit-stage] to stage, +\\[magit-unstage] to unstage, \ +\\[magit-discard] to discard, or \ +\\[magit-reverse] to reverse it. + +\\\ +Type \\[magit-commit] to create a commit. + +\\{magit-status-mode-map}" + :group 'magit-status + (hack-dir-local-variables-non-file-buffer) + (setq imenu-create-index-function + 'magit-imenu--status-create-index-function)) + +(put 'magit-status-mode 'magit-diff-default-arguments + '("--no-ext-diff")) +(put 'magit-status-mode 'magit-log-default-arguments + '("-n256" "--decorate")) + +;;;###autoload +(defun magit-status-setup-buffer (&optional directory) + (unless directory + (setq directory default-directory)) + (magit--tramp-asserts directory) + (let* ((default-directory directory) + (d (magit-diff--get-value 'magit-status-mode)) + (l (magit-log--get-value 'magit-status-mode)) + (file (and magit-status-goto-file-position + (magit-file-relative-name))) + (line (and file (line-number-at-pos))) + (col (and file (current-column))) + (buf (magit-setup-buffer #'magit-status-mode nil + (magit-buffer-diff-args (nth 0 d)) + (magit-buffer-diff-files (nth 1 d)) + (magit-buffer-log-args (nth 0 l)) + (magit-buffer-log-files (nth 1 l))))) + (when file + (with-current-buffer buf + (let ((staged (magit-get-section '((staged) (status))))) + (if (and staged + (cadr (magit-diff--locate-hunk file line staged))) + (magit-diff--goto-position file line col staged) + (let ((unstaged (magit-get-section '((unstaged) (status))))) + (unless (and unstaged + (magit-diff--goto-position file line col unstaged)) + (when staged + (magit-diff--goto-position file line col staged)))))))) + buf)) + +(defun magit-status-refresh-buffer () + (magit-git-exit-code "update-index" "--refresh") + (magit-insert-section (status) + (magit-run-section-hook 'magit-status-sections-hook))) + +(defun magit-status-goto-initial-section () + "In a `magit-status-mode' buffer, jump `magit-status-initial-section'. +Actually doing so is deferred until `magit-refresh-buffer-hook' +runs `magit-status-goto-initial-section-1'. That function then +removes itself from the hook, so that this only happens when the +status buffer is first created." + (when (and magit-status-initial-section + (derived-mode-p 'magit-status-mode)) + (add-hook 'magit-refresh-buffer-hook + 'magit-status-goto-initial-section-1 nil t))) + +(defun magit-status-goto-initial-section-1 () + "In a `magit-status-mode' buffer, jump `magit-status-initial-section'. +This function removes itself from `magit-refresh-buffer-hook'." + (when-let ((section + (--some (if (integerp it) + (nth (1- it) + (magit-section-siblings (magit-current-section) + 'next)) + (magit-get-section it)) + magit-status-initial-section))) + (goto-char (oref section start)) + (when-let ((vis (cdr (assq 'magit-status-initial-section + magit-section-initial-visibility-alist)))) + (if (eq vis 'hide) + (magit-section-hide section) + (magit-section-show section)))) + (remove-hook 'magit-refresh-buffer-hook + 'magit-status-goto-initial-section-1 t)) + +(defun magit-status-maybe-update-revision-buffer (&optional _) + "When moving in the status buffer, update the revision buffer. +If there is no revision buffer in the same frame, then do nothing." + (when (derived-mode-p 'magit-status-mode) + (magit--maybe-update-revision-buffer))) + +(defun magit-status-maybe-update-stash-buffer (&optional _) + "When moving in the status buffer, update the stash buffer. +If there is no stash buffer in the same frame, then do nothing." + (when (derived-mode-p 'magit-status-mode) + (magit--maybe-update-stash-buffer))) + +(defun magit-status-maybe-update-blob-buffer (&optional _) + "When moving in the status buffer, update the blob buffer. +If there is no blob buffer in the same frame, then do nothing." + (when (derived-mode-p 'magit-status-mode) + (magit--maybe-update-blob-buffer))) + +;;; Sections +;;;; Special Headers + +(defun magit-insert-status-headers () + "Insert header sections appropriate for `magit-status-mode' buffers. +The sections are inserted by running the functions on the hook +`magit-status-headers-hook'." + (if (magit-rev-verify "HEAD") + (magit-insert-headers 'magit-status-headers-hook) + (insert "In the beginning there was darkness\n\n"))) + +(defvar magit-error-section-map + (let ((map (make-sparse-keymap))) + (define-key map [remap magit-visit-thing] 'magit-process-buffer) + map) + "Keymap for `error' sections.") + +(defun magit-insert-error-header () + "Insert the message about the Git error that just occurred. + +This function is only aware of the last error that occur when Git +was run for side-effects. If, for example, an error occurs while +generating a diff, then that error won't be inserted. Refreshing +the status buffer causes this section to disappear again." + (when magit-this-error + (magit-insert-section (error 'git) + (insert (propertize (format "%-10s" "GitError! ") + 'font-lock-face 'magit-section-heading)) + (insert (propertize magit-this-error + 'font-lock-face 'font-lock-warning-face)) + (when-let ((key (car (where-is-internal 'magit-process-buffer)))) + (insert (format " [Type `%s' for details]" (key-description key)))) + (insert ?\n)) + (setq magit-this-error nil))) + +(defun magit-insert-diff-filter-header () + "Insert a header line showing the effective diff filters." + (let ((ignore-modules (magit-ignore-submodules-p))) + (when (or ignore-modules + magit-buffer-diff-files) + (insert (propertize (format "%-10s" "Filter! ") + 'font-lock-face 'magit-section-heading)) + (when ignore-modules + (insert ignore-modules) + (when magit-buffer-diff-files + (insert " -- "))) + (when magit-buffer-diff-files + (insert (mapconcat #'identity magit-buffer-diff-files " "))) + (insert ?\n)))) + +;;;; Reference Headers + +(defun magit-insert-head-branch-header (&optional branch) + "Insert a header line about the current branch. +If `HEAD' is detached, then insert information about that commit +instead. The optional BRANCH argument is for internal use only." + (let ((branch (or branch (magit-get-current-branch))) + (output (magit-rev-format "%h %s" (or branch "HEAD")))) + (string-match "^\\([^ ]+\\) \\(.*\\)" output) + (magit-bind-match-strings (commit summary) output + (when (equal summary "") + (setq summary "(no commit message)")) + (if branch + (magit-insert-section (branch branch) + (insert (format "%-10s" "Head: ")) + (when magit-status-show-hashes-in-headers + (insert (propertize commit 'font-lock-face 'magit-hash) ?\s)) + (insert (propertize branch 'font-lock-face 'magit-branch-local)) + (insert ?\s) + (insert (funcall magit-log-format-message-function branch summary)) + (insert ?\n)) + (magit-insert-section (commit commit) + (insert (format "%-10s" "Head: ")) + (insert (propertize commit 'font-lock-face 'magit-hash)) + (insert ?\s) + (insert (funcall magit-log-format-message-function nil summary)) + (insert ?\n)))))) + +(defun magit-insert-upstream-branch-header (&optional branch upstream keyword) + "Insert a header line about the upstream of the current branch. +If no branch is checked out, then insert nothing. The optional +arguments are for internal use only." + (when-let ((branch (or branch (magit-get-current-branch)))) + (let ((remote (magit-get "branch" branch "remote")) + (merge (magit-get "branch" branch "merge")) + (rebase (magit-get "branch" branch "rebase"))) + (when (or remote merge) + (unless upstream + (setq upstream (magit-get-upstream-branch branch))) + (magit-insert-section (branch upstream) + (pcase rebase + ("true") + ("false" (setq rebase nil)) + (_ (setq rebase (magit-get-boolean "pull.rebase")))) + (insert (format "%-10s" (or keyword (if rebase "Rebase: " "Merge: ")))) + (insert + (if upstream + (concat (and magit-status-show-hashes-in-headers + (concat (propertize (magit-rev-format "%h" upstream) + 'font-lock-face 'magit-hash) + " ")) + upstream " " + (funcall magit-log-format-message-function upstream + (funcall magit-log-format-message-function nil + (or (magit-rev-format "%s" upstream) + "(no commit message)")))) + (cond + ((magit--unnamed-upstream-p remote merge) + (concat (propertize merge 'font-lock-face 'magit-branch-remote) + " from " + (propertize remote 'font-lock-face 'bold))) + ((magit--valid-upstream-p remote merge) + (if (equal remote ".") + (concat + (propertize merge 'font-lock-face 'magit-branch-local) + (propertize " does not exist" + 'font-lock-face 'font-lock-warning-face)) + (concat + (propertize merge 'font-lock-face 'magit-branch-remote) + (propertize " does not exist on " + 'font-lock-face 'font-lock-warning-face) + (propertize remote 'font-lock-face 'magit-branch-remote)))) + (t + (propertize "invalid upstream configuration" + 'font-lock-face 'font-lock-warning-face))))) + (insert ?\n)))))) + +(defun magit-insert-push-branch-header () + "Insert a header line about the branch the current branch is pushed to." + (when-let ((branch (magit-get-current-branch)) + (target (magit-get-push-branch branch))) + (magit-insert-section (branch target) + (insert (format "%-10s" "Push: ")) + (insert + (if (magit-rev-verify target) + (concat target " " + (and magit-status-show-hashes-in-headers + (concat (propertize (magit-rev-format "%h" target) + 'font-lock-face 'magit-hash) + " ")) + (funcall magit-log-format-message-function target + (funcall magit-log-format-message-function nil + (or (magit-rev-format "%s" target) + "(no commit message)")))) + (let ((remote (magit-get-push-remote branch))) + (if (magit-remote-p remote) + (concat target + (propertize " does not exist" + 'font-lock-face 'font-lock-warning-face)) + (concat remote + (propertize " remote does not exist" + 'font-lock-face 'font-lock-warning-face)))))) + (insert ?\n)))) + +(defun magit-insert-tags-header () + "Insert a header line about the current and/or next tag." + (let* ((this-tag (magit-get-current-tag nil t)) + (next-tag (magit-get-next-tag nil t)) + (this-cnt (cadr this-tag)) + (next-cnt (cadr next-tag)) + (this-tag (car this-tag)) + (next-tag (car next-tag)) + (both-tags (and this-tag next-tag t))) + (when (or this-tag next-tag) + (magit-insert-section (tag (or this-tag next-tag)) + (insert (format "%-10s" (if both-tags "Tags: " "Tag: "))) + (cl-flet ((insert-count + (tag count face) + (insert (concat (propertize tag 'font-lock-face 'magit-tag) + (and (> count 0) + (format " (%s)" + (propertize + (format "%s" count) + 'font-lock-face face))))))) + (when this-tag (insert-count this-tag this-cnt 'magit-branch-local)) + (when both-tags (insert ", ")) + (when next-tag (insert-count next-tag next-cnt 'magit-tag))) + (insert ?\n))))) + +;;;; Auxiliary Headers + +(defun magit-insert-user-header () + "Insert a header line about the current user." + (let ((name (magit-get "user.name")) + (email (magit-get "user.email"))) + (when (and name email) + (magit-insert-section (user name) + (insert (format "%-10s" "User: ")) + (insert (propertize name 'font-lock-face 'magit-log-author)) + (insert " <" email ">\n"))))) + +(defun magit-insert-repo-header () + "Insert a header line showing the path to the repository top-level." + (let ((topdir (magit-toplevel))) + (magit-insert-section (repo topdir) + (insert (format "%-10s%s\n" "Repo: " (abbreviate-file-name topdir)))))) + +(defun magit-insert-remote-header () + "Insert a header line about the remote of the current branch. + +If no remote is configured for the current branch, then fall back +showing the \"origin\" remote, or if that does not exist the first +remote in alphabetic order." + (when-let ((name (magit-get-some-remote)) + ;; Under certain configurations it's possible for url + ;; to be nil, when name is not, see #2858. + (url (magit-get "remote" name "url"))) + (magit-insert-section (remote name) + (insert (format "%-10s" "Remote: ")) + (insert (propertize name 'font-lock-face 'magit-branch-remote) ?\s) + (insert url ?\n)))) + +;;;; File Sections + +(defvar magit-untracked-section-map + (let ((map (make-sparse-keymap))) + (define-key map [remap magit-delete-thing] 'magit-discard) + (define-key map "s" 'magit-stage) + map) + "Keymap for the `untracked' section.") + +(magit-define-section-jumper magit-jump-to-untracked "Untracked files" untracked) + +(defun magit-insert-untracked-files () + "Maybe insert a list or tree of untracked files. + +Do so depending on the value of `status.showUntrackedFiles'. +Note that even if the value is `all', Magit still initially +only shows directories. But the directory sections can then +be expanded using \"TAB\". + +If the first element of `magit-buffer-diff-files' is a +directory, then limit the list to files below that. The value +value of that variable can be set using \"D -- DIRECTORY RET g\"." + (let* ((show (or (magit-get "status.showUntrackedFiles") "normal")) + (base (car magit-buffer-diff-files)) + (base (and base (file-directory-p base) base))) + (unless (equal show "no") + (if (equal show "all") + (when-let ((files (magit-untracked-files nil base))) + (magit-insert-section (untracked) + (magit-insert-heading "Untracked files:") + (magit-insert-files files base) + (insert ?\n))) + (when-let ((files + (--mapcat (and (eq (aref it 0) ??) + (list (substring it 3))) + (magit-git-items "status" "-z" "--porcelain" + (magit-ignore-submodules-p) + "--" base)))) + (magit-insert-section (untracked) + (magit-insert-heading "Untracked files:") + (dolist (file files) + (magit-insert-section (file file) + (insert (propertize file 'font-lock-face 'magit-filename) ?\n))) + (insert ?\n))))))) + +(magit-define-section-jumper magit-jump-to-tracked "Tracked files" tracked) + +(defun magit-insert-tracked-files () + "Insert a tree of tracked files. + +If the first element of `magit-buffer-diff-files' is a +directory, then limit the list to files below that. The value +value of that variable can be set using \"D -- DIRECTORY RET g\"." + (when-let ((files (magit-list-files))) + (let* ((base (car magit-buffer-diff-files)) + (base (and base (file-directory-p base) base))) + (magit-insert-section (tracked nil t) + (magit-insert-heading "Tracked files:") + (magit-insert-files files base) + (insert ?\n))))) + +(defun magit-insert-ignored-files () + "Insert a tree of ignored files. + +If the first element of `magit-buffer-diff-files' is a +directory, then limit the list to files below that. The value +of that variable can be set using \"D -- DIRECTORY RET g\"." + (when-let ((files (magit-ignored-files))) + (let* ((base (car magit-buffer-diff-files)) + (base (and base (file-directory-p base) base))) + (magit-insert-section (tracked nil t) + (magit-insert-heading "Ignored files:") + (magit-insert-files files base) + (insert ?\n))))) + +(magit-define-section-jumper magit-jump-to-skip-worktree "Skip-worktree files" skip-worktree) + +(defun magit-insert-skip-worktree-files () + "Insert a tree of skip-worktree files. + +If the first element of `magit-buffer-diff-files' is a +directory, then limit the list to files below that. The value +of that variable can be set using \"D -- DIRECTORY RET g\"." + (when-let ((files (magit-skip-worktree-files))) + (let* ((base (car magit-buffer-diff-files)) + (base (and base (file-directory-p base) base))) + (magit-insert-section (skip-worktree nil t) + (magit-insert-heading "Skip-worktree files:") + (magit-insert-files files base) + (insert ?\n))))) + +(magit-define-section-jumper magit-jump-to-assume-unchanged "Assume-unchanged files" assume-unchanged) + +(defun magit-insert-assume-unchanged-files () + "Insert a tree of files that are assumed to be unchanged. + +If the first element of `magit-buffer-diff-files' is a +directory, then limit the list to files below that. The value +of that variable can be set using \"D -- DIRECTORY RET g\"." + (when-let ((files (magit-assume-unchanged-files))) + (let* ((base (car magit-buffer-diff-files)) + (base (and base (file-directory-p base) base))) + (magit-insert-section (assume-unchanged nil t) + (magit-insert-heading "Assume-unchanged files:") + (magit-insert-files files base) + (insert ?\n))))) + +(defun magit-insert-files (files directory) + (while (and files (string-prefix-p (or directory "") (car files))) + (let ((dir (file-name-directory (car files)))) + (if (equal dir directory) + (let ((file (pop files))) + (magit-insert-section (file file) + (insert (propertize file 'font-lock-face 'magit-filename) ?\n))) + (magit-insert-section (file dir t) + (insert (propertize dir 'file 'magit-filename) ?\n) + (magit-insert-heading) + (setq files (magit-insert-files files dir)))))) + files) + +;;; _ +(provide 'magit-status) +;;; magit-status.el ends here diff --git a/elpa/magit-20191122.2040/magit-status.elc b/elpa/magit-20191122.2040/magit-status.elc new file mode 100644 index 0000000000000000000000000000000000000000..e1627b81009a8fa4b61c891093b2af127928fb6e GIT binary patch literal 57132 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�zW?)Eq4lh* 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 +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Code: + +(eval-when-compile + (require 'subr-x)) + +(require 'magit) + +(defvar x-stretch-cursor) +;;; Options + +(defcustom magit-module-sections-hook + '(magit-insert-modules-overview + magit-insert-modules-unpulled-from-upstream + magit-insert-modules-unpulled-from-pushremote + magit-insert-modules-unpushed-to-upstream + magit-insert-modules-unpushed-to-pushremote) + "Hook run by `magit-insert-modules'. + +That function isn't part of `magit-status-sections-hook's default +value, so you have to add it yourself for this hook to have any +effect." + :package-version '(magit . "2.11.0") + :group 'magit-status + :type 'hook) + +(defcustom magit-module-sections-nested t + "Whether `magit-insert-modules' wraps inserted sections. + +If this is non-nil, then only a single top-level section +is inserted. If it is nil, then all sections listed in +`magit-module-sections-hook' become top-level sections." + :package-version '(magit . "2.11.0") + :group 'magit-status + :type 'boolean) + +(defcustom magit-submodule-list-mode-hook '(hl-line-mode) + "Hook run after entering Magit-Submodule-List mode." + :package-version '(magit . "2.9.0") + :group 'magit-repolist + :type 'hook + :get 'magit-hook-custom-get + :options '(hl-line-mode)) + +(defcustom magit-submodule-list-columns + '(("Path" 25 magit-modulelist-column-path nil) + ("Version" 25 magit-repolist-column-version nil) + ("Branch" 20 magit-repolist-column-branch nil) + ("BU" 3 magit-repolist-column-unpushed-to-upstream ((:right-align t))) + ("BP" 3 magit-repolist-column-unpushed-to-pushremote ((:right-align t))) + ("B" 3 magit-repolist-column-branches ((:right-align t))) + ("S" 3 magit-repolist-column-stashes ((:right-align t)))) + "List of columns displayed by `magit-list-submodules'. + +Each element has the form (HEADER WIDTH FORMAT PROPS). + +HEADER is the string displayed in the header. WIDTH is the width +of the column. FORMAT is a function that is called with one +argument, the repository identification (usually its basename), +and with `default-directory' bound to the toplevel of its working +tree. It has to return a string to be inserted or nil. PROPS is +an alist that supports the keys `:right-align' and `:pad-right'." + :package-version '(magit . "2.8.0") + :group 'magit-repolist-mode + :type `(repeat (list :tag "Column" + (string :tag "Header Label") + (integer :tag "Column Width") + (function :tag "Inserter Function") + (repeat :tag "Properties" + (list (choice :tag "Property" + (const :right-align) + (const :pad-right) + (symbol)) + (sexp :tag "Value")))))) + +(defcustom magit-submodule-remove-trash-gitdirs nil + "Whether `magit-submodule-remove' offers to trash module gitdirs. + +If this is nil, then that command does not offer to do so unless +a prefix argument is used. When this is t, then it does offer to +do so even without a prefix argument. + +In both cases the action still has to be confirmed unless that is +disabled using the option `magit-no-confirm'. Doing the latter +and also setting this variable to t will lead to tears." + :package-version '(magit . "2.90.0") + :group 'magit-commands + :type 'boolean) + +;;; Popup + +;;;###autoload (autoload 'magit-submodule "magit-submodule" nil t) +(define-transient-command magit-submodule () + "Act on a submodule." + :man-page "git-submodule" + ["Arguments" + ("-f" "Force" ("-f" "--force")) + ("-r" "Recursive" "--recursive") + ("-N" "Do not fetch" ("-N" "--no-fetch")) + ("-C" "Checkout tip" "--checkout") + ("-R" "Rebase onto tip" "--rebase") + ("-M" "Merge tip" "--merge") + ("-U" "Use upstream tip" "--remote")] + ["One module actions" + ("a" magit-submodule-add) + ("r" magit-submodule-register) + ("p" magit-submodule-populate) + ("u" magit-submodule-update) + ("s" magit-submodule-synchronize) + ("d" magit-submodule-unpopulate) + ("k" "Remove" magit-submodule-remove)] + ["All modules actions" + ("l" "List all modules" magit-list-submodules) + ("f" "Fetch all modules" magit-fetch-modules)]) + +(defun magit-submodule-arguments (&rest filters) + (--filter (and (member it filters) it) + (transient-args 'magit-submodule))) + +(defclass magit--git-submodule-suffix (transient-suffix) + ()) + +(cl-defmethod transient-format-description ((obj magit--git-submodule-suffix)) + (let ((value (delq nil (mapcar 'transient-infix-value transient--suffixes)))) + (replace-regexp-in-string + "\\[--[^]]+\\]" + (lambda (match) + (format (propertize "[%s]" 'face 'transient-inactive-argument) + (mapconcat (lambda (arg) + (propertize arg 'face + (if (member arg value) + 'transient-argument + 'transient-inactive-argument))) + (save-match-data + (split-string (substring match 1 -1) "|")) + (propertize "|" 'face 'transient-inactive-argument)))) + (cl-call-next-method obj)))) + +;;;###autoload (autoload 'magit-submodule-add "magit-submodule" nil t) +(define-suffix-command magit-submodule-add (url &optional path name args) + "Add the repository at URL as a module. + +Optional PATH is the path to the module relative to the root of +the superproject. If it is nil, then the path is determined +based on the URL. Optional NAME is the name of the module. If +it is nil, then PATH also becomes the name." + :class 'magit--git-submodule-suffix + :description "Add git submodule add [--force]" + (interactive + (magit-with-toplevel + (let* ((url (magit-read-string-ns "Add submodule (remote url)")) + (path (let ((read-file-name-function + (if (or (eq read-file-name-function 'ido-read-file-name) + (advice-function-member-p + 'ido-read-file-name + read-file-name-function)) + ;; The Ido variant doesn't work properly here. + #'read-file-name-default + read-file-name-function))) + (directory-file-name + (file-relative-name + (read-directory-name + "Add submodules at path: " nil nil nil + (and (string-match "\\([^./]+\\)\\(\\.git\\)?$" url) + (match-string 1 url)))))))) + (list url + (directory-file-name path) + (magit-submodule-read-name-for-path path) + (magit-submodule-arguments "--force"))))) + (magit-submodule-add-1 url path name args)) + +(defun magit-submodule-add-1 (url &optional path name args) + (magit-with-toplevel + (magit-submodule--maybe-reuse-gitdir name path) + (magit-run-git-async "submodule" "add" + (and name (list "--name" name)) + args "--" url path) + (set-process-sentinel + magit-this-process + (lambda (process event) + (when (memq (process-status process) '(exit signal)) + (if (> (process-exit-status process) 0) + (magit-process-sentinel process event) + (process-put process 'inhibit-refresh t) + (magit-process-sentinel process event) + (unless (version< (magit-git-version) "2.12.0") + (magit-call-git "submodule" "absorbgitdirs" path)) + (magit-refresh))))))) + +;;;###autoload +(defun magit-submodule-read-name-for-path (path &optional prefer-short) + (let* ((path (directory-file-name (file-relative-name path))) + (name (file-name-nondirectory path))) + (push (if prefer-short path name) minibuffer-history) + (magit-read-string-ns + "Submodule name" nil (cons 'minibuffer-history 2) + (or (--keep (pcase-let ((`(,var ,val) (split-string it "="))) + (and (equal val path) + (cadr (split-string var "\\.")))) + (magit-git-lines "config" "--list" "-f" ".gitmodules")) + (if prefer-short name path))))) + +;;;###autoload (autoload 'magit-submodule-register "magit-submodule" nil t) +(define-suffix-command magit-submodule-register (modules) + "Register MODULES. + +With a prefix argument act on all suitable modules. Otherwise, +if the region selects modules, then act on those. Otherwise, if +there is a module at point, then act on that. Otherwise read a +single module from the user." + ;; This command and the underlying "git submodule init" do NOT + ;; "initialize" modules. They merely "register" modules in the + ;; super-projects $GIT_DIR/config file, the purpose of which is to + ;; allow users to change such values before actually initializing + ;; the modules. + :description "Register git submodule init" + (interactive + (list (magit-module-confirm "Register" 'magit-module-no-worktree-p))) + (magit-with-toplevel + (magit-run-git-async "submodule" "init" "--" modules))) + +;;;###autoload (autoload 'magit-submodule-populate "magit-submodule" nil t) +(define-suffix-command magit-submodule-populate (modules) + "Create MODULES working directories, checking out the recorded commits. + +With a prefix argument act on all suitable modules. Otherwise, +if the region selects modules, then act on those. Otherwise, if +there is a module at point, then act on that. Otherwise read a +single module from the user." + ;; This is the command that actually "initializes" modules. + ;; A module is initialized when it has a working directory, + ;; a gitlink, and a .gitmodules entry. + :description "Populate git submodule update --init" + (interactive + (list (magit-module-confirm "Populate" 'magit-module-no-worktree-p))) + (magit-with-toplevel + (magit-run-git-async "submodule" "update" "--init" "--" modules))) + +;;;###autoload (autoload 'magit-submodule-update "magit-submodule" nil t) +(define-suffix-command magit-submodule-update (modules args) + "Update MODULES by checking out the recorded commits. + +With a prefix argument act on all suitable modules. Otherwise, +if the region selects modules, then act on those. Otherwise, if +there is a module at point, then act on that. Otherwise read a +single module from the user." + ;; Unlike `git-submodule's `update' command ours can only update + ;; "initialized" modules by checking out other commits but not + ;; "initialize" modules by creating the working directories. + ;; To do the latter we provide the "setup" command. + :class 'magit--git-submodule-suffix + :description "Update git submodule update [--force] [--no-fetch] + [--remote] [--recursive] [--checkout|--rebase|--merge]" + (interactive + (list (magit-module-confirm "Update" 'magit-module-worktree-p) + (magit-submodule-arguments + "--force" "--remote" "--recursive" "--checkout" "--rebase" "--merge" + "--no-fetch"))) + (magit-with-toplevel + (magit-run-git-async "submodule" "update" args "--" modules))) + +;;;###autoload (autoload 'magit-submodule-synchronize "magit-submodule" nil t) +(define-suffix-command magit-submodule-synchronize (modules args) + "Synchronize url configuration of MODULES. + +With a prefix argument act on all suitable modules. Otherwise, +if the region selects modules, then act on those. Otherwise, if +there is a module at point, then act on that. Otherwise read a +single module from the user." + :class 'magit--git-submodule-suffix + :description "Synchronize git submodule sync [--recursive]" + (interactive + (list (magit-module-confirm "Synchronize" 'magit-module-worktree-p) + (magit-submodule-arguments "--recursive"))) + (magit-with-toplevel + (magit-run-git-async "submodule" "sync" args "--" modules))) + +;;;###autoload (autoload 'magit-submodule-unpopulate "magit-submodule" nil t) +(define-suffix-command magit-submodule-unpopulate (modules args) + "Remove working directories of MODULES. + +With a prefix argument act on all suitable modules. Otherwise, +if the region selects modules, then act on those. Otherwise, if +there is a module at point, then act on that. Otherwise read a +single module from the user." + ;; Even though a package is "uninitialized" (it has no worktree) + ;; the super-projects $GIT_DIR/config may never-the-less set the + ;; module's url. This may happen if you `deinit' and then `init' + ;; to register (NOT initialize). Because the purpose of `deinit' + ;; is to remove the working directory AND to remove the url, this + ;; command does not limit itself to modules that have no working + ;; directory. + :class 'magit--git-submodule-suffix + :description "Unpopulate git submodule deinit [--force]" + (interactive + (list (magit-module-confirm "Unpopulate") + (magit-submodule-arguments "--force"))) + (magit-with-toplevel + (magit-run-git-async "submodule" "deinit" args "--" modules))) + +;;;###autoload +(defun magit-submodule-remove (modules args trash-gitdirs) + "Unregister MODULES and remove their working directories. + +For safety reasons, do not remove the gitdirs and if a module has +uncomitted changes, then do not remove it at all. If a module's +gitdir is located inside the working directory, then move it into +the gitdir of the superproject first. + +With the \"--force\" argument offer to remove dirty working +directories and with a prefix argument offer to delete gitdirs. +Both actions are very dangerous and have to be confirmed. There +are additional safety precautions in place, so you might be able +to recover from making a mistake here, but don't count on it." + (interactive + (list (if-let ((modules (magit-region-values 'magit-module-section t))) + (magit-confirm 'remove-modules nil "Remove %i modules" nil modules) + (list (magit-read-module-path "Remove module"))) + (magit-submodule-arguments "--force") + current-prefix-arg)) + (when (version< (magit-git-version) "2.12.0") + (error "This command requires Git v2.12.0")) + (when magit-submodule-remove-trash-gitdirs + (setq trash-gitdirs t)) + (magit-with-toplevel + (when-let + ((modified + (-filter (lambda (module) + (let ((default-directory (file-name-as-directory + (expand-file-name module)))) + (and (cddr (directory-files default-directory)) + (magit-anything-modified-p)))) + modules))) + (if (member "--force" args) + (if (magit-confirm 'remove-dirty-modules + "Remove dirty module %s" + "Remove %i dirty modules" + t modified) + (dolist (module modified) + (let ((default-directory (file-name-as-directory + (expand-file-name module)))) + (magit-git "stash" "push" + "-m" "backup before removal of this module"))) + (setq modules (cl-set-difference modules modified))) + (if (cdr modified) + (message "Omitting %s modules with uncommitted changes: %s" + (length modified) + (mapconcat #'identity modified ", ")) + (message "Omitting module %s, it has uncommitted changes" + (car modified))) + (setq modules (cl-set-difference modules modified)))) + (when modules + (let ((alist + (and trash-gitdirs + (--map (split-string it "\0") + (magit-git-lines "submodule" "foreach" "-q" + "printf \"$sm_path\\0$name\n\""))))) + (magit-git "submodule" "absorbgitdirs" "--" modules) + (magit-git "submodule" "deinit" args "--" modules) + (magit-git "rm" args "--" modules) + (when (and trash-gitdirs + (magit-confirm 'trash-module-gitdirs + "Trash gitdir of module %s" + "Trash gitdirs of %i modules" + t modules)) + (dolist (module modules) + (if-let ((name (cadr (assoc module alist)))) + ;; Disregard if `magit-delete-by-moving-to-trash' + ;; is nil. Not doing so would be too dangerous. + (delete-directory (magit-git-dir + (convert-standard-filename + (concat "modules/" name))) + t t) + (error "BUG: Weird module name and/or path for %s" module))))) + (magit-refresh)))) + +;;; Sections + +;;;###autoload +(defun magit-insert-modules () + "Insert submodule sections. +Hook `magit-module-sections-hook' controls which module sections +are inserted, and option `magit-module-sections-nested' controls +whether they are wrapped in an additional section." + (when-let ((modules (magit-list-module-paths))) + (if magit-module-sections-nested + (magit-insert-section (modules nil t) + (magit-insert-heading + (format "%s (%s)" + (propertize "Modules" + 'font-lock-face 'magit-section-heading) + (length modules))) + (magit-insert-section-body + (magit--insert-modules))) + (magit--insert-modules)))) + +(defun magit--insert-modules (&optional _section) + (magit-run-section-hook 'magit-module-sections-hook)) + +;;;###autoload +(defun magit-insert-modules-overview () + "Insert sections for all modules. +For each section insert the path and the output of `git describe --tags', +or, failing that, the abbreviated HEAD commit hash." + (when-let ((modules (magit-list-module-paths))) + (magit-insert-section (modules nil t) + (magit-insert-heading + (format "%s (%s)" + (propertize "Modules overview" + 'font-lock-face 'magit-section-heading) + (length modules))) + (magit-insert-section-body + (magit--insert-modules-overview))))) + +(defvar magit-modules-overview-align-numbers t) + +(defun magit--insert-modules-overview (&optional _section) + (magit-with-toplevel + (let* ((modules (magit-list-module-paths)) + (path-format (format "%%-%is " + (min (apply 'max (mapcar 'length modules)) + (/ (window-width) 2)))) + (branch-format (format "%%-%is " (min 25 (/ (window-width) 3))))) + (dolist (module modules) + (let ((default-directory + (expand-file-name (file-name-as-directory module)))) + (magit-insert-section (magit-module-section module t) + (insert (propertize (format path-format module) + 'font-lock-face 'magit-diff-file-heading)) + (if (not (file-exists-p ".git")) + (insert "(unpopulated)") + (insert (format + branch-format + (--if-let (magit-get-current-branch) + (propertize it 'font-lock-face 'magit-branch-local) + (propertize "(detached)" 'font-lock-face 'warning)))) + (--if-let (magit-git-string "describe" "--tags") + (progn (when (and magit-modules-overview-align-numbers + (string-match-p "\\`[0-9]" it)) + (insert ?\s)) + (insert (propertize it 'font-lock-face 'magit-tag))) + (--when-let (magit-rev-format "%h") + (insert (propertize it 'font-lock-face 'magit-hash))))) + (insert ?\n)))))) + (insert ?\n)) + +(defvar magit-modules-section-map + (let ((map (make-sparse-keymap))) + (define-key map [remap magit-visit-thing] 'magit-list-submodules) + map) + "Keymap for `modules' sections.") + +(defvar magit-module-section-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map magit-file-section-map) + (unless (featurep 'jkl) + (define-key map "\C-j" 'magit-submodule-visit)) + (define-key map [C-return] 'magit-submodule-visit) + (define-key map [remap magit-visit-thing] 'magit-submodule-visit) + (define-key map [remap magit-delete-thing] 'magit-submodule-unpopulate) + (define-key map "K" 'magit-file-untrack) + (define-key map "R" 'magit-file-rename) + map) + "Keymap for `module' sections.") + +(defun magit-submodule-visit (module &optional other-window) + "Visit MODULE by calling `magit-status' on it. +Offer to initialize MODULE if it's not checked out yet. +With a prefix argument, visit in another window." + (interactive (list (or (magit-section-value-if 'module) + (magit-read-module-path "Visit module")) + current-prefix-arg)) + (magit-with-toplevel + (let ((path (expand-file-name module))) + (cond + ((file-exists-p (expand-file-name ".git" module)) + (magit-diff-visit-directory path other-window)) + ((y-or-n-p (format "Initialize submodule '%s' first?" module)) + (magit-run-git-async "submodule" "update" "--init" "--" module) + (set-process-sentinel + magit-this-process + (lambda (process event) + (let ((magit-process-raise-error t)) + (magit-process-sentinel process event)) + (when (and (eq (process-status process) 'exit) + (= (process-exit-status process) 0)) + (magit-diff-visit-directory path other-window))))) + ((file-exists-p path) + (dired-jump other-window (concat path "/."))))))) + +;;;###autoload +(defun magit-insert-modules-unpulled-from-upstream () + "Insert sections for modules that haven't been pulled from the upstream. +These sections can be expanded to show the respective commits." + (magit--insert-modules-logs "Modules unpulled from @{upstream}" + 'modules-unpulled-from-upstream + "HEAD..@{upstream}")) + +;;;###autoload +(defun magit-insert-modules-unpulled-from-pushremote () + "Insert sections for modules that haven't been pulled from the push-remote. +These sections can be expanded to show the respective commits." + (magit--insert-modules-logs "Modules unpulled from @{push}" + 'modules-unpulled-from-pushremote + "HEAD..@{push}")) + +;;;###autoload +(defun magit-insert-modules-unpushed-to-upstream () + "Insert sections for modules that haven't been pushed to the upstream. +These sections can be expanded to show the respective commits." + (magit--insert-modules-logs "Modules unmerged into @{upstream}" + 'modules-unpushed-to-upstream + "@{upstream}..HEAD")) + +;;;###autoload +(defun magit-insert-modules-unpushed-to-pushremote () + "Insert sections for modules that haven't been pushed to the push-remote. +These sections can be expanded to show the respective commits." + (magit--insert-modules-logs "Modules unpushed to @{push}" + 'modules-unpushed-to-pushremote + "@{push}..HEAD")) + +(defun magit--insert-modules-logs (heading type range) + "For internal use, don't add to a hook." + (unless (magit-ignore-submodules-p) + (when-let ((modules (magit-list-module-paths))) + (magit-insert-section section ((eval type) nil t) + (string-match "\\`\\(.+\\) \\([^ ]+\\)\\'" heading) + (magit-insert-heading + (propertize (match-string 1 heading) + 'font-lock-face 'magit-section-heading) + " " + (propertize (match-string 2 heading) + 'font-lock-face 'magit-branch-remote) + ":") + (magit-with-toplevel + (dolist (module modules) + (when (magit-module-worktree-p module) + (let ((default-directory + (expand-file-name (file-name-as-directory module)))) + (when (magit-file-accessible-directory-p default-directory) + (magit-insert-section sec (magit-module-section module t) + (magit-insert-heading + (propertize module + 'font-lock-face 'magit-diff-file-heading) + ":") + (magit-git-wash + (apply-partially 'magit-log-wash-log 'module) + "-c" "push.default=current" "log" "--oneline" range) + (when (> (point) + (oref sec content)) + (delete-char -1)))))))) + (if (> (point) + (oref section content)) + (insert ?\n) + (magit-cancel-section)))))) + +;;; List + +;;;###autoload +(defun magit-list-submodules () + "Display a list of the current repository's submodules." + (interactive) + (magit-display-buffer + (or (magit-get-mode-buffer 'magit-submodule-list-mode) + (magit-with-toplevel + (magit-generate-new-buffer 'magit-submodule-list-mode)))) + (magit-submodule-list-mode) + (magit-submodule-list-refresh) + (tabulated-list-print)) + +(defvar magit-submodule-list-mode-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map magit-repolist-mode-map) + map) + "Local keymap for Magit-Submodule-List mode buffers.") + +(define-derived-mode magit-submodule-list-mode tabulated-list-mode "Modules" + "Major mode for browsing a list of Git submodules." + :group 'magit-repolist-mode + (setq-local x-stretch-cursor nil) + (setq tabulated-list-padding 0) + (setq tabulated-list-sort-key (cons "Path" nil)) + (setq tabulated-list-format + (vconcat (mapcar (pcase-lambda (`(,title ,width ,_fn ,props)) + (nconc (list title width t) + (-flatten props))) + magit-submodule-list-columns))) + (tabulated-list-init-header) + (add-hook 'tabulated-list-revert-hook 'magit-submodule-list-refresh nil t) + (setq imenu-prev-index-position-function + #'magit-imenu--submodule-prev-index-position-function) + (setq imenu-extract-index-name-function + #'magit-imenu--submodule-extract-index-name-function)) + +(defun magit-submodule-list-refresh () + (setq tabulated-list-entries + (-keep (lambda (module) + (let ((default-directory + (expand-file-name (file-name-as-directory module)))) + (and (file-exists-p ".git") + (list module + (vconcat + (--map (or (funcall (nth 2 it) module) "") + magit-submodule-list-columns)))))) + (magit-list-module-paths)))) + +(defun magit-modulelist-column-path (path) + "Insert the relative path of the submodule." + path) + +;;; Utilities + +(defun magit-submodule--maybe-reuse-gitdir (name path) + (let ((gitdir + (magit-git-dir (convert-standard-filename (concat "modules/" name))))) + (when (and (file-exists-p gitdir) + (not (file-exists-p path))) + (pcase (read-char-choice + (concat + gitdir " already exists.\n" + "Type [u] to use the existing gitdir and create the working tree\n" + " [r] to rename the existing gitdir and clone again\n" + " [t] to trash the existing gitdir and clone again\n" + " [C-g] to abort ") + '(?u ?r ?t)) + (?u (magit-submodule--restore-worktree (expand-file-name path) gitdir)) + (?r (rename-file gitdir (concat gitdir "-" + (format-time-string "%F-%T")))) + (?t (delete-directory gitdir t t)))))) + +(defun magit-submodule--restore-worktree (worktree gitdir) + (make-directory worktree t) + (with-temp-file (expand-file-name ".git" worktree) + (insert "gitdir: " (file-relative-name gitdir worktree) "\n")) + (let ((default-directory worktree)) + (magit-call-git "reset" "--hard" "HEAD" "--"))) + +;;; _ +(provide 'magit-submodule) +;;; magit-submodule.el ends here diff --git a/elpa/magit-20191122.2040/magit-submodule.elc b/elpa/magit-20191122.2040/magit-submodule.elc new file mode 100644 index 0000000000000000000000000000000000000000..420b2cea30820a81fdbab41caaf2f5ce948146a4 GIT binary patch literal 38467 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

=EYK^72UdmiM}|5iOl&5QQz#LCExD zuaHBtq0)8nq&oFb@HRWtQ7t85mOH>S^7Mn-4f>4`^9NdN57Ca?ZKQy*sqg0#Wwomy zA%Dd(NL8-K&Y<^3UV+ZIf;+GPNU;T?D=pm19P&l-+dULyLu`~d-#cmW<&*&~BLos7 zB}x1xpv)@>Ck50cfao>?WAUZpAuXkU4a~<;KcQU4jc}s!FWIeC=o*hKgCD*GbZ6L zA`*)J6}Ux2&N%(@D2Qe`+*SFBV4!7|s{RBYV0<8mVFNH3*kwP$L8)w$NW_SX5RA)d zc)p8I@Jw1mYn9>HB{l^>Y+ExQe7M5$_=eP~WPP}D)Akk2ST>wSYJgP%ZGo2)2$bbZc-xt>d3awjhop`M zhr+=Xj3V}fL`%XBK-oV9$}!X<`c3t^qP?|`TGA)hdgD4{qDk{2r)t;!NmqI2QY@R+ z!n=tQnx!y1wl$?}egX2+#1no)=T?qjX@aL*Hy9@$k;%ruwhNto#YZXl7%Po1@tTPk zNkVt{7@qN&r!pOyoQ>q72_$>9!#m|m+gGuEsRXmfwMH|Dris;%7DV&l2Z`Xp)!L^f5hiBw7H_zU*2W*Cn+jQOm8Y9z30M@ubxpO9c7X}( zaTENNvEAtdEVJtvyD+|L`7B(B?O|L38qF$r|eJDzBg*dY)T5S0Nf05k%6VQR0 zq~%p;O9?-u*}@YDJ9q47ab-Z(%udB`?%FYlDN$n zD9=a0$~{sPiAf;&L`UeJy)#xp6IH>^5m;PsQofNRZAjSG=LnyHHq?;y=w><)T$;vS zqmA%-=w7Q1r7F-ZAMZjBQwK0v6IQ!0ou<*l4iF_8TM59V1wk2qc&>y$#*Z{COZfCt zoXUqMrNgYRvk?1ZSUJ+SmN?Y|PYV@;bxF8%+q<+~VpmS~nweh?1yfQKXkotQUzNv^ z!R(jad&G~nKHuKj+%y_ablSlP|#BY72x?i6#5NWf-|$J z+a)rAlIc_#`SOU=Q3x2;^Z8YrK)UikR!O3n*tfhaU`~+>DqmVMzZu4`!{q7s4Rr?S zB164uOhp1EXtyG^m82l@leic1_59nrwpWRz_o|Jz<1~Tjt)$0=4}Ho}bZ<%8aS-0$ z4B8M~YRo!e$P_-aN9eH4u|9?co{|s$iJ_HP+Jc$Nz-e90*;XLOdd=8C_G$AJU{)9Y EFPYTfW&i*H literal 0 HcmV?d00001 diff --git a/elpa/magit-20191122.2040/magit-subtree.el b/elpa/magit-20191122.2040/magit-subtree.el new file mode 100644 index 00000000..b8375f71 --- /dev/null +++ b/elpa/magit-20191122.2040/magit-subtree.el @@ -0,0 +1,182 @@ +;;; magit-subtree.el --- subtree support for Magit -*- lexical-binding: t -*- + +;; Copyright (C) 2011-2019 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Code: + +(require 'magit) + +;;; Commands + +;;;###autoload (autoload 'magit-subtree "magit-subtree" nil t) +(define-transient-command magit-subtree () + "Import or export subtrees." + :man-page "git-subtree" + ["Actions" + ("i" "Import" magit-subtree-import) + ("e" "Export" magit-subtree-export)]) + +;;;###autoload (autoload 'magit-subtree-import "magit-subtree" nil t) +(define-transient-command magit-subtree-import () + "Import subtrees." + :man-page "git-subtree" + ["Arguments" + (magit-subtree:--prefix) + (magit-subtree:--message) + ("-s" "Squash" "--squash")] + ["Actions" + [("a" "Add" magit-subtree-add) + ("c" "Add commit" magit-subtree-add-commit)] + [("m" "Merge" magit-subtree-merge) + ("f" "Pull" magit-subtree-pull)]]) + +;;;###autoload (autoload 'magit-subtree-export "magit-subtree" nil t) +(define-transient-command magit-subtree-export () + "Export subtrees." + :man-page "git-subtree" + ["Arguments" + (magit-subtree:--prefix) + (magit-subtree:--annotate) + (magit-subtree:--branch) + (magit-subtree:--onto) + ("-i" "Ignore joins" "--ignore-joins") + ("-j" "Rejoin" "--rejoin")] + ["Actions" + ("p" "Push" magit-subtree-push) + ("s" "Split" magit-subtree-split)]) + +(define-infix-argument magit-subtree:--prefix () + :description "Prefix" + :class 'transient-option + :shortarg "-P" + :argument "--prefix=" + :reader 'magit-subtree-read-prefix) + +(defun magit-subtree-read-prefix (prompt &optional default _history) + (let* ((insert-default-directory nil) + (topdir (magit-toplevel)) + (prefix (read-directory-name (concat prompt ": ") topdir default))) + (if (file-name-absolute-p prefix) + ;; At least `ido-mode's variant is not compatible. + (if (string-prefix-p topdir prefix) + (file-relative-name prefix topdir) + (user-error "%s isn't inside the repository at %s" prefix topdir)) + prefix))) + +(define-infix-argument magit-subtree:--message () + :description "Message" + :class 'transient-option + :shortarg "-m" + :argument "--message=") + +(define-infix-argument magit-subtree:--annotate () + :description "Annotate" + :class 'transient-option + :key "-a" + :argument "--annotate=") + +(define-infix-argument magit-subtree:--branch () + :description "Branch" + :class 'transient-option + :shortarg "-b" + :argument "--branch=") + +(define-infix-argument magit-subtree:--onto () + :description "Onto" + :class 'transient-option + :key "-o" + :argument "--onto=" + :reader 'magit-transient-read-revision) + +(defun magit-subtree-prefix (transient prompt) + (--if-let (--first (string-prefix-p "--prefix=" it) + (transient-args transient)) + (substring it 9) + (magit-subtree-read-prefix prompt))) + +(defun magit-subtree-arguments (transient) + (--remove (string-prefix-p "--prefix=" it) + (transient-args transient))) + +(defun magit-git-subtree (subcmd prefix &rest args) + (magit-run-git-async "subtree" subcmd (concat "--prefix=" prefix) args)) + +;;;###autoload +(defun magit-subtree-add (prefix repository ref args) + "Add REF from REPOSITORY as a new subtree at PREFIX." + (interactive + (cons (magit-subtree-prefix 'magit-subtree-import "Add subtree") + (let ((remote (magit-read-remote-or-url "From repository"))) + (list remote + (magit-read-refspec "Ref" remote) + (magit-subtree-arguments 'magit-subtree-import))))) + (magit-git-subtree "add" prefix args repository ref)) + +;;;###autoload +(defun magit-subtree-add-commit (prefix commit args) + "Add COMMIT as a new subtree at PREFIX." + (interactive + (list (magit-subtree-prefix 'magit-subtree-import "Add subtree") + (magit-read-string-ns "Commit") + (magit-subtree-arguments 'magit-subtree-import))) + (magit-git-subtree "add" prefix args commit)) + +;;;###autoload +(defun magit-subtree-merge (prefix commit args) + "Merge COMMIT into the PREFIX subtree." + (interactive + (list (magit-subtree-prefix 'magit-subtree-import "Merge into subtree") + (magit-read-string-ns "Commit") + (magit-subtree-arguments 'magit-subtree-import))) + (magit-git-subtree "merge" prefix args commit)) + +;;;###autoload +(defun magit-subtree-pull (prefix repository ref args) + "Pull REF from REPOSITORY into the PREFIX subtree." + (interactive + (cons (magit-subtree-prefix 'magit-subtree-import "Pull into subtree") + (let ((remote (magit-read-remote-or-url "From repository"))) + (list remote + (magit-read-refspec "Ref" remote) + (magit-subtree-arguments 'magit-subtree-import))))) + (magit-git-subtree "pull" prefix args repository ref)) + +;;;###autoload +(defun magit-subtree-push (prefix repository ref args) + "Extract the history of the subtree PREFIX and push it to REF on REPOSITORY." + (interactive (list (magit-subtree-prefix 'magit-subtree-export "Push subtree") + (magit-read-remote-or-url "To repository") + (magit-read-string-ns "To reference") + (magit-subtree-arguments 'magit-subtree-export))) + (magit-git-subtree "push" prefix args repository ref)) + +;;;###autoload +(defun magit-subtree-split (prefix commit args) + "Extract the history of the subtree PREFIX." + (interactive (list (magit-subtree-prefix 'magit-subtree-export "Split subtree") + (magit-read-string-ns "Commit") + (magit-subtree-arguments 'magit-subtree-export))) + (magit-git-subtree "split" prefix args commit)) + +;;; _ +(provide 'magit-subtree) +;;; magit-subtree.el ends here diff --git a/elpa/magit-20191122.2040/magit-subtree.elc b/elpa/magit-20191122.2040/magit-subtree.elc new file mode 100644 index 0000000000000000000000000000000000000000..f9555aff4f45747b4ec2c737890ad476eb9c09b6 GIT binary patch literal 9095 zcmeHNZExbn7EVY~UF8q7x?g%~_64Lm!ZvTos#3Bk+Z(BAP?AcmHu>Pd5WLse)MK)n z`|Iy>#$&Jnv#{+(E44@l&v;(W`#k5ESDl|vzuwx~+JE)x6`h8ovFD4vYIp&4Ms82i zgNURT24pu69QEYA7Z1txeG131H}d}H#&|3b_SM7dp(km8RcIoGr2b>zj=UcA!=8*I zFSwWA<7p&ga{GPJr|B-%;ema)utq<`8bKISFAQQAgD3I8Y@;VIPp(eS&ZswZBexfW z#P8MiZqO$gQqK+OPLLnExlJ@Hl7t)io`@(OVxa9L`$7bN>ca&5+0Xv|ekBrrOuR_Y z%aMEU#nt^vUkqH|bEWPv<>W4ogrM@<8W}fEt%l3`?#8aQ40;&8(7E&TFjKbsq6 zIq0pUQ;|2G#Cein0#F}x=sgHC4E#rmX)p=UhLT}6lM#4PCPv2DXdFf{g%ODl>P|~S z9vC#^+Z;z?;C;yS=#HaaI2y5q9O2s>yZ7K55>ADaTf=uBLy%f|Yh~8yh5lp|Q01sE zWH0hy{_qRqMA0gZDpe}k(Q-0iGAc*^6^~?i2IZ$E%%C@=DyJ#aQ@mEOXz`k2e$9>& zOW~S{)T-6$ZS|Jg#g?Tv{{#cmGrvGPOL^Md+`bGWi|&;ttT3~sc64NFcPO-^qG=-` zC0t}-9>RZbm|C?d=S}eHkBKXX=yf&4WSFK*JJZdk-U?UDxS&=Nh)!m(snQY`lq-C2 z$#50(Ryn6T&&5fB}Ny`(+1I{^CcZ&Paa*|0I<%D ziw$t8(IPP10pIk7g?3vs4fru!n3NA?izoDb5CVt23%!8DTsEM2>XDf~N_Q;^Yl(G$ z`s}=qkn?Wd`7Q--H%Ca6cCJlAGNUlcd=j`B&(qqSs52lXDj#{qc(}lPE`lzeDr0{| z@Ra;C2|cS|&Gams0UH8>wYKqP?|gS-+}O=#2@Qu9!L*{!4Da5FUYvo1UI2{8P- z5^g`!Y06>v{+1e_9e)FDE5wc81}jyB-Bc}F_13OXRtcSBh zz~kxZlSjW@h0$R)5K9!pwEz>kbGDtp_8-v8vP8O;HzV%U;O3UBdUd~iT(<}b)F7bl z<;8jTnqDMCxIX>Zd2{mX&)4*yv#aZi%ipWt7N%8ZW?dLct9huhBkLQs61Ep-7hm;m zX|Igm#x^Hj&dV*_H%le9p_=n8w_4jfs%2Nu;uOiUO1rE9?yxPZs%;FxMMSa5N#4ZA zFH*l=97d1IP!f*gaO{f*;gce5I>JP5jTGjH43%-Krs>{EWGTq&#*}2-T104bS`O}f zWK+ns)MO;-ktw1GDV6bDk|%?gF)}jgAt#K70vnD)=_zvDn4U}HmJX>>ento6v<~Y? zBnssSo6->SZ{=<;{Qi(j3o1G^hKJRA?6tjn!Ch7+$*RoeCG(ENd(P&bFfsIc^ z@>D84(Z~r(RD}hTlb5VIQ;OEmX9A}F(dJZ}S|CrQ%hw9b=DqW7PMrx!YbcW;?%zt4 zYa$yZm#5O`1(Y!LOuox{CR4HiXJ&{=o$ir%@VMTdLK?fFA_%%QMvx3KD%q8{wvW*O-mcXXDb>GL zobJA6kwB~fep5MZD>_{}IO0 zd2{v~y@&)}x}048bhV7PUV+3guidplp@^E}5;RsselF&3IyP^(o#9lq#o3BQ6-764O*I*}9Lf)8*% zGB3QE=_ogWNhnLtXEEAU^PNfYAFmcb{ZzJE@|^WVViW@6hmkpnd@|m!EN4*N(0-xg z$v}<;baW|D&dYBzHSt?&CN9!!Cj=%t}#EeUTJN4U7Xc_86g*+|lAH{0t8 z`>&29N?3&o_-ygSLJ;kI0L0;<8R`l6cYrD;gag&o#*iLT{BD+ugXCd!sC0`8(o9o% zADQ*5kspgbYT=EK0-lxCVB0>l*VCXr2N*0Qr@))_ +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; This library implements tag commands. + +;;; Code: + +(require 'magit) + +;;;###autoload (autoload 'magit-tag "magit" nil t) +(define-transient-command magit-tag () + "Create or delete a tag." + :man-page "git-tag" + ["Arguments" + ("-f" "Force" ("-f" "--force")) + ("-a" "Annotate" ("-a" "--annotate")) + ("-s" "Sign" ("-s" "--sign")) + (magit-tag:--local-user)] + [["Create" + ("t" "tag" magit-tag-create) + ("r" "release" magit-tag-release)] + ["Do" + ("k" "delete" magit-tag-delete) + ("p" "prune" magit-tag-prune)]]) + +(defun magit-tag-arguments () + (transient-args 'magit-tag)) + +(define-infix-argument magit-tag:--local-user () + :description "Sign as" + :class 'transient-option + :shortarg "-u" + :argument "--local-user=" + :reader 'magit-read-gpg-secret-key + :history-key 'magit:--gpg-sign) + +;;;###autoload +(defun magit-tag-create (name rev &optional args) + "Create a new tag with the given NAME at REV. +With a prefix argument annotate the tag. +\n(git tag [--annotate] NAME REV)" + (interactive (list (magit-read-tag "Tag name") + (magit-read-branch-or-commit "Place tag on") + (let ((args (magit-tag-arguments))) + (when current-prefix-arg + (cl-pushnew "--annotate" args)) + args))) + (magit-run-git-with-editor "tag" args name rev)) + +;;;###autoload +(defun magit-tag-delete (tags) + "Delete one or more tags. +If the region marks multiple tags (and nothing else), then offer +to delete those, otherwise prompt for a single tag to be deleted, +defaulting to the tag at point. +\n(git tag -d TAGS)" + (interactive (list (--if-let (magit-region-values 'tag) + (magit-confirm t nil "Delete %i tags" nil it) + (magit-read-tag "Delete tag" t)))) + (magit-run-git "tag" "-d" tags)) + +;;;###autoload +(defun magit-tag-prune (tags remote-tags remote) + "Offer to delete tags missing locally from REMOTE, and vice versa." + (interactive + (let* ((remote (magit-read-remote "Prune tags using remote")) + (tags (magit-list-tags)) + (rtags (prog2 (message "Determining remote tags...") + (magit-remote-list-tags remote) + (message "Determining remote tags...done"))) + (ltags (-difference tags rtags)) + (rtags (-difference rtags tags))) + (unless (or ltags rtags) + (message "Same tags exist locally and remotely")) + (unless (magit-confirm t + "Delete %s locally" + "Delete %i tags locally" + 'noabort ltags) + (setq ltags nil)) + (unless (magit-confirm t + "Delete %s from remote" + "Delete %i tags from remote" + 'noabort rtags) + (setq rtags nil)) + (list ltags rtags remote))) + (when tags + (magit-call-git "tag" "-d" tags)) + (when remote-tags + (magit-run-git-async "push" remote (--map (concat ":" it) remote-tags)))) + +(defvar magit-release-tag-regexp "\\`\ +\\(?1:\\(?:v\\(?:ersion\\)?\\|r\\(?:elease\\)?\\)?[-_]?\\)?\ +\\(?2:[0-9]+\\(?:\\.[0-9]+\\)*\\)\\'" + "Regexp used to parse release tag names. +The first submatch must match the prefix, if any. +The second submatch must match the version string.") + +;;;###autoload +(defun magit-tag-release (tag msg) + "Create an annotated release tag. + +Assume that release tags match `magit-release-tag-regexp'. + +First prompt for the name of the new tag using the highest +existing tag as initial input and leaving it to the user to +increment the desired part of the version string. + +Then prompt for the message of the new tag. Base the proposed +tag message on the message of the highest tag, provided that +that contains the corresponding version string and substituting +the new version string for that. Otherwise propose something +like \"Foo-Bar 1.2.3\", given, for example, a TAG \"v1.2.3\" and a +repository located at something like \"/path/to/foo-bar\". + +Then call \"git tag --annotate --sign -m MSG TAG\" to create the, +tag, regardless of whether these arguments are enabled in the +popup. Finally show the refs buffer to let the user quickly +review the result." + (interactive + (save-match-data + (pcase-let* + ((`(,pver ,ptag ,pmsg) (car (magit--list-releases))) + (tag (read-string "Create release tag: " ptag)) + (ver (and (string-match magit-release-tag-regexp tag) + (match-string 2 tag))) + (msg (cond ((and pver (string-match (regexp-quote pver) pmsg)) + (replace-match ver t t pmsg)) + ((and ptag (string-match (regexp-quote ptag) pmsg)) + (replace-match tag t t pmsg)) + (t (format "%s %s" + (capitalize + (file-name-nondirectory + (directory-file-name (magit-toplevel)))) + ver))))) + (list tag (read-string (format "Message for %S: " tag) msg))))) + (magit-run-git-async "tag" "--annotate" "--sign" "-m" msg tag) + (set-process-sentinel + magit-this-process + (lambda (process event) + (when (memq (process-status process) '(exit signal)) + (magit-process-sentinel process event) + (magit-refs-setup-buffer "HEAD" (magit-show-refs-arguments)))))) + +(defun magit--list-releases () + "Return a list of releases. +The list is ordered, beginning with the highest release. +Each release element has the form (VERSION TAG MESSAGE). +`magit-release-tag-regexp' is used to determine whether +a tag qualifies as a release tag." + (save-match-data + (mapcar + #'cdr + (nreverse + (cl-sort (cl-mapcan + (lambda (line) + (and (string-match " +" line) + (let ((tag (substring line 0 (match-beginning 0))) + (msg (substring line (match-end 0)))) + (and (string-match magit-release-tag-regexp tag) + (let ((ver (match-string 2 tag))) + (list (list (version-to-list ver) + ver tag msg))))))) + ;; Cannot rely on "--sort=-version:refname" because + ;; that gets confused if the version prefix has changed. + (magit-git-lines "tag" "-n")) + ;; The inverse of this function does not exist. + #'version-list-< :key #'car))))) + +;;; _ +(provide 'magit-tag) +;;; magit-tag.el ends here diff --git a/elpa/magit-20191122.2040/magit-tag.elc b/elpa/magit-20191122.2040/magit-tag.elc new file mode 100644 index 0000000000000000000000000000000000000000..430ef41a6c1511cf7fb1c863819f29f320583b62 GIT binary patch literal 7151 zcmcIpX>S|J5w&DXYw%kF1eVOrc$PQ|^mj&R1^P6r=vZ|rx5jyNlGnHG^sOSe#EH5a@94L=vY zNTZlO=UDLKvQ%!6g=)D3mhtiF-W&TKt;y@+w}(%EvvGjN;ke5KJ^a$gzrQic>!P)X zMiy;el}mA8c9;xyix$ew()d!8Vp64ehhYJgD!~~TR>FCnD_JU$p9 z!@BcaO`^{$EvDfx$dZI0afoksE~hv!R7x6In;*-|4DvP4yp=VAEUuDNG!H{n1bGCk z!wHb})QrIsFNjxnVuo0; z>mx#bBln>h)x!2)*j;Y!ew4zEpvZLrXxOR%ayjbDGT4D%5u?}?<0P7<>mtyQRS^n3 z;>+99petKf69PfAHu|d0;w+G{i;$GJTCH<&jiC`|;2^&R0veH5?Qi#I`=KV_H4chjmTgP3PPM^o#5(C;70sx%R_r_tsrsKFoY`y?I`x z*B^y@=pgi8Jh?s;x)wdf*McGj7Rw-nm`Jhkn&1i_TjFK8s6f>7w(#ZO-Wxk(e=yj_ zOIKVCzKjGnyZEmP%9V%`r2r^}<|}Q$K)BNAB1U{V7yUmxW+Os#l*Vr#AH;PJaotDo z_Yu>5|KWIYZ2(`_&~K0Ch%ap!9z$27%MTf!mC99#n7eY z{)rw^Eb_ee4tjB?^C?UKuPa^htwZpYGRrUdg@@s6JO-Pc3vbYB-22|^cZA79Ql#n= zWgx*csGKP=MHWlNo1@nwAxrUY^h>+(Z>C7Xq@h|o8#Tc@6lXDHd&G5K?#y*<_qkpS zE446SV%Em1c&HU5V{!EE$CK9Iu7$4&DFE(pxIz-PcXsX@s2X)tsY_Xf4&tgXf*OQF zVG6D$n)mLDHmFf=fJC#-7l4e8zemu=r$-NcaThCh|9T70%ni25KRP{b7;gOlU-7p< zEIfV~87YD)&xxyOEs-0q+KE)`oZ<@v647DBf)`*p!OYEaP?#iv`kc413|OHeLw3t zIT$Vt5l!M3$gMMwTcP4Ywf1RBDzeE$<&844yrrCFh1wSwsq#-zp@0tXZ4e)*U5WzJ z^^yWpz+H7H4fh)qplC-dj~;^@LfSlo*LeWz93UCB0!A_2}!DlbCRCT2zTZACg?2YVT18q(chcX#Zpn~3BjKVGqs^%mpcvbanG;moUIM#`B7 zGG8_Q)?1@==Meho0uSjprIWonZ8_)X;=tIu+x2@l*&9|CR#sFaTp9GYZIBq)rr|b4 z1{4q5cg7AKv3LKLjtl(6hxIyUv@R=FQ`GJ*A*bg`OC`8sh2&FsW-7277PkR&vUBz!DBKpmpKBQVWRA~ z6vYuwPm%a^{a;iUiKK!lsc=C3NWo2KgMATA;BJ?C2J&@=lixJO-caZphPIA*3xM3( zg2^)35H@Eyo$>hnc-(yE9n$yVg1_}W$9UX&HXi>k*G)WAH?^Lfx&JvwAN4n%`G;p6 z_u%|H9ycDh?OW^b7%?6{a*WsXyup(e<(Vh_K}{k+V@#z*_T)`SONb~(MS*e zPcs~fZ_yOaXjyK7CnZ!WFL0Ge7kn7gm}m294%NJjQckN>;IQs-b5n>5)B!pbTr_u z{zd8j&y?U18?6QKOdc(h|w>jH|xBh*Be~rfgaI;P3AY)Ax1zt#@!)` z5iU4A@jX$1@3)TDf41)IeuHsX!|UGWDZRV8uIP6tw{yXY2If#dQ40vBH@ve)6bb6= zQkxGVMYSw8*u6{Tk00NbmcxsQ*=ZnXR$}%p;8Ng1I(62!t=4q_?n40#^VPjx7Ki?3>OX<$ph5wft*JruCjk65)dnwa+8b8{16#~q`wsP zlUolkQkNN`;sU`673;8y&NBFk|x zpu&CBTGJ?HDpyzZHhY+v?Z!wV_gbYOUvsvbAx~0Ff*grx{xW)Z^6K~v2kqBzl%pR< zt#;$R^}S6B@<>1iOP4~!4V4Y44Zh?SA1f$p5~23NRqN(c&swnv0!S5X-63`p@Z>M*RFYhkJ6$IXgaC}`}aiHl8xAwN~+ +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; This library implements Magit-specific prefix and suffix classes, +;; and their methods. + +;;; Code: + +(eval-when-compile + (require 'subr-x)) + +(require 'transient) + +(require 'magit-git) +(require 'magit-mode) +(require 'magit-process) + +;;; Classes + +(defclass magit--git-variable (transient-variable) + ((scope :initarg :scope))) + +(defclass magit--git-variable:choices (magit--git-variable) + ((choices :initarg :choices) + (fallback :initarg :fallback :initform nil) + (default :initarg :default :initform nil))) + +(defclass magit--git-variable:urls (magit--git-variable) + ((seturl-arg :initarg :seturl-arg :initform nil))) + +;;; Methods +;;;; Init + +(cl-defmethod transient-init-scope ((obj magit--git-variable)) + (oset obj scope + (cond (transient--prefix + (oref transient--prefix scope)) + ((slot-boundp obj 'scope) + (funcall (oref obj scope) obj))))) + +(cl-defmethod transient-init-value ((obj magit--git-variable)) + (let ((variable (format (oref obj variable) + (oref obj scope)))) + (oset obj variable variable) + (oset obj value + (cond ((oref obj multi-value) + (magit-get-all variable)) + (t + (magit-git-string "config" "--local" variable)))))) + +;;;; Read + +(cl-defmethod transient-infix-read :around ((obj magit--git-variable:urls)) + (mapcar (lambda (url) + (if (string-prefix-p "~" url) + (expand-file-name url) + url)) + (cl-call-next-method obj))) + +(cl-defmethod transient-infix-read ((obj magit--git-variable:choices)) + (let ((choices (oref obj choices))) + (when (functionp choices) + (setq choices (funcall choices))) + (if-let ((value (oref obj value))) + (cadr (member value choices)) + (car choices)))) + +;;;; Readers + +(defun magit-transient-read-person (prompt initial-input history) + (magit-completing-read + prompt + (mapcar (lambda (line) + (save-excursion + (and (string-match "\\`[\s\t]+[0-9]+\t" line) + (list (substring line (match-end 0)))))) + (magit-git-lines "shortlog" "-n" "-s" "-e" "HEAD")) + nil nil initial-input history)) + +(defun magit-transient-read-revision (prompt initial-input history) + (or (magit-completing-read prompt (cons "HEAD" (magit-list-refnames)) + nil nil initial-input history + (or (magit-branch-or-commit-at-point) + (magit-get-current-branch))) + (user-error "Nothing selected"))) + +;;;; Set + +(cl-defmethod transient-infix-set ((obj magit--git-variable) value) + (let ((variable (oref obj variable))) + (oset obj value value) + (if (oref obj multi-value) + (magit-set-all value variable) + (magit-set value variable)) + (magit-refresh) + (unless (or value transient--prefix) + (message "Unset %s" variable)))) + +(cl-defmethod transient-infix-set ((obj magit--git-variable:urls) values) + (let ((previous (oref obj value)) + (seturl (oref obj seturl-arg)) + (remote (oref transient--prefix scope))) + (oset obj value values) + (dolist (v (-difference values previous)) + (magit-call-git "remote" "set-url" seturl "--add" remote v)) + (dolist (v (-difference previous values)) + (magit-call-git "remote" "set-url" seturl "--delete" remote + (concat "^" (regexp-quote v) "$"))) + (magit-refresh))) + +;;;; Draw + +(cl-defmethod transient-format-description ((obj magit--git-variable)) + (or (oref obj description) + (oref obj variable))) + +(cl-defmethod transient-format-value ((obj magit--git-variable)) + (if-let ((value (oref obj value))) + (if (oref obj multi-value) + (if (cdr value) + (mapconcat (lambda (v) + (concat "\n " + (propertize v 'face 'transient-value))) + value "") + (propertize (car value) 'face 'transient-value)) + (propertize (car (split-string value "\n")) + 'face 'transient-value)) + (propertize "unset" 'face 'transient-inactive-value))) + +(cl-defmethod transient-format-value ((obj magit--git-variable:choices)) + (let* ((variable (oref obj variable)) + (choices (oref obj choices)) + (local (magit-git-string "config" "--local" variable)) + (global (magit-git-string "config" "--global" variable)) + (default (oref obj default)) + (fallback (oref obj fallback)) + (fallback (and fallback + (when-let ((val (magit-get fallback))) + (concat fallback ":" val))))) + (when (functionp choices) + (setq choices (funcall choices))) + (concat + (propertize "[" 'face 'transient-inactive-value) + (mapconcat (lambda (choice) + (propertize choice 'face (if (equal choice local) + (if (member choice choices) + 'transient-value + 'font-lock-warning-face) + 'transient-inactive-value))) + (if (and local (not (member local choices))) + (cons local choices) + choices) + (propertize "|" 'face 'transient-inactive-value)) + (and (or global fallback default) + (concat + (propertize "|" 'face 'transient-inactive-value) + (cond (global + (propertize (concat "global:" global) + 'face (cond (local + 'transient-inactive-value) + ((member global choices) + 'transient-value) + (t + 'font-lock-warning-face)))) + (fallback + (propertize fallback + 'face (if local + 'transient-inactive-value + 'transient-value))) + (default + (propertize (concat "default:" default) + 'face (if local + 'transient-inactive-value + 'transient-value)))))) + (propertize "]" 'face 'transient-inactive-value)))) + +;;; _ +(provide 'magit-transient) +;;; magit-transient.el ends here + diff --git a/elpa/magit-20191122.2040/magit-transient.elc b/elpa/magit-20191122.2040/magit-transient.elc new file mode 100644 index 0000000000000000000000000000000000000000..29254b5fa455082de37cd3d549a02e1ff74664d9 GIT binary patch literal 8360 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 +;; Maintainer: Jonas Bernoulli + +;; Contains code from GNU Emacs https://www.gnu.org/software/emacs, +;; released under the GNU General Public License version 3 or later. + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; This library defines several utility functions used by several +;; other libraries which cannot depend on one another (because +;; circular dependencies are not good). Luckily most (all) of these +;; functions have very little (nothing) to do with Git, so we not only +;; have to do this, it even makes sense. + +;; Unfortunately there are also some options which are used by several +;; libraries which cannot depend on one another, they are defined here +;; too. + +;;; Code: + +(require 'cl-lib) +(require 'dash) + +(eval-when-compile + (require 'subr-x)) + +(require 'crm) + +(eval-when-compile (require 'ido)) +(declare-function ido-completing-read+ "ido-completing-read+" + (prompt collection &optional predicate + require-match initial-input + hist def inherit-input-method)) +(declare-function Info-get-token "info" (pos start all &optional errorstring)) + +(eval-when-compile (require 'vc-git)) +(declare-function vc-git--run-command-string "vc-git" (file &rest args)) + +(eval-when-compile (require 'which-func)) +(declare-function which-function "which-func" ()) + +(defvar magit-wip-before-change-mode) + +;;; Options + +(defcustom magit-completing-read-function 'magit-builtin-completing-read + "Function to be called when requesting input from the user. + +If you have enabled `ivy-mode' or `helm-mode', then you don't +have to customize this option; `magit-builtin-completing-read' +will work just fine. However, if you use Ido completion, then +you do have to use `magit-ido-completing-read', because Ido is +less well behaved than the former, more modern alternatives. + +If you would like to use Ivy or Helm completion with Magit but +not enable the respective modes globally, then customize this +option to use `ivy-completing-read' or +`helm--completing-read-default'. If you choose to use +`ivy-completing-read', note that the items may always be shown in +alphabetical order, depending on your version of Ivy." + :group 'magit-essentials + :type '(radio (function-item magit-builtin-completing-read) + (function-item magit-ido-completing-read) + (function-item ivy-completing-read) + (function-item helm--completing-read-default) + (function :tag "Other function"))) + +(defcustom magit-dwim-selection + '((magit-stash-apply nil t) + (magit-stash-branch nil t) + (magit-stash-branch-here nil t) + (magit-stash-format-patch nil t) + (magit-stash-drop nil ask) + (magit-stash-pop nil ask) + (forge-browse-dwim nil t) + (forge-browse-commit nil t) + (forge-browse-branch nil t) + (forge-browse-remote nil t) + (forge-browse-issue nil t) + (forge-browse-pullreq nil t) + (forge-edit-topic-title nil t) + (forge-edit-topic-state nil t) + (forge-edit-topic-labels nil t) + (forge-edit-topic-marks nil t) + (forge-edit-topic-assignees nil t) + (forge-edit-topic-review-requests nil t) + (forge-pull-pullreq nil t) + (forge-visit-issue nil t) + (forge-visit-pullreq nil t)) + "When not to offer alternatives and ask for confirmation. + +Many commands by default ask the user to select from a list of +possible candidates. They do so even when there is a thing at +point that they can act on, which is then offered as the default. + +This option can be used to tell certain commands to use the thing +at point instead of asking the user to select a candidate to act +on, with or without confirmation. + +The value has the form ((COMMAND nil|PROMPT DEFAULT)...). + +- COMMAND is the command that should not prompt for a choice. + To have an effect, the command has to use the function + `magit-completing-read' or a utility function which in turn uses + that function. + +- If the command uses `magit-completing-read' multiple times, then + PROMPT can be used to only affect one of these uses. PROMPT, if + non-nil, is a regular expression that is used to match against + the PROMPT argument passed to `magit-completing-read'. + +- DEFAULT specifies how to use the default. If it is t, then + the DEFAULT argument passed to `magit-completing-read' is used + without confirmation. If it is `ask', then the user is given + a chance to abort. DEFAULT can also be nil, in which case the + entry has no effect." + :package-version '(magit . "2.12.0") + :group 'magit-commands + :type '(repeat + (list (symbol :tag "Command") ; It might not be fboundp yet. + (choice (const :tag "for all prompts" nil) + (regexp :tag "for prompts matching regexp")) + (choice (const :tag "offer other choices" nil) + (const :tag "require confirmation" ask) + (const :tag "use default without confirmation" t))))) + +(defconst magit--confirm-actions + '((const reverse) (const discard) + (const rename) (const resurrect) + (const untrack) (const trash) + (const delete) (const abort-rebase) + (const abort-merge) (const merge-dirty) + (const drop-stashes) (const reset-bisect) + (const kill-process) (const delete-unmerged-branch) + (const delete-pr-branch) (const remove-modules) + (const stage-all-changes) (const unstage-all-changes) + (const safe-with-wip))) + +(defcustom magit-no-confirm nil + "A list of symbols for actions Magit should not confirm, or t. + +Many potentially dangerous commands by default ask the user for +confirmation. Each of the below symbols stands for an action +which, when invoked unintentionally or without being fully aware +of the consequences, could lead to tears. In many cases there +are several commands that perform variations of a certain action, +so we don't use the command names but more generic symbols. + +Applying changes: + + `discard' Discarding one or more changes (i.e. hunks or the + complete diff for a file) loses that change, obviously. + + `reverse' Reverting one or more changes can usually be undone + by reverting the reversion. + + `stage-all-changes', `unstage-all-changes' When there are both + staged and unstaged changes, then un-/staging everything would + destroy that distinction. Of course that also applies when + un-/staging a single change, but then less is lost and one does + that so often that having to confirm every time would be + unacceptable. + +Files: + + `delete' When a file that isn't yet tracked by Git is deleted + then it is completely lost, not just the last changes. Very + dangerous. + + `trash' Instead of deleting a file it can also be move to the + system trash. Obviously much less dangerous than deleting it. + + Also see option `magit-delete-by-moving-to-trash'. + + `resurrect' A deleted file can easily be resurrected by + \"deleting\" the deletion, which is done using the same command + that was used to delete the same file in the first place. + + `untrack' Untracking a file can be undone by tracking it again. + + `rename' Renaming a file can easily be undone. + +Sequences: + + `reset-bisect' Aborting (known to Git as \"resetting\") a + bisect operation loses all information collected so far. + + `abort-rebase' Aborting a rebase throws away all already + modified commits, but it's possible to restore those from the + reflog. + + `abort-merge' Aborting a merge throws away all conflict + resolutions which has already been carried out by the user. + + `merge-dirty' Merging with a dirty worktree can make it hard to + go back to the state before the merge was initiated. + +References: + + `delete-unmerged-branch' Once a branch has been deleted it can + only be restored using low-level recovery tools provided by + Git. And even then the reflog is gone. The user always has + to confirm the deletion of a branch by accepting the default + choice (or selecting another branch), but when a branch has + not been merged yet, also make sure the user is aware of that. + + `delete-pr-remote' When deleting a branch that was created from + a pull-request and if no other branches still exist on that + remote, then `magit-branch-delete' offers to delete the remote + as well. This should be safe because it only happens if no + other refs exist in the remotes namespace, and you can recreate + the remote if necessary. + + `drop-stashes' Dropping a stash is dangerous because Git stores + stashes in the reflog. Once a stash is removed, there is no + going back without using low-level recovery tools provided by + Git. When a single stash is dropped, then the user always has + to confirm by accepting the default (or selecting another). + This action only concerns the deletion of multiple stashes at + once. + +Edit published history: + + Without adding these symbols here, you will be warned before + editing commits that have already been pushed to one of the + branches listed in `magit-published-branches'. + + `amend-published' Affects most commands that amend to \"HEAD\". + + `rebase-published' Affects commands that perform interactive + rebases. This includes commands from the commit popup that + modify a commit other than \"HEAD\", namely the various fixup + and squash variants. + + `edit-published' Affects the commands `magit-edit-line-commit' + and `magit-diff-edit-hunk-commit'. These two commands make + it quite easy to accidentally edit a published commit, so you + should think twice before configuring them not to ask for + confirmation. + + To disable confirmation completely, add all three symbols here + or set `magit-published-branches' to nil. + +Removing modules: + + `remove-modules' When you remove the working directory of a + module that does not contain uncommitted changes, then that is + safer than doing so when there are uncommitted changes and/or + when you also remove the gitdir. Still, you don't want to do + that by accident. + + `remove-dirty-modules' When you remove the working directory of + a module that contains uncommitted changes, then those changes + are gone for good. It is better to go to the module, inspect + these changes and only if appropriate discard them manually. + + `trash-module-gitdirs' When you remove the gitdir of a module, + then all unpushed changes are gone for good. It is very easy + to forget that you have some unfinished work on an unpublished + feature branch or even in a stash. + + Actually there are some safety precautions in place, that might + help you out if you make an unwise choice here, but don't count + on it. In case of emergency, stay calm and check the stash and + the `trash-directory' for traces of lost work. + +Various: + + `kill-process' There seldom is a reason to kill a process. + +Global settings: + + Instead of adding all of the above symbols to the value of this + option you can also set it to the atom `t', which has the same + effect as adding all of the above symbols. Doing that most + certainly is a bad idea, especially because other symbols might + be added in the future. So even if you don't want to be asked + for confirmation for any of these actions, you are still better + of adding all of the respective symbols individually. + + When `magit-wip-before-change-mode' is enabled then these actions + can fairly easily be undone: `discard', `reverse', + `stage-all-changes', and `unstage-all-changes'. If and only if + this mode is enabled, then `safe-with-wip' has the same effect + as adding all of these symbols individually." + :package-version '(magit . "2.1.0") + :group 'magit-essentials + :group 'magit-commands + :type `(choice (const :tag "Always require confirmation" nil) + (const :tag "Never require confirmation" t) + (set :tag "Require confirmation except for" + ;; `remove-dirty-modules' and + ;; `trash-module-gitdirs' intentionally + ;; omitted. + ,@magit--confirm-actions))) + +(defcustom magit-slow-confirm '(drop-stashes) + "Whether to ask user \"y or n\" or \"yes or no\" questions. + +When this is nil, then `y-or-n-p' is used when the user has to +confirm a potentially destructive action. When this is t, then +`yes-or-no-p' is used instead. If this is a list of symbols +identifying actions, then `yes-or-no-p' is used for those, +`y-or-no-p' for all others. The list of actions is the same as +for `magit-no-confirm' (which see)." + :package-version '(magit . "2.9.0") + :group 'magit-miscellaneous + :type `(choice (const :tag "Always ask \"yes or no\" questions" t) + (const :tag "Always ask \"y or n\" questions" nil) + (set :tag "Ask \"yes or no\" questions only for" + ,@magit--confirm-actions))) + +(defcustom magit-no-message nil + "A list of messages Magit should not display. + +Magit displays most echo area messages using `message', but a few +are displayed using `magit-message' instead, which takes the same +arguments as the former, FORMAT-STRING and ARGS. `magit-message' +forgoes printing a message if any member of this list is a prefix +of the respective FORMAT-STRING. + +If Magit prints a message which causes you grief, then please +first investigate whether there is another option which can be +used to suppress it. If that is not the case, then ask the Magit +maintainers to start using `magit-message' instead of `message' +in that case. We are not proactively replacing all uses of +`message' with `magit-message', just in case someone *might* find +some of these messages useless. + +Messages which can currently be suppressed using this option are: +* \"Turning on magit-auto-revert-mode...\"" + :package-version '(magit . "2.8.0") + :group 'magit-miscellaneous + :type '(repeat string)) + +(defcustom magit-ellipsis ?… + "Character used to abbreviate text. + +Currently this is used to abbreviate author names in the margin +and in process buffers to elide `magit-git-global-arguments'." + :package-version '(magit . "2.1.0") + :group 'magit-miscellaneous + :type 'character) + +(defcustom magit-update-other-window-delay 0.2 + "Delay before automatically updating the other window. + +When moving around in certain buffers, then certain other +buffers, which are being displayed in another window, may +optionally be updated to display information about the +section at point. + +When holding down a key to move by more than just one section, +then that would update that buffer for each section on the way. +To prevent that, updating the revision buffer is delayed, and +this option controls for how long. For optimal experience you +might have to adjust this delay and/or the keyboard repeat rate +and delay of your graphical environment or operating system." + :package-version '(magit . "2.3.0") + :group 'magit-miscellaneous + :type 'number) + +(defcustom magit-view-git-manual-method 'info + "How links to Git documentation are followed from Magit's Info manuals. + +`info' Follow the link to the node in the `gitman' Info manual + as usual. Unfortunately that manual is not installed by + default on some platforms, and when it is then the nodes + look worse than the actual manpages. + +`man' View the respective man-page using the `man' package. + +`woman' View the respective man-page using the `woman' package." + :package-version '(magit . "2.9.0") + :group 'magit-miscellaneous + :type '(choice (const :tag "view info manual" info) + (const :tag "view manpage using `man'" man) + (const :tag "view manpage using `woman'" woman))) + +;;; User Input + +(defvar helm-completion-in-region-default-sort-fn) +(defvar ivy-sort-functions-alist) + +(defvar magit-completing-read--silent-default nil) + +(defun magit-completing-read (prompt collection &optional + predicate require-match initial-input + hist def fallback) + "Read a choice in the minibuffer, or use the default choice. + +This is the function that Magit commands use when they need the +user to select a single thing to act on. The arguments have the +same meaning as for `completing-read', except for FALLBACK, which +is unique to this function and is described below. + +Instead of asking the user to choose from a list of possible +candidates, this function may instead just return the default +specified by DEF, with or without requiring user confirmation. +Whether that is the case depends on PROMPT, `this-command' and +`magit-dwim-selection'. See the documentation of the latter for +more information. + +If it does use the default without the user even having to +confirm that, then `magit-completing-read--silent-default' is set +to t, otherwise nil. + +If it does read a value in the minibuffer, then this function +acts similarly to `completing-read', except for the following: + +- COLLECTION must be a list of choices. A function is not + supported. + +- If REQUIRE-MATCH is nil and the user exits without a choice, + then nil is returned instead of an empty string. + +- If REQUIRE-MATCH is non-nil and the users exits without a + choice, an user-error is raised. + +- FALLBACK specifies a secondary default that is only used if + the primary default DEF is nil. The secondary default is not + subject to `magit-dwim-selection' — if DEF is nil but FALLBACK + is not, then this function always asks the user to choose a + candidate, just as if both defaults were nil. + +- \": \" is appended to PROMPT. + +- PROMPT is modified to end with \" (default DEF|FALLBACK): \" + provided that DEF or FALLBACK is non-nil, that neither + `ivy-mode' nor `helm-mode' is enabled, and that + `magit-completing-read-function' is set to its default value of + `magit-builtin-completing-read'." + (setq magit-completing-read--silent-default nil) + (if-let ((dwim (and def + (nth 2 (-first (pcase-lambda (`(,cmd ,re ,_)) + (and (eq this-command cmd) + (or (not re) + (string-match-p re prompt)))) + magit-dwim-selection))))) + (if (eq dwim 'ask) + (if (y-or-n-p (format "%s %s? " prompt def)) + def + (user-error "Abort")) + (setq magit-completing-read--silent-default t) + def) + (unless def + (setq def fallback)) + (let ((command this-command) + (reply (funcall magit-completing-read-function + (concat prompt ": ") + (if (and def (not (member def collection))) + (cons def collection) + collection) + predicate + require-match initial-input hist def))) + (setq this-command command) + (if (string= reply "") + (if require-match + (user-error "Nothing selected") + nil) + reply)))) + +(defun magit--completion-table (collection) + (lambda (string pred action) + (if (eq action 'metadata) + '(metadata (display-sort-function . identity)) + (complete-with-action action collection string pred)))) + +(defun magit-builtin-completing-read + (prompt choices &optional predicate require-match initial-input hist def) + "Magit wrapper for standard `completing-read' function." + (unless (or (bound-and-true-p helm-mode) + (bound-and-true-p ivy-mode)) + (setq prompt (magit-prompt-with-default prompt def)) + (setq choices (magit--completion-table choices))) + (cl-letf (((symbol-function 'completion-pcm--all-completions) + #'magit-completion-pcm--all-completions)) + (let ((ivy-sort-functions-alist nil)) + (completing-read prompt choices + predicate require-match + initial-input hist def)))) + +(defun magit-completing-read-multiple + (prompt choices &optional sep default hist keymap) + "Read multiple items from CHOICES, separated by SEP. + +Set up the `crm' variables needed to read multiple values with +`read-from-minibuffer'. + +SEP is a regexp matching characters that can separate choices. +When SEP is nil, it defaults to `crm-default-separator'. +DEFAULT, HIST, and KEYMAP are passed to `read-from-minibuffer'. +When KEYMAP is nil, it defaults to `crm-local-completion-map'. + +Unlike `completing-read-multiple', the return value is not split +into a list." + (let* ((crm-separator (or sep crm-default-separator)) + (crm-completion-table (magit--completion-table choices)) + (choose-completion-string-functions + '(crm--choose-completion-string)) + (minibuffer-completion-table #'crm--collection-fn) + (minibuffer-completion-confirm t) + (helm-completion-in-region-default-sort-fn nil) + (input + (cl-letf (((symbol-function 'completion-pcm--all-completions) + #'magit-completion-pcm--all-completions)) + (read-from-minibuffer + (concat prompt (and default (format " (%s)" default)) ": ") + nil (or keymap crm-local-completion-map) + nil hist default)))) + (when (string-equal input "") + (or (setq input default) + (user-error "Nothing selected"))) + input)) + +(defun magit-completing-read-multiple* + (prompt table &optional predicate require-match initial-input + hist def inherit-input-method) + "Read multiple strings in the minibuffer, with completion. +Like `completing-read-multiple' but don't mess with order of +TABLE. Also bind `helm-completion-in-region-default-sort-fn' +to nil." + (unwind-protect + (cl-letf (((symbol-function 'completion-pcm--all-completions) + #'magit-completion-pcm--all-completions)) + (add-hook 'choose-completion-string-functions + 'crm--choose-completion-string) + (let* ((minibuffer-completion-table #'crm--collection-fn) + (minibuffer-completion-predicate predicate) + ;; see completing_read in src/minibuf.c + (minibuffer-completion-confirm + (unless (eq require-match t) require-match)) + (crm-completion-table (magit--completion-table table)) + (map (if require-match + crm-local-must-match-map + crm-local-completion-map)) + (helm-completion-in-region-default-sort-fn nil) + ;; If the user enters empty input, `read-from-minibuffer' + ;; returns the empty string, not DEF. + (input (read-from-minibuffer + prompt initial-input map + nil hist def inherit-input-method))) + (and def (string-equal input "") (setq input def)) + ;; Remove empty strings in the list of read strings. + (split-string input crm-separator t))) + (remove-hook 'choose-completion-string-functions + 'crm--choose-completion-string))) + +(defun magit-ido-completing-read + (prompt choices &optional predicate require-match initial-input hist def) + "Ido-based `completing-read' almost-replacement. + +Unfortunately `ido-completing-read' is not suitable as a +drop-in replacement for `completing-read', instead we use +`ido-completing-read+' from the third-party package by the +same name." + (if (require 'ido-completing-read+ nil t) + (ido-completing-read+ prompt choices predicate require-match + initial-input hist + (or def (and require-match (car choices)))) + (display-warning 'magit "ido-completing-read+ is not installed + +To use Ido completion with Magit you need to install the +third-party `ido-completing-read+' packages. Falling +back to built-in `completing-read' for now." :error) + (magit-builtin-completing-read prompt choices predicate require-match + initial-input hist def))) + +(defun magit-prompt-with-default (prompt def) + (if (and def (> (length prompt) 2) + (string-equal ": " (substring prompt -2))) + (format "%s (default %s): " (substring prompt 0 -2) def) + prompt)) + +(defvar magit-minibuffer-local-ns-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map minibuffer-local-map) + (define-key map "\s" 'magit-whitespace-disallowed) + (define-key map "\t" 'magit-whitespace-disallowed) + map)) + +(defun magit-whitespace-disallowed () + "Beep to tell the user that whitespace is not allowed." + (interactive) + (ding) + (message "Whitespace isn't allowed here") + (setq defining-kbd-macro nil) + (force-mode-line-update)) + +(defun magit-read-string (prompt &optional initial-input history default-value + inherit-input-method no-whitespace) + "Read a string from the minibuffer, prompting with string PROMPT. + +This is similar to `read-string', but +* empty input is only allowed if DEFAULT-VALUE is non-nil in + which case that is returned, +* whitespace is not allowed and leading and trailing whitespace is + removed automatically if NO-WHITESPACE is non-nil, +* \": \" is appended to PROMPT, and +* an invalid DEFAULT-VALUE is silently ignored." + (when default-value + (when (consp default-value) + (setq default-value (car default-value))) + (unless (stringp default-value) + (setq default-value nil))) + (let* ((minibuffer-completion-table nil) + (val (read-from-minibuffer + (magit-prompt-with-default (concat prompt ": ") default-value) + initial-input (and no-whitespace magit-minibuffer-local-ns-map) + nil history default-value inherit-input-method)) + (trim (lambda (regexp string) + (save-match-data + (if (string-match regexp string) + (replace-match "" t t string) + string))))) + (when (and (string= val "") default-value) + (setq val default-value)) + (when no-whitespace + (setq val (funcall trim "\\`\\(?:[ \t\n\r]+\\)" + (funcall trim "\\(?:[ \t\n\r]+\\)\\'" val)))) + (cond ((string= val "") + (user-error "Need non-empty input")) + ((and no-whitespace (string-match-p "[\s\t\n]" val)) + (user-error "Input contains whitespace")) + (t val)))) + +(defun magit-read-string-ns (prompt &optional initial-input history + default-value inherit-input-method) + "Call `magit-read-string' with non-nil NO-WHITESPACE." + (magit-read-string prompt initial-input history default-value + inherit-input-method t)) + +(defmacro magit-read-char-case (prompt verbose &rest clauses) + (declare (indent 2) + (debug (form form &rest (characterp form body)))) + `(prog1 (pcase (read-char-choice + (concat ,prompt + ,(concat (mapconcat 'cadr clauses ", ") + (and verbose ", or [C-g] to abort") " ")) + ',(mapcar 'car clauses)) + ,@(--map `(,(car it) ,@(cddr it)) clauses)) + (message ""))) + +(defun magit-y-or-n-p (prompt &optional action) + "Ask user a \"y or n\" or a \"yes or no\" question using PROMPT. +Which kind of question is used depends on whether +ACTION is a member of option `magit-slow-confirm'." + (if (or (eq magit-slow-confirm t) + (and action (member action magit-slow-confirm))) + (yes-or-no-p prompt) + (y-or-n-p prompt))) + +(defvar magit--no-confirm-alist + '((safe-with-wip magit-wip-before-change-mode + discard reverse stage-all-changes unstage-all-changes))) + +(cl-defun magit-confirm (action &optional prompt prompt-n noabort + (items nil sitems)) + (declare (indent defun)) + (setq prompt-n (format (concat (or prompt-n prompt) "? ") (length items))) + (setq prompt (format (concat (or prompt (magit-confirm-make-prompt action)) + "? ") + (car items))) + (or (cond ((and (not (eq action t)) + (or (eq magit-no-confirm t) + (memq action magit-no-confirm) + (cl-member-if (pcase-lambda (`(,key ,var . ,sub)) + (and (memq key magit-no-confirm) + (memq action sub) + (or (not var) + (and (boundp var) + (symbol-value var))))) + magit--no-confirm-alist))) + (or (not sitems) items)) + ((not sitems) + (magit-y-or-n-p prompt action)) + ((= (length items) 1) + (and (magit-y-or-n-p prompt action) items)) + ((> (length items) 1) + (and (magit-y-or-n-p (concat (mapconcat #'identity items "\n") + "\n\n" prompt-n) + action) + items))) + (if noabort nil (user-error "Abort")))) + +(defun magit-confirm-files (action files &optional prompt) + (when files + (unless prompt + (setq prompt (magit-confirm-make-prompt action))) + (magit-confirm action + (concat prompt " %s") + (concat prompt " %i files") + nil files))) + +(defun magit-confirm-make-prompt (action) + (let ((prompt (symbol-name action))) + (replace-regexp-in-string + "-" " " (concat (upcase (substring prompt 0 1)) (substring prompt 1))))) + +(defun magit-read-number-string (prompt &optional default _history) + "Like `read-number' but return value is a string. +DEFAULT may be a number or a numeric string." + (number-to-string + (read-number prompt (if (stringp default) + (string-to-number default) + default)))) + +;;; Debug Utilities + +;;;###autoload +(defun magit-emacs-Q-command () + "Show a shell command that runs an uncustomized Emacs with only Magit loaded. +See info node `(magit)Debugging Tools' for more information." + (interactive) + (let ((cmd (mapconcat + #'shell-quote-argument + `(,(concat invocation-directory invocation-name) + "-Q" "--eval" "(setq debug-on-error t)" + ,@(cl-mapcan + (lambda (dir) (list "-L" dir)) + (delete-dups + (cl-mapcan + (lambda (lib) + (let ((path (locate-library lib))) + (cond + (path + (list (file-name-directory path))) + ((not (equal lib "libgit")) + (error "Cannot find mandatory dependency %s" lib))))) + '(;; Like `LOAD_PATH' in `default.mk'. + "dash" + "libgit" + "transient" + "with-editor" + ;; Obviously `magit' itself is needed too. + "magit" + ;; While this is part of the Magit repository, + ;; it is distributed as a separate package. + "git-commit" + ;; Even though `async' is a dependency of the + ;; `magit' package, it is not required here. + )))) + ;; Avoid Emacs bug#16406 by using full path. + "-l" ,(file-name-sans-extension (locate-library "magit"))) + " "))) + (message "Uncustomized Magit command saved to kill-ring, %s" + "please run it in a terminal.") + (kill-new cmd))) + +;;; Text Utilities + +(defmacro magit-bind-match-strings (varlist string &rest body) + "Bind variables to submatches according to VARLIST then evaluate BODY. +Bind the symbols in VARLIST to submatches of the current match +data, starting with 1 and incrementing by 1 for each symbol. If +the last match was against a string, then that has to be provided +as STRING." + (declare (indent 2) (debug (listp form body))) + (let ((s (cl-gensym "string")) + (i 0)) + `(let ((,s ,string)) + (let ,(save-match-data + (--map (list it (list 'match-string (cl-incf i) s)) varlist)) + ,@body)))) + +(defun magit-delete-line () + "Delete the rest of the current line." + (delete-region (point) (1+ (line-end-position)))) + +(defun magit-delete-match (&optional num) + "Delete text matched by last search. +If optional NUM is specified, only delete that subexpression." + (delete-region (match-beginning (or num 0)) + (match-end (or num 0)))) + +(defun magit-file-line (file) + "Return the first line of FILE as a string." + (when (file-regular-p file) + (with-temp-buffer + (insert-file-contents file) + (buffer-substring-no-properties (point-min) + (line-end-position))))) + +(defun magit-file-lines (file &optional keep-empty-lines) + "Return a list of strings containing one element per line in FILE. +Unless optional argument KEEP-EMPTY-LINES is t, trim all empty lines." + (when (file-regular-p file) + (with-temp-buffer + (insert-file-contents file) + (split-string (buffer-string) "\n" (not keep-empty-lines))))) + +(defun magit-set-header-line-format (string) + "Set the header-line using STRING. +Propertize STRING with the `magit-header-line'. If the `face' +property of any part of STRING is already set, then that takes +precedence. Also pad the left and right sides of STRING so that +it aligns with the text area." + (setq header-line-format + (concat + (propertize " " 'display '(space :align-to 0)) + string + (propertize " " 'display + `(space :width + (+ left-fringe + left-margin + ,@(and (eq (car (window-current-scroll-bars)) + 'left) + '(scroll-bar))))))) + (magit--add-face-text-property 0 (1- (length header-line-format)) + 'magit-header-line t header-line-format)) + +(defun magit-face-property-all (face string) + "Return non-nil if FACE is present in all of STRING." + (cl-loop for pos = 0 then (next-single-property-change + pos 'font-lock-face string) + unless pos + return t + for current = (get-text-property pos 'font-lock-face string) + unless (if (consp current) + (memq face current) + (eq face current)) + return nil)) + +(defun magit--add-face-text-property (beg end face &optional append object) + "Like `add-face-text-property' but for `font-lock-face'." + (cl-loop for pos = (next-single-property-change + beg 'font-lock-face object end) + for current = (get-text-property beg 'font-lock-face object) + for newface = (if (listp current) + (if append + (append current (list face)) + (cons face current)) + (if append + (list current face) + (list face current))) + do (progn (put-text-property beg pos 'font-lock-face newface object) + (setq beg pos)) + while (< beg end))) + +(defun magit--propertize-face (string face) + (propertize string 'face face 'font-lock-face face)) + +(defun magit--put-face (beg end face string) + (put-text-property beg end 'face face string) + (put-text-property beg end 'font-lock-face face string)) + +(defun magit--format-spec (format specification) + "Like `format-spec' but preserve text properties in SPECIFICATION." + (with-temp-buffer + (insert format) + (goto-char (point-min)) + (while (search-forward "%" nil t) + (cond + ;; Quoted percent sign. + ((eq (char-after) ?%) + (delete-char 1)) + ;; Valid format spec. + ((looking-at "\\([-0-9.]*\\)\\([a-zA-Z]\\)") + (let* ((num (match-string 1)) + (spec (string-to-char (match-string 2))) + (val (assq spec specification))) + (unless val + (error "Invalid format character: `%%%c'" spec)) + (setq val (cdr val)) + ;; Pad result to desired length. + (let ((text (format (concat "%" num "s") val))) + ;; Insert first, to preserve text properties. + (if (next-property-change 0 (concat " " text)) + ;; If the inserted text has properties, then preserve those. + (insert text) + ;; Otherwise preserve FORMAT's properties, like `format-spec'. + (insert-and-inherit text)) + ;; Delete the specifier body. + (delete-region (+ (match-beginning 0) (length text)) + (+ (match-end 0) (length text))) + ;; Delete the percent sign. + (delete-region (1- (match-beginning 0)) (match-beginning 0))))) + ;; Signal an error on bogus format strings. + (t + (error "Invalid format string")))) + (buffer-string))) + +;;; Missing from Emacs + +(defun magit-kill-this-buffer () + "Kill the current buffer." + (interactive) + (kill-buffer (current-buffer))) + +(defun magit--buffer-string (&optional min max trim) + "Like `buffer-substring-no-properties' but the arguments are optional. + +This combines the benefits of `buffer-string', `buffer-substring' +and `buffer-substring-no-properties' into one function that is +not as painful to use as the latter. I.e. you can write + (magit--buffer-string) +instead of + (buffer-substring-no-properties (point-min) + (point-max)) + +Optional MIN defaults to the value of `point-min'. +Optional MAX defaults to the value of `point-max'. + +If optional TRIM is non-nil, then all leading and trailing +whitespace is remove. If it is the newline character, then +one trailing newline is added." + ;; Lets write that one last time and be done with it: + (let ((str (buffer-substring-no-properties (or min (point-min)) + (or max (point-max))))) + (if trim + (concat (string-trim str) + (and (eq trim ?\n) "\n")) + str))) + +(cl-defun magit--overlay-at (pos prop &optional (val nil sval) testfn) + (cl-find-if (lambda (o) + (let ((p (overlay-properties o))) + (and (plist-member p prop) + (or (not sval) + (funcall (or testfn #'eql) + (plist-get p prop) + val))))) + (overlays-at pos t))) + +;;; Kludges for Emacs Bugs + +(defun magit-file-accessible-directory-p (filename) + "Like `file-accessible-directory-p' but work around an Apple bug. +See http://debbugs.gnu.org/cgi/bugreport.cgi?bug=21573#17 +and https://github.com/magit/magit/issues/2295." + (and (file-directory-p filename) + (file-accessible-directory-p filename))) + +(when (version<= "25.1" emacs-version) + (with-eval-after-load 'vc-git + (defun vc-git-conflicted-files (directory) + "Return the list of files with conflicts in DIRECTORY." + (let* ((status + (vc-git--run-command-string directory "diff-files" + "--name-status")) + (lines (when status (split-string status "\n" 'omit-nulls))) + files) + (dolist (line lines files) + (when (string-match "\\([ MADRCU?!]\\)[ \t]+\\(.+\\)" line) + (let ((state (match-string 1 line)) + (file (match-string 2 line))) + (when (equal state "U") + (push (expand-file-name file directory) files))))))))) + +(when (< emacs-major-version 27) + (defun vc-git--call@bug21559 (fn buffer command &rest args) + "Backport https://debbugs.gnu.org/cgi/bugreport.cgi?bug=21559." + (let ((process-environment process-environment)) + (when revert-buffer-in-progress-p + (push "GIT_OPTIONAL_LOCKS=0" process-environment)) + (apply fn buffer command args))) + (advice-add 'vc-git--call :around 'vc-git--call@bug21559) + + (defun vc-git-command@bug21559 + (fn buffer okstatus file-or-list &rest flags) + "Backport https://debbugs.gnu.org/cgi/bugreport.cgi?bug=21559." + (let ((process-environment process-environment)) + (when revert-buffer-in-progress-p + (push "GIT_OPTIONAL_LOCKS=0" process-environment)) + (apply fn buffer okstatus file-or-list flags))) + (advice-add 'vc-git-command :around 'vc-git-command@bug21559) + + (defun auto-revert-handler@bug21559 (fn) + "Backport https://debbugs.gnu.org/cgi/bugreport.cgi?bug=21559." + (let ((revert-buffer-in-progress-p t)) + (funcall fn))) + (advice-add 'auto-revert-handler :around 'auto-revert-handler@bug21559) + ) + +;; `completion-pcm--all-completions' reverses the completion list. To +;; preserve the order of our pre-sorted completions, we'll temporarily +;; override it with the function below. bug#24676 +(defun magit-completion-pcm--all-completions (prefix pattern table pred) + (if (completion-pcm--pattern-trivial-p pattern) + (all-completions (concat prefix (car pattern)) table pred) + (let* ((regex (completion-pcm--pattern->regex pattern)) + (case-fold-search completion-ignore-case) + (completion-regexp-list (cons regex completion-regexp-list)) + (compl (all-completions + (concat prefix + (if (stringp (car pattern)) (car pattern) "")) + table pred))) + (if (not (functionp table)) + compl + (let ((poss ())) + (dolist (c compl) + (when (string-match-p regex c) (push c poss))) + ;; This `nreverse' call is the only code change made to the + ;; `completion-pcm--all-completions' that shipped with Emacs 25.1. + (nreverse poss)))))) + +(defun magit-which-function () + "Return current function name based on point. + +This is a simple wrapper around `which-function', that resets +Imenu's potentially outdated and therefore unreliable cache by +setting `imenu--index-alist' to nil before calling that function." + (setq imenu--index-alist nil) + (which-function)) + +;;; Kludges for Custom + +(defun magit-custom-initialize-reset (symbol exp) + "Initialize SYMBOL based on EXP. +Set the symbol, using `set-default' (unlike +`custom-initialize-reset' which uses the `:set' function if any.) +The value is either the symbol's current value + (as obtained using the `:get' function), if any, +or the value in the symbol's `saved-value' property if any, +or (last of all) the value of EXP." + (set-default-toplevel-value + symbol + (condition-case nil + (let ((def (default-toplevel-value symbol)) + (getter (get symbol 'custom-get))) + (if getter (funcall getter symbol) def)) + (error + (eval (let ((sv (get symbol 'saved-value))) + (if sv (car sv) exp))))))) + +(defun magit-hook-custom-get (symbol) + (if (symbol-file symbol 'defvar) + (default-toplevel-value symbol) + ;; + ;; Called by `custom-initialize-reset' on behalf of `symbol's + ;; `defcustom', which is being evaluated for the first time to + ;; set the initial value, but there's already a default value, + ;; which most likely was established by one or more `add-hook' + ;; calls. + ;; + ;; We combine the `standard-value' and the current value, while + ;; preserving the order established by `:options', and return + ;; the result of that to be used as the "initial" default value. + ;; + (let ((standard (eval (car (get symbol 'standard-value)))) + (current (default-toplevel-value symbol)) + (value nil)) + (dolist (fn (get symbol 'custom-options)) + (when (or (memq fn standard) + (memq fn current)) + (push fn value))) + (dolist (fn current) + (unless (memq fn value) + (push fn value))) + (nreverse value)))) + +;;; Kludges for Info Manuals + +;;;###autoload +(defun Info-follow-nearest-node--magit-gitman (fn &optional fork) + (let ((node (Info-get-token + (point) "\\*note[ \n\t]+" + "\\*note[ \n\t]+\\([^:]*\\):\\(:\\|[ \n\t]*(\\)?"))) + (if (and node (string-match "^(gitman)\\(.+\\)" node)) + (pcase magit-view-git-manual-method + (`info (funcall fn fork)) + (`man (require 'man) + (man (match-string 1 node))) + (`woman (require 'woman) + (woman (match-string 1 node))) + (_ + (user-error "Invalid value for `magit-view-git-manual-method'"))) + (funcall fn fork)))) + +;;;###autoload +(advice-add 'Info-follow-nearest-node :around + 'Info-follow-nearest-node--magit-gitman) + +;;;###autoload +(defun org-man-export--magit-gitman (fn link description format) + (if (and (eq format 'texinfo) + (string-match-p "\\`git" link)) + (replace-regexp-in-string "%s" link " +@ifinfo +@ref{%s,,,gitman,}. +@end ifinfo +@ifhtml +@html +the %s(1) manpage. +@end html +@end ifhtml +@iftex +the %s(1) manpage. +@end iftex +") + (funcall fn link description format))) + +;;;###autoload +(advice-add 'org-man-export :around + 'org-man-export--magit-gitman) + +;;; Bitmaps + +(when (fboundp 'define-fringe-bitmap) + (define-fringe-bitmap 'magit-fringe-bitmap+ + [#b00000000 + #b00011000 + #b00011000 + #b01111110 + #b01111110 + #b00011000 + #b00011000 + #b00000000]) + (define-fringe-bitmap 'magit-fringe-bitmap- + [#b00000000 + #b00000000 + #b00000000 + #b01111110 + #b01111110 + #b00000000 + #b00000000 + #b00000000]) + + (define-fringe-bitmap 'magit-fringe-bitmap> + [#b01100000 + #b00110000 + #b00011000 + #b00001100 + #b00011000 + #b00110000 + #b01100000 + #b00000000]) + (define-fringe-bitmap 'magit-fringe-bitmapv + [#b00000000 + #b10000010 + #b11000110 + #b01101100 + #b00111000 + #b00010000 + #b00000000 + #b00000000]) + + (define-fringe-bitmap 'magit-fringe-bitmap-bold> + [#b11100000 + #b01110000 + #b00111000 + #b00011100 + #b00011100 + #b00111000 + #b01110000 + #b11100000]) + (define-fringe-bitmap 'magit-fringe-bitmap-boldv + [#b10000001 + #b11000011 + #b11100111 + #b01111110 + #b00111100 + #b00011000 + #b00000000 + #b00000000]) + ) + +;;; Miscellaneous + +(defun magit-message (format-string &rest args) + "Display a message at the bottom of the screen, or not. +Like `message', except that if the users configured option +`magit-no-message' to prevent the message corresponding to +FORMAT-STRING to be displayed, then don't." + (unless (--first (string-prefix-p it format-string) magit-no-message) + (apply #'message format-string args))) + +(defun magit-msg (format-string &rest args) + "Display a message at the bottom of the screen, but don't log it. +Like `message', except that `message-log-max' is bound to nil." + (let ((message-log-max nil)) + (apply #'message format-string args))) + +(defmacro magit--with-temp-position (buf pos &rest body) + (declare (indent 2)) + `(with-current-buffer ,buf + (save-excursion + (save-restriction + (widen) + (goto-char ,pos) + ,@body)))) + +;;; _ +(provide 'magit-utils) +;;; magit-utils.el ends here diff --git a/elpa/magit-20191122.2040/magit-utils.elc b/elpa/magit-20191122.2040/magit-utils.elc new file mode 100644 index 0000000000000000000000000000000000000000..049cf1d4585beac1e6f89c1d7f1134438b11fa11 GIT binary patch literal 40322 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 +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; This library defines tree global modes which automatically commit +;; snapshots to branch-specific work-in-progress refs before and after +;; making changes, and two commands which can be used to do so on +;; demand. + +;;; Code: + +(eval-when-compile + (require 'subr-x)) + +(require 'magit-core) +(require 'magit-log) + +;;; Options + +(defgroup magit-wip nil + "Automatically commit to work-in-progress refs." + :link '(info-link "(magit)Wip Modes") + :group 'magit-modes + :group 'magit-essentials) + +(defgroup magit-wip-legacy nil + "It is better to not use these modes individually." + :link '(info-link "(magit)Legacy Wip Modes") + :group 'magit-wip) + +(defcustom magit-wip-mode-lighter " Wip" + "Lighter for Magit-Wip mode." + :package-version '(magit . "2.90.0") + :group 'magit-wip + :type 'string) + +(defcustom magit-wip-after-save-local-mode-lighter "" + "Lighter for Magit-Wip-After-Save-Local mode." + :package-version '(magit . "2.1.0") + :group 'magit-wip-legacy + :type 'string) + +(defcustom magit-wip-after-apply-mode-lighter "" + "Lighter for Magit-Wip-After-Apply mode." + :package-version '(magit . "2.1.0") + :group 'magit-wip-legacy + :type 'string) + +(defcustom magit-wip-before-change-mode-lighter "" + "Lighter for Magit-Wip-Before-Change mode." + :package-version '(magit . "2.1.0") + :group 'magit-wip-legacy + :type 'string) + +(defcustom magit-wip-initial-backup-mode-lighter "" + "Lighter for Magit-Wip-Initial Backup mode." + :package-version '(magit . "2.1.0") + :group 'magit-wip-legacy + :type 'string) + +(defcustom magit-wip-merge-branch nil + "Whether to merge the current branch into its wip ref. + +If non-nil and the current branch has new commits, then it is +merged into the wip ref before creating a new wip commit. This +makes it easier to inspect wip history and the wip commits are +never garbage collected. + +If nil and the current branch has new commits, then the wip ref +is reset to the tip of the branch before creating a new wip +commit. With this setting wip commits are eventually garbage +collected. This is currently the default." + :package-version '(magit . "2.90.0") + :group 'magit-wip + :type 'boolean) + +(defcustom magit-wip-namespace "refs/wip/" + "Namespace used for work-in-progress refs. +The wip refs are named \"index/\" +and \"wtree/\". When snapshots +are created while the `HEAD' is detached then \"HEAD\" +is used as `branch-ref'." + :package-version '(magit . "2.1.0") + :group 'magit-wip + :type 'string) + +;;; Modes + +(define-minor-mode magit-wip-mode + "Save uncommitted changes to work-in-progress refs. + +Whenever appropriate (i.e. when dataloss would be a possibility +otherwise) this mode causes uncommitted changes to be committed +to dedicated work-in-progress refs. + +For historic reasons this mode is implemented on top of four +other `magit-wip-*' modes, which can also be used individually, +if you want finer control over when the wip refs are updated; +but that is discouraged." + :package-version '(magit . "2.90.0") + :lighter magit-wip-mode-lighter + :global t + (let ((arg (if magit-wip-mode 1 -1))) + (magit-wip-after-save-mode arg) + (magit-wip-after-apply-mode arg) + (magit-wip-before-change-mode arg) + (magit-wip-initial-backup-mode arg))) + +(define-minor-mode magit-wip-after-save-local-mode + "After saving, also commit to a worktree work-in-progress ref. + +After saving the current file-visiting buffer this mode also +commits the changes to the worktree work-in-progress ref for +the current branch. + +This mode should be enabled globally by turning on the globalized +variant `magit-wip-after-save-mode'." + :package-version '(magit . "2.1.0") + :lighter magit-wip-after-save-local-mode-lighter + (if magit-wip-after-save-local-mode + (if (and buffer-file-name (magit-inside-worktree-p t)) + (add-hook 'after-save-hook 'magit-wip-commit-buffer-file t t) + (setq magit-wip-after-save-local-mode nil) + (user-error "Need a worktree and a file")) + (remove-hook 'after-save-hook 'magit-wip-commit-buffer-file t))) + +(defun magit-wip-after-save-local-mode-turn-on () + (and buffer-file-name + (magit-inside-worktree-p t) + (magit-file-tracked-p buffer-file-name) + (magit-wip-after-save-local-mode))) + +;;;###autoload +(define-globalized-minor-mode magit-wip-after-save-mode + magit-wip-after-save-local-mode magit-wip-after-save-local-mode-turn-on + :package-version '(magit . "2.1.0") + :group 'magit-wip) + +(defun magit-wip-commit-buffer-file (&optional msg) + "Commit visited file to a worktree work-in-progress ref. + +Also see `magit-wip-after-save-mode' which calls this function +automatically whenever a buffer visiting a tracked file is saved." + (interactive) + (--when-let (magit-wip-get-ref) + (magit-with-toplevel + (let ((file (file-relative-name buffer-file-name))) + (magit-wip-commit-worktree + it (list file) + (format (cond (msg) + ((called-interactively-p 'any) + "wip-save %s after save") + (t + "autosave %s after save")) + file)))))) + +;;;###autoload +(define-minor-mode magit-wip-after-apply-mode + "Commit to work-in-progress refs. + +After applying a change using any \"apply variant\" +command (apply, stage, unstage, discard, and reverse) commit the +affected files to the current wip refs. For each branch there +may be two wip refs; one contains snapshots of the files as found +in the worktree and the other contains snapshots of the entries +in the index." + :package-version '(magit . "2.1.0") + :group 'magit-wip + :lighter magit-wip-after-apply-mode-lighter + :global t) + +(defun magit-wip-commit-after-apply (&optional files msg) + (when magit-wip-after-apply-mode + (magit-wip-commit files msg))) + +;;;###autoload +(define-minor-mode magit-wip-before-change-mode + "Commit to work-in-progress refs before certain destructive changes. + +Before invoking a revert command or an \"apply variant\" +command (apply, stage, unstage, discard, and reverse) commit the +affected tracked files to the current wip refs. For each branch +there may be two wip refs; one contains snapshots of the files +as found in the worktree and the other contains snapshots of the +entries in the index. + +Only changes to files which could potentially be affected by the +command which is about to be called are committed." + :package-version '(magit . "2.1.0") + :group 'magit-wip + :lighter magit-wip-before-change-mode-lighter + :global t) + +(defun magit-wip-commit-before-change (&optional files msg) + (when magit-wip-before-change-mode + (magit-with-toplevel + (magit-wip-commit files msg)))) + +(define-minor-mode magit-wip-initial-backup-mode + "Before saving a buffer for the first time, commit to a wip ref." + :package-version '(magit . "2.90.0") + :group 'magit-wip + :lighter magit-wip-initial-backup-mode-lighter + :global t + (if magit-wip-initial-backup-mode + (add-hook 'before-save-hook 'magit-wip-commit-initial-backup) + (remove-hook 'before-save-hook 'magit-wip-commit-initial-backup))) + +(defvar-local magit-wip-buffer-backed-up nil) +(put 'magit-wip-buffer-backed-up 'permanent-local t) + +;;;###autoload +(defun magit-wip-commit-initial-backup () + "Before saving, commit current file to a worktree wip ref. + +The user has to add this function to `before-save-hook'. + +Commit the current state of the visited file before saving the +current buffer to that file. This backs up the same version of +the file as `backup-buffer' would, but stores the backup in the +worktree wip ref, which is also used by the various Magit Wip +modes, instead of in a backup file as `backup-buffer' would. + +This function ignores the variables that affect `backup-buffer' +and can be used along-side that function, which is recommended +because this function only backs up files that are tracked in +a Git repository." + (when (and (not magit-wip-buffer-backed-up) + buffer-file-name + (magit-inside-worktree-p t) + (magit-file-tracked-p buffer-file-name)) + (let ((magit-save-repository-buffers nil)) + (magit-wip-commit-buffer-file "autosave %s before save")) + (setq magit-wip-buffer-backed-up t))) + +;;; Core + +(defun magit-wip-commit (&optional files msg) + "Commit all tracked files to the work-in-progress refs. + +Interactively, commit all changes to all tracked files using +a generic commit message. With a prefix-argument the commit +message is read in the minibuffer. + +Non-interactively, only commit changes to FILES using MSG as +commit message." + (interactive (list nil (if current-prefix-arg + (magit-read-string "Wip commit message") + "wip-save tracked files"))) + (--when-let (magit-wip-get-ref) + (magit-wip-commit-index it files msg) + (magit-wip-commit-worktree it files msg))) + +(defun magit-wip-commit-index (ref files msg) + (let* ((wipref (magit--wip-index-ref ref)) + (parent (magit-wip-get-parent ref wipref)) + (tree (magit-git-string "write-tree"))) + (magit-wip-update-wipref ref wipref tree parent files msg "index"))) + +(defun magit-wip-commit-worktree (ref files msg) + (let* ((wipref (magit--wip-wtree-ref ref)) + (parent (magit-wip-get-parent ref wipref)) + (tree (magit-with-temp-index parent "--reset" + (if files + (magit-call-git "add" "--" files) + (magit-with-toplevel + (magit-call-git "add" "-u" "."))) + (magit-git-string "write-tree")))) + (magit-wip-update-wipref ref wipref tree parent files msg "worktree"))) + +(defun magit-wip-update-wipref (ref wipref tree parent files msg start-msg) + (cond + ((and (not (equal parent wipref)) + (or (not magit-wip-merge-branch) + (not (magit-rev-verify wipref)))) + (setq start-msg (concat "start autosaving " start-msg)) + (magit-update-ref wipref start-msg + (magit-git-string "commit-tree" "--no-gpg-sign" + "-p" parent "-m" start-msg + (concat parent "^{tree}"))) + (setq parent wipref)) + ((and magit-wip-merge-branch + (or (not (magit-rev-ancestor-p ref wipref)) + (not (magit-rev-ancestor-p + (concat (magit-git-string "log" "--format=%H" + "-1" "--merges" wipref) + "^2") + ref)))) + (setq start-msg (format "merge %s into %s" ref start-msg)) + (magit-update-ref wipref start-msg + (magit-git-string "commit-tree" "--no-gpg-sign" + "-p" wipref "-p" ref + "-m" start-msg + (concat ref "^{tree}"))) + (setq parent wipref))) + (when (magit-git-failure "diff-tree" "--quiet" parent tree "--" files) + (unless (and msg (not (= (aref msg 0) ?\s))) + (let ((len (length files))) + (setq msg (concat + (cond ((= len 0) "autosave tracked files") + ((> len 1) (format "autosave %s files" len)) + (t (concat "autosave " + (file-relative-name (car files) + (magit-toplevel))))) + msg)))) + (magit-update-ref wipref msg + (magit-git-string "commit-tree" "--no-gpg-sign" + "-p" parent "-m" msg tree)))) + +(defun magit-wip-get-ref () + (let ((ref (or (magit-git-string "symbolic-ref" "HEAD") "HEAD"))) + (and (magit-rev-verify ref) + ref))) + +(defun magit-wip-get-parent (ref wipref) + (if (and (magit-rev-verify wipref) + (equal (magit-git-string "merge-base" wipref ref) + (magit-rev-verify ref))) + wipref + ref)) + +(defun magit--wip-index-ref (&optional ref) + (magit--wip-ref "index/" ref)) + +(defun magit--wip-wtree-ref (&optional ref) + (magit--wip-ref "wtree/" ref)) + +(defun magit--wip-ref (namespace &optional ref) + (concat magit-wip-namespace namespace + (or (and ref (string-prefix-p "refs/" ref) ref) + (when-let ((branch (or ref (magit-get-current-branch)))) + (concat "refs/heads/" branch)) + "HEAD"))) + +(defun magit-wip-maybe-add-commit-hook () + (when (and magit-wip-merge-branch + (magit-wip-any-enabled-p)) + (add-hook 'git-commit-post-finish-hook 'magit-wip-commit nil t))) + +(defun magit-wip-any-enabled-p () + (or magit-wip-mode + magit-wip-after-save-local-mode + magit-wip-after-save-mode + magit-wip-after-apply-mode + magit-wip-before-change-mode + magit-wip-initial-backup-mode)) + +;;; Log + +(defun magit-wip-log-index (args files) + "Show log for the index wip ref of the current branch." + (interactive (magit-log-arguments)) + (magit-log-setup-buffer (list (magit--wip-index-ref)) args files)) + +(defun magit-wip-log-worktree (args files) + "Show log for the worktree wip ref of the current branch." + (interactive (magit-log-arguments)) + (magit-log-setup-buffer (list (magit--wip-wtree-ref)) args files)) + +(defun magit-wip-log-current (branch args files count) + "Show log for the current branch and its wip refs. +With a negative prefix argument only show the worktree wip ref. +The absolute numeric value of the prefix argument controls how +many \"branches\" of each wip ref are shown." + (interactive + (nconc (list (or (magit-get-current-branch) "HEAD")) + (magit-log-arguments) + (list (prefix-numeric-value current-prefix-arg)))) + (magit-wip-log branch args files count)) + +(defun magit-wip-log (branch args files count) + "Show log for a branch and its wip refs. +With a negative prefix argument only show the worktree wip ref. +The absolute numeric value of the prefix argument controls how +many \"branches\" of each wip ref are shown." + (interactive + (nconc (list (magit-completing-read + "Log branch and its wip refs" + (-snoc (magit-list-local-branch-names) "HEAD") + nil t nil 'magit-revision-history + (or (magit-branch-at-point) + (magit-get-current-branch) + "HEAD"))) + (magit-log-arguments) + (list (prefix-numeric-value current-prefix-arg)))) + (magit-log-setup-buffer (nconc (list branch) + (magit-wip-log-get-tips + (magit--wip-wtree-ref branch) + (abs count)) + (and (>= count 0) + (magit-wip-log-get-tips + (magit--wip-index-ref branch) + (abs count)))) + args files)) + +(defun magit-wip-log-get-tips (wipref count) + (when-let ((reflog (magit-git-lines "reflog" wipref))) + (let (tips) + (while (and reflog (> count 1)) + (setq reflog (cl-member "^[^ ]+ [^:]+: restart autosaving" + reflog :test #'string-match-p)) + (when (and (cadr reflog) + (string-match "^[^ ]+ \\([^:]+\\)" (cadr reflog))) + (push (match-string 1 (cadr reflog)) tips)) + (setq reflog (cddr reflog)) + (cl-decf count)) + (cons wipref (nreverse tips))))) + +;;; _ +(provide 'magit-wip) +;;; magit-wip.el ends here diff --git a/elpa/magit-20191122.2040/magit-wip.elc b/elpa/magit-20191122.2040/magit-wip.elc new file mode 100644 index 0000000000000000000000000000000000000000..47e3790397fc0c709655de7a2f16873ce80decd7 GIT binary patch literal 26804 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 +;; Maintainer: Jonas Bernoulli + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; This library implements support for `git-worktree'. + +;;; Code: + +(require 'magit) + +;;; Options + +(defcustom magit-worktree-read-directory-name-function 'read-directory-name + "Function used to read a directory for worktree commands. +This is called with one argument, the prompt, and can be used +to e.g. use a base directory other than `default-directory'. +Used by `magit-worktree-checkout' and `magit-worktree-branch'." + :package-version '(magit . "2.91.0") + :group 'magit-commands + :type 'function) + +;;; Commands + +;;;###autoload (autoload 'magit-worktree "magit-worktree" nil t) +(define-transient-command magit-worktree () + "Act on a worktree." + :man-page "git-worktree" + [["Create new" + ("b" "worktree" magit-worktree-checkout) + ("c" "branch and worktree" magit-worktree-branch)] + ["Commands" + ("m" "Move worktree" magit-worktree-move) + ("k" "Delete worktree" magit-worktree-delete) + ("g" "Visit worktree" magit-worktree-status)]]) + +;;;###autoload +(defun magit-worktree-checkout (path branch) + "Checkout BRANCH in a new worktree at PATH." + (interactive + (let ((branch (magit-read-branch-or-commit "Checkout"))) + (list (funcall magit-worktree-read-directory-name-function + (format "Checkout %s in new worktree: " branch)) + branch))) + (magit-run-git "worktree" "add" (expand-file-name path) branch) + (magit-diff-visit-directory path)) + +;;;###autoload +(defun magit-worktree-branch (path branch start-point &optional force) + "Create a new BRANCH and check it out in a new worktree at PATH." + (interactive + `(,(funcall magit-worktree-read-directory-name-function + "Create worktree: ") + ,@(magit-branch-read-args "Create and checkout branch") + ,current-prefix-arg)) + (magit-run-git "worktree" "add" (if force "-B" "-b") + branch (expand-file-name path) start-point) + (magit-diff-visit-directory path)) + +;;;###autoload +(defun magit-worktree-move (worktree path) + "Move WORKTREE to PATH." + (interactive + (list (magit-completing-read "Move worktree" + (cdr (magit-list-worktrees)) + nil t nil nil + (magit-section-value-if 'worktree)) + (funcall magit-worktree-read-directory-name-function + "Move worktree to: "))) + (if (file-directory-p (expand-file-name ".git" worktree)) + (user-error "You may not move the main working tree") + (let ((preexisting-directory (file-directory-p path))) + (when (and (zerop (magit-call-git "worktree" "move" worktree + (expand-file-name path))) + (not (file-exists-p default-directory)) + (derived-mode-p 'magit-status-mode)) + (kill-buffer) + (magit-diff-visit-directory + (if preexisting-directory + (concat (file-name-as-directory path) + (file-name-nondirectory worktree)) + path))) + (magit-refresh)))) + +(defun magit-worktree-delete (worktree) + "Delete a worktree, defaulting to the worktree at point. +The primary worktree cannot be deleted." + (interactive + (list (magit-completing-read "Delete worktree" + (cdr (magit-list-worktrees)) + nil t nil nil + (magit-section-value-if 'worktree)))) + (if (file-directory-p (expand-file-name ".git" worktree)) + (user-error "Deleting %s would delete the shared .git directory" worktree) + (let ((primary (file-name-as-directory (caar (magit-list-worktrees))))) + (magit-confirm-files (if magit-delete-by-moving-to-trash 'trash 'delete) + (list "worktree")) + (when (file-exists-p worktree) + (let ((delete-by-moving-to-trash magit-delete-by-moving-to-trash)) + (delete-directory worktree t magit-delete-by-moving-to-trash))) + (if (file-exists-p default-directory) + (magit-run-git "worktree" "prune") + (let ((default-directory primary)) + (magit-run-git "worktree" "prune")) + (when (derived-mode-p 'magit-status-mode) + (kill-buffer) + (magit-status-setup-buffer primary)))))) + +(defun magit-worktree-status (worktree) + "Show the status for the worktree at point. +If there is no worktree at point, then read one in the +minibuffer. If the worktree at point is the one whose +status is already being displayed in the current buffer, +then show it in Dired instead." + (interactive + (list (or (magit-section-value-if 'worktree) + (magit-completing-read + "Show status for worktree" + (cl-delete (directory-file-name (magit-toplevel)) + (magit-list-worktrees) + :test #'equal :key #'car))))) + (magit-diff-visit-directory worktree)) + +;;; Sections + +(defvar magit-worktree-section-map + (let ((map (make-sparse-keymap))) + (define-key map [remap magit-visit-thing] 'magit-worktree-status) + (define-key map [remap magit-delete-thing] 'magit-worktree-delete) + map) + "Keymap for `worktree' sections.") + +(defun magit-insert-worktrees () + "Insert sections for all worktrees. +If there is only one worktree, then insert nothing." + (let ((worktrees (magit-list-worktrees))) + (when (> (length worktrees) 1) + (magit-insert-section (worktrees) + (magit-insert-heading "Worktrees:") + (let* ((cols + (mapcar + (pcase-lambda (`(,path ,barep ,commit ,branch)) + (cons (cond + (branch (propertize + branch 'font-lock-face 'magit-branch-local)) + (commit (propertize (magit-rev-abbrev commit) + 'font-lock-face 'magit-hash)) + (barep "(bare)")) + path)) + worktrees)) + (align (1+ (-max (--map (string-width (car it)) cols))))) + (pcase-dolist (`(,head . ,path) cols) + (magit-insert-section (worktree path) + (insert head) + (indent-to align) + (insert (let ((r (file-relative-name path)) + (a (abbreviate-file-name path))) + (if (< (string-width r) (string-width a)) r a))) + (insert ?\n)))) + (insert ?\n))))) + +;;; _ +(provide 'magit-worktree) +;;; magit-worktree.el ends here diff --git a/elpa/magit-20191122.2040/magit-worktree.elc b/elpa/magit-20191122.2040/magit-worktree.elc new file mode 100644 index 0000000000000000000000000000000000000000..e71b21d6b76ee2e15c549b6f43bc22242d483bfc GIT binary patch literal 8598 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 literal 0 HcmV?d00001 diff --git a/elpa/magit-20191122.2040/magit.el b/elpa/magit-20191122.2040/magit.el new file mode 100644 index 00000000..9f26c71f --- /dev/null +++ b/elpa/magit-20191122.2040/magit.el @@ -0,0 +1,596 @@ +;;; magit.el --- A Git porcelain inside Emacs -*- lexical-binding: t; coding: utf-8 -*- + +;; Copyright (C) 2008-2019 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Marius Vollmer +;; Maintainer: Jonas Bernoulli +;; Kyle Meyer +;; Noam Postavsky +;; Former-Maintainers: +;; Nicolas Dudebout +;; Peter J. Weisberg +;; Phil Jackson +;; Rémi Vanicat +;; Yann Hodique + +;; Keywords: git tools vc +;; Homepage: https://github.com/magit/magit + +;; Magit requires at least GNU Emacs 25.1 and Git 2.2.0. + +;; Magit is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; Magit is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Magit. If not, see http://www.gnu.org/licenses. + +;;; Commentary: + +;; Magit is an interface to the version control system Git, +;; implemented as an Emacs package. Magit aspires to be a complete +;; Git porcelain. While we cannot (yet) claim, that Magit wraps and +;; improves upon each and every Git command, it is complete enough to +;; allow even experienced Git users to perform almost all of their +;; daily version control tasks directly from within Emacs. While many +;; fine Git clients exist, only Magit and Git itself deserve to be +;; called porcelains. + +;;; Code: + +(require 'cl-lib) +(require 'dash) + +(require 'subr-x) + +(require 'with-editor) +(require 'git-commit) +(require 'magit-core) +(require 'magit-diff) +(require 'magit-log) +(require 'magit-wip) +(require 'magit-apply) +(require 'magit-repos) + +(require 'format-spec) +(require 'package nil t) ; used in `magit-version' + +(defconst magit--minimal-git "2.2.0") +(defconst magit--minimal-emacs "25.1") + +;;; Faces + +(defface magit-header-line + '((t :inherit magit-section-heading)) + "Face for the `header-line' in some Magit modes. +Note that some modes, such as `magit-log-select-mode', have their +own faces for the `header-line', or for parts of the +`header-line'." + :group 'magit-faces) + +(defface magit-header-line-key + '((t :inherit magit-popup-key)) + "Face for keys in the `header-line'." + :group 'magit-faces) + +(defface magit-dimmed + '((((class color) (background light)) :foreground "grey50") + (((class color) (background dark)) :foreground "grey50")) + "Face for text that shouldn't stand out." + :group 'magit-faces) + +(defface magit-hash + '((((class color) (background light)) :foreground "grey60") + (((class color) (background dark)) :foreground "grey40")) + "Face for the sha1 part of the log output." + :group 'magit-faces) + +(defface magit-tag + '((((class color) (background light)) :foreground "Goldenrod4") + (((class color) (background dark)) :foreground "LightGoldenrod2")) + "Face for tag labels shown in log buffer." + :group 'magit-faces) + +(defface magit-branch-remote + '((((class color) (background light)) :foreground "DarkOliveGreen4") + (((class color) (background dark)) :foreground "DarkSeaGreen2")) + "Face for remote branch head labels shown in log buffer." + :group 'magit-faces) + +(defface magit-branch-remote-head + '((((class color) (background light)) :inherit magit-branch-remote :box t) + (((class color) (background dark)) :inherit magit-branch-remote :box t)) + "Face for current branch." + :group 'magit-faces) + +(defface magit-branch-local + '((((class color) (background light)) :foreground "SkyBlue4") + (((class color) (background dark)) :foreground "LightSkyBlue1")) + "Face for local branches." + :group 'magit-faces) + +(defface magit-branch-current + '((((class color) (background light)) :inherit magit-branch-local :box t) + (((class color) (background dark)) :inherit magit-branch-local :box t)) + "Face for current branch." + :group 'magit-faces) + +(defface magit-branch-upstream + '((t :slant italic)) + "Face for upstream branch. +This face is only used in logs and it gets combined + with `magit-branch-local', `magit-branch-remote' +and/or `magit-branch-remote-head'." + :group 'magit-faces) + +(defface magit-head + '((((class color) (background light)) :inherit magit-branch-local) + (((class color) (background dark)) :inherit magit-branch-local)) + "Face for the symbolic ref `HEAD'." + :group 'magit-faces) + +(defface magit-refname + '((((class color) (background light)) :foreground "grey30") + (((class color) (background dark)) :foreground "grey80")) + "Face for refnames without a dedicated face." + :group 'magit-faces) + +(defface magit-refname-stash + '((t :inherit magit-refname)) + "Face for stash refnames." + :group 'magit-faces) + +(defface magit-refname-wip + '((t :inherit magit-refname)) + "Face for wip refnames." + :group 'magit-faces) + +(defface magit-refname-pullreq + '((t :inherit magit-refname)) + "Face for pullreq refnames." + :group 'magit-faces) + +(defface magit-keyword + '((t :inherit font-lock-string-face)) + "Face for parts of commit messages inside brackets." + :group 'magit-faces) + +(defface magit-keyword-squash + '((t :inherit font-lock-warning-face)) + "Face for squash! and fixup! keywords in commit messages." + :group 'magit-faces) + +(defface magit-signature-good + '((t :foreground "green")) + "Face for good signatures." + :group 'magit-faces) + +(defface magit-signature-bad + '((t :foreground "red" :weight bold)) + "Face for bad signatures." + :group 'magit-faces) + +(defface magit-signature-untrusted + '((t :foreground "cyan")) + "Face for good untrusted signatures." + :group 'magit-faces) + +(defface magit-signature-expired + '((t :foreground "orange")) + "Face for signatures that have expired." + :group 'magit-faces) + +(defface magit-signature-expired-key + '((t :inherit magit-signature-expired)) + "Face for signatures made by an expired key." + :group 'magit-faces) + +(defface magit-signature-revoked + '((t :foreground "violet red")) + "Face for signatures made by a revoked key." + :group 'magit-faces) + +(defface magit-signature-error + '((t :foreground "firebrick3")) + "Face for signatures that cannot be checked (e.g. missing key)." + :group 'magit-faces) + +(defface magit-cherry-unmatched + '((t :foreground "cyan")) + "Face for unmatched cherry commits." + :group 'magit-faces) + +(defface magit-cherry-equivalent + '((t :foreground "magenta")) + "Face for equivalent cherry commits." + :group 'magit-faces) + +(defface magit-filename + '((t :weight normal)) + "Face for filenames." + :group 'magit-faces) + +;;; Dispatch Popup + +;;;###autoload (autoload 'magit-dispatch "magit" nil t) +(define-transient-command magit-dispatch () + "Invoke a Magit command from a list of available commands." + ["Transient and dwim commands" + [("A" "Apply" magit-cherry-pick) + ("b" "Branch" magit-branch) + ("B" "Bisect" magit-bisect) + ("c" "Commit" magit-commit) + ("C" "Clone" magit-clone) + ("d" "Diff" magit-diff) + ("D" "Diff (change)" magit-diff-refresh) + ("e" "Ediff (dwim)" magit-ediff-dwim) + ("E" "Ediff" magit-ediff)] + [("f" "Fetch" magit-fetch) + ("F" "Pull" magit-pull) + ("l" "Log" magit-log) + ("L" "Log (change)" magit-log-refresh) + ("m" "Merge" magit-merge) + ("M" "Remote" magit-remote) + ("o" "Submodule" magit-submodule) + ("O" "Subtree" magit-subtree)] + [("P" "Push" magit-push) + ("r" "Rebase" magit-rebase) + ("t" "Tag" magit-tag) + ("T" "Note" magit-notes) + ("V" "Revert" magit-revert) + ("w" "Apply patches" magit-am) + ("W" "Format patches" magit-patch) + ("X" "Reset" magit-reset)] + [("y" "Show Refs" magit-show-refs) + ("Y" "Cherries" magit-cherry) + ("z" "Stash" magit-stash) + ("!" "Run" magit-run) + ("%" "Worktree" magit-worktree)]] + ["Applying changes" + :if-derived magit-mode + [("a" "Apply" magit-apply) + ("v" "Reverse" magit-reverse) + ("k" "Discard" magit-discard)] + [("s" "Stage" magit-stage) + ("u" "Unstage" magit-unstage)] + [("S" "Stage all" magit-stage-modified) + ("U" "Unstage all" magit-unstage-all)]] + ["Essential commands" + :if-derived magit-mode + ("g" " refresh current buffer" magit-refresh) + ("" " toggle section at point" magit-section-toggle) + ("" "visit thing at point" magit-visit-thing) + ("C-h m" " show all key bindings" describe-mode)]) + +;;; Git Popup + +(defcustom magit-shell-command-verbose-prompt t + "Whether to show the working directory when reading a command. +This affects `magit-git-command', `magit-git-command-topdir', +`magit-shell-command', and `magit-shell-command-topdir'." + :package-version '(magit . "2.11.0") + :group 'magit-commands + :type 'boolean) + +(defvar magit-git-command-history nil) + +;;;###autoload (autoload 'magit-run "magit" nil t) +(define-transient-command magit-run () + "Run git or another command, or launch a graphical utility." + [["Run git subcommand" + ("!" "in repository root" magit-git-command-topdir) + ("p" "in working directory" magit-git-command)] + ["Run shell command" + ("s" "in repository root" magit-shell-command-topdir) + ("S" "in working directory" magit-shell-command)] + ["Launch" + ("k" "gitk" magit-run-gitk) + ("a" "gitk --all" magit-run-gitk-all) + ("b" "gitk --branches" magit-run-gitk-branches) + ("g" "git gui" magit-run-git-gui)]]) + +;;;###autoload +(defun magit-git-command (command) + "Execute COMMAND asynchronously; display output. + +Interactively, prompt for COMMAND in the minibuffer. \"git \" is +used as initial input, but can be deleted to run another command. + +With a prefix argument COMMAND is run in the top-level directory +of the current working tree, otherwise in `default-directory'." + (interactive (list (magit-read-shell-command nil "git "))) + (magit--shell-command command)) + +;;;###autoload +(defun magit-git-command-topdir (command) + "Execute COMMAND asynchronously; display output. + +Interactively, prompt for COMMAND in the minibuffer. \"git \" is +used as initial input, but can be deleted to run another command. + +COMMAND is run in the top-level directory of the current +working tree." + (interactive (list (magit-read-shell-command t "git "))) + (magit--shell-command command (magit-toplevel))) + +;;;###autoload +(defun magit-shell-command (command) + "Execute COMMAND asynchronously; display output. + +Interactively, prompt for COMMAND in the minibuffer. With a +prefix argument COMMAND is run in the top-level directory of +the current working tree, otherwise in `default-directory'." + (interactive (list (magit-read-shell-command))) + (magit--shell-command command)) + +;;;###autoload +(defun magit-shell-command-topdir (command) + "Execute COMMAND asynchronously; display output. + +Interactively, prompt for COMMAND in the minibuffer. COMMAND +is run in the top-level directory of the current working tree." + (interactive (list (magit-read-shell-command t))) + (magit--shell-command command (magit-toplevel))) + +(defun magit--shell-command (command &optional directory) + (let ((default-directory (or directory default-directory)) + (process-environment process-environment)) + (push "GIT_PAGER=cat" process-environment) + (magit-start-process shell-file-name nil + shell-command-switch command)) + (magit-process-buffer)) + +(defun magit-read-shell-command (&optional toplevel initial-input) + (let ((dir (abbreviate-file-name + (if (or toplevel current-prefix-arg) + (or (magit-toplevel) + (magit--not-inside-repository-error)) + default-directory)))) + (read-shell-command (if magit-shell-command-verbose-prompt + (format "Async shell command in %s: " dir) + "Async shell command: ") + initial-input 'magit-git-command-history))) + +;;; Font-Lock Keywords + +(defconst magit-font-lock-keywords + (eval-when-compile + `((,(concat "(\\(magit-define-section-jumper\\)\\_>" + "[ \t'\(]*" + "\\(\\(?:\\sw\\|\\s_\\)+\\)?") + (1 'font-lock-keyword-face) + (2 'font-lock-function-name-face nil t)) + (,(concat "(" (regexp-opt '("magit-insert-section" + "magit-section-case" + "magit-bind-match-strings" + "magit-with-temp-index" + "magit-with-blob" + "magit-with-toplevel") t) + "\\_>") + . 1)))) + +(font-lock-add-keywords 'emacs-lisp-mode magit-font-lock-keywords) + +;;; Version + +(defvar magit-version 'undefined + "The version of Magit that you're using. +Use the function by the same name instead of this variable.") + +;;;###autoload +(defun magit-version (&optional print-dest) + "Return the version of Magit currently in use. +If optional argument PRINT-DEST is non-nil, output +stream (interactively, the echo area, or the current buffer with +a prefix argument), also print the used versions of Magit, Git, +and Emacs to it." + (interactive (list (if current-prefix-arg (current-buffer) t))) + (let ((magit-git-global-arguments nil) + (toplib (or load-file-name buffer-file-name)) + debug) + (unless (and toplib + (equal (file-name-nondirectory toplib) "magit.el")) + (setq toplib (locate-library "magit.el"))) + (setq toplib (and toplib (file-chase-links toplib))) + (push toplib debug) + (when toplib + (let* ((topdir (file-name-directory toplib)) + (gitdir (expand-file-name + ".git" (file-name-directory + (directory-file-name topdir)))) + (static (locate-library "magit-version.el" nil (list topdir))) + (static (and static (file-chase-links static)))) + (or (progn + (push 'repo debug) + (when (and (file-exists-p gitdir) + ;; It is a repo, but is it the Magit repo? + (file-exists-p + (expand-file-name "../lisp/magit.el" gitdir))) + (push t debug) + ;; Inside the repo the version file should only exist + ;; while running make. + (when (and static (not noninteractive)) + (ignore-errors (delete-file static))) + (setq magit-version + (let ((default-directory topdir)) + (magit-git-string "describe" "--tags" "--dirty"))))) + (progn + (push 'static debug) + (when (and static (file-exists-p static)) + (push t debug) + (load-file static) + magit-version)) + (when (featurep 'package) + (push 'elpa debug) + (ignore-errors + (--when-let (assq 'magit package-alist) + (push t debug) + (setq magit-version + (and (fboundp 'package-desc-version) + (package-version-join + (package-desc-version (cadr it)))))))) + (progn + (push 'dirname debug) + (let ((dirname (file-name-nondirectory + (directory-file-name topdir)))) + (when (string-match "\\`magit-\\([0-9]\\{8\\}\\.[0-9]*\\)" + dirname) + (setq magit-version (match-string 1 dirname)))))))) + (if (stringp magit-version) + (when print-dest + (princ (format "Magit %s, Git %s, Emacs %s, %s" + (or magit-version "(unknown)") + (or (let ((magit-git-debug + (lambda (err) + (display-warning '(magit git) + err :error)))) + (magit-git-version t)) + "(unknown)") + emacs-version + system-type) + print-dest)) + (setq debug (reverse debug)) + (setq magit-version 'error) + (when magit-version + (push magit-version debug)) + (unless (equal (getenv "TRAVIS") "true") + ;; The repository is a sparse clone. + (message "Cannot determine Magit's version %S" debug))) + magit-version)) + +;;; Debugging Tools + +(defun magit-debug-git-executable () + "Display a buffer with information about `magit-git-executable'. +See info node `(magit)Debugging Tools' for more information." + (interactive) + (with-current-buffer (get-buffer-create "*magit-git-debug*") + (pop-to-buffer (current-buffer)) + (erase-buffer) + (insert (concat + (format "magit-git-executable: %S" magit-git-executable) + (and (not (file-name-absolute-p magit-git-executable)) + (format " [%S]" (executable-find magit-git-executable))) + (format " (%s)\n" + (let* ((errmsg nil) + (magit-git-debug (lambda (err) (setq errmsg err)))) + (or (magit-git-version t) errmsg))))) + (insert (format "exec-path: %S\n" exec-path)) + (--when-let (cl-set-difference + (-filter #'file-exists-p (remq nil (parse-colon-path + (getenv "PATH")))) + (-filter #'file-exists-p (remq nil exec-path)) + :test #'file-equal-p) + (insert (format " entries in PATH, but not in exec-path: %S\n" it))) + (dolist (execdir exec-path) + (insert (format " %s (%s)\n" execdir (car (file-attributes execdir)))) + (when (file-directory-p execdir) + (dolist (exec (directory-files + execdir t (concat + "\\`git" (regexp-opt exec-suffixes) "\\'"))) + (insert (format " %s (%s)\n" exec + (let* ((magit-git-executable exec) + (errmsg nil) + (magit-git-debug (lambda (err) (setq errmsg err)))) + (or (magit-git-version t) errmsg))))))))) + +;;; Startup Asserts + +(defun magit-startup-asserts () + (when-let ((val (getenv "GIT_DIR"))) + (setenv "GIT_DIR") + (message "Magit unset $GIT_DIR (was %S). See \ +https://github.com/magit/magit/wiki/Don't-set-$GIT_DIR-and-alike" val)) + (when-let ((val (getenv "GIT_WORK_TREE"))) + (setenv "GIT_WORK_TREE") + (message "Magit unset $GIT_WORK_TREE (was %S). See \ +https://github.com/magit/magit/wiki/Don't-set-$GIT_DIR-and-alike" val)) + (let ((version (magit-git-version))) + (when (and version + (version< version magit--minimal-git) + (not (equal (getenv "TRAVIS") "true"))) + (display-warning 'magit (format "\ +Magit requires Git >= %s, you are using %s. + +If this comes as a surprise to you, because you do actually have +a newer version installed, then that probably means that the +older version happens to appear earlier on the `$PATH'. If you +always start Emacs from a shell, then that can be fixed in the +shell's init file. If you start Emacs by clicking on an icon, +or using some sort of application launcher, then you probably +have to adjust the environment as seen by graphical interface. +For X11 something like ~/.xinitrc should work. + +If you use Tramp to work inside remote Git repositories, then you +have to make sure a suitable Git is used on the remote machines +too.\n" magit--minimal-git version) :error))) + (when (version< emacs-version magit--minimal-emacs) + (display-warning 'magit (format "\ +Magit requires Emacs >= %s, you are using %s. + +If this comes as a surprise to you, because you do actually have +a newer version installed, then that probably means that the +older version happens to appear earlier on the `$PATH'. If you +always start Emacs from a shell, then that can be fixed in the +shell's init file. If you start Emacs by clicking on an icon, +or using some sort of application launcher, then you probably +have to adjust the environment as seen by graphical interface. +For X11 something like ~/.xinitrc should work.\n" + magit--minimal-emacs emacs-version) + :error))) + +;;; Loading Libraries + +(provide 'magit) + +(cl-eval-when (load eval) + (require 'magit-status) + (require 'magit-refs) + (require 'magit-files) + (require 'magit-reset) + (require 'magit-branch) + (require 'magit-merge) + (require 'magit-tag) + (require 'magit-worktree) + (require 'magit-notes) + (require 'magit-sequence) + (require 'magit-commit) + (require 'magit-remote) + (require 'magit-clone) + (require 'magit-fetch) + (require 'magit-pull) + (require 'magit-push) + (require 'magit-bisect) + (require 'magit-stash) + (require 'magit-blame) + (require 'magit-obsolete) + (require 'magit-submodule) + (unless (load "magit-autoloads" t t) + (require 'magit-patch) + (require 'magit-subtree) + (require 'magit-ediff) + (require 'magit-gitignore) + (require 'magit-extras) + (require 'git-rebase) + (require 'magit-imenu) + (require 'magit-bookmark))) + +(eval-after-load 'bookmark + '(require 'magit-bookmark)) + +(if after-init-time + (progn (magit-startup-asserts) + (magit-version)) + (add-hook 'after-init-hook #'magit-startup-asserts t) + (add-hook 'after-init-hook #'magit-version t)) + +;;; magit.el ends here diff --git a/elpa/magit-20191122.2040/magit.elc b/elpa/magit-20191122.2040/magit.elc new file mode 100644 index 0000000000000000000000000000000000000000..8096f689e44dffa392a1c965b9c54e6b9cfb3942 GIT binary patch literal 20434 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 H?CgI54OOy} literal 0 HcmV?d00001 diff --git a/elpa/magit-20191122.2040/magit.info b/elpa/magit-20191122.2040/magit.info new file mode 100644 index 00000000..cb8b1f46 --- /dev/null +++ b/elpa/magit-20191122.2040/magit.info @@ -0,0 +1,189 @@ +This is magit.info, produced by makeinfo version 6.5 from magit.texi. + + Copyright (C) 2015-2019 Jonas Bernoulli + + You can redistribute this document and/or modify it under the terms + of the GNU General Public License as published by the Free Software + Foundation, either version 3 of the License, or (at your option) + any later version. + + This document is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + +INFO-DIR-SECTION Emacs +START-INFO-DIR-ENTRY +* Magit: (magit). Using Git from Emacs with Magit. +END-INFO-DIR-ENTRY + + +Indirect: +magit.info-1: 754 +magit.info-2: 302345 + +Tag Table: +(Indirect) +Node: Top754 +Node: Introduction6475 +Node: Installation11198 +Node: Installing from Melpa11528 +Node: Installing from the Git Repository12601 +Node: Post-Installation Tasks14949 +Node: Getting Started16234 +Node: Interface Concepts21683 +Node: Modes and Buffers22044 +Node: Switching Buffers23793 +Node: Naming Buffers28563 +Node: Quitting Windows31870 +Node: Automatic Refreshing of Magit Buffers33616 +Node: Automatic Saving of File-Visiting Buffers36468 +Node: Automatic Reverting of File-Visiting Buffers37653 +Node: Risk of Reverting Automatically42648 +Node: Sections45030 +Node: Section Movement45956 +Node: Section Visibility50517 +Node: Section Hooks56594 +Node: Section Types and Values59001 +Node: Section Options60304 +Node: Transient Commands60776 +Node: Transient Arguments and Buffer Variables62013 +Node: Completion Confirmation and the Selection69031 +Node: Action Confirmation69475 +Node: Completion and Confirmation76825 +Node: The Selection80011 +Node: The hunk-internal region82910 +Node: Support for Completion Frameworks83999 +Node: Additional Completion Options88906 +Node: Running Git89505 +Node: Viewing Git Output89778 +Node: Git Process Status90911 +Node: Running Git Manually91876 +Node: Git Executable94346 +Node: Global Git Arguments96628 +Node: Inspecting97434 +Node: Status Buffer98591 +Node: Status Sections102581 +Node: Status Header Sections108133 +Node: Status Module Sections110763 +Node: Status Options113268 +Node: Repository List115143 +Node: Logging118181 +Node: Refreshing Logs120744 +Node: Log Buffer122190 +Node: Log Margin126046 +Node: Select from Log129225 +Node: Reflog131450 +Node: Cherries133107 +Node: Diffing134955 +Node: Refreshing Diffs138036 +Node: Commands Available in Diffs141615 +Node: Diff Options144151 +Node: Revision Buffer149189 +Node: Ediffing152519 +Node: References Buffer156167 +Node: References Sections166687 +Node: Bisecting167548 +Node: Visiting Files and Blobs169361 +Node: General-Purpose Visit Commands169831 +Node: Visiting Files and Blobs from a Diff170787 +Node: Blaming174246 +Node: Manipulating180809 +Node: Creating Repository181151 +Node: Cloning Repository181706 +Node: Staging and Unstaging186949 +Node: Staging from File-Visiting Buffers191032 +Node: Applying192200 +Node: Committing194093 +Node: Initiating a Commit194676 +Node: Editing Commit Messages198061 +Node: Branching208453 +Node: The Two Remotes208679 +Node: Branch Commands211332 +Node: Branch Git Variables223716 +Node: Auxiliary Branch Commands229107 +Node: Merging230225 +Node: Resolving Conflicts234233 +Node: Rebasing239234 +Node: Editing Rebase Sequences244244 +Node: Information About In-Progress Rebase248572 +Ref: Information About In-Progress Rebase-Footnote-1257454 +Node: Cherry Picking258050 +Node: Reverting262381 +Node: Resetting263830 +Node: Stashing265484 +Node: Transferring270185 +Node: Remotes270407 +Node: Remote Commands270559 +Node: Remote Git Variables274640 +Node: Fetching277019 +Node: Pulling279373 +Node: Pushing280566 +Node: Plain Patches284174 +Node: Maildir Patches285665 +Node: Miscellaneous287179 +Node: Tagging287495 +Node: Notes289423 +Node: Submodules291795 +Node: Listing Submodules292013 +Node: Submodule Transient293941 +Node: Subtree296463 +Node: Worktree298439 +Node: Common Commands299544 +Node: Wip Modes302345 +Node: Wip Graph307278 +Node: Legacy Wip Modes309592 +Node: Minor Mode for Buffers Visiting Files312487 +Node: Minor Mode for Buffers Visiting Blobs319588 +Node: Customizing320401 +Node: Per-Repository Configuration321997 +Node: Essential Settings323646 +Node: Safety323970 +Node: Performance325735 +Node: Microsoft Windows Performance332452 +Node: MacOS Performance333643 +Ref: MacOS Performance-Footnote-1334348 +Node: Plumbing334430 +Node: Calling Git335259 +Node: Getting a Value from Git336784 +Node: Calling Git for Effect339870 +Node: Section Plumbing346390 +Node: Creating Sections346618 +Node: Section Selection350518 +Node: Matching Sections352317 +Node: Refreshing Buffers358290 +Node: Conventions361438 +Node: Theming Faces361630 +Node: FAQ369745 +Node: FAQ - How to ...?370187 +Node: How to show git's output?370547 +Node: How to install the gitman info manual?371301 +Node: How to show diffs for gpg-encrypted files?372271 +Node: How does branching and pushing work?372867 +Node: Can Magit be used as ediff-version-control-package?373230 +Node: FAQ - Issues and Errors375219 +Node: Magit is slow376151 +Node: I changed several thousand files at once and now Magit is unusable376365 +Node: I am having problems committing377094 +Node: I am using MS Windows and cannot push with Magit377575 +Node: I am using OS X and SOMETHING works in shell but not in Magit378192 +Node: Diffs contain control sequences378998 +Node: Expanding a file to show the diff causes it to disappear380111 +Node: Point is wrong in the COMMIT_EDITMSG buffer380662 +Node: The mode-line information isn't always up-to-date381708 +Node: A branch and tag sharing the same name breaks SOMETHING382790 +Node: My Git hooks work on the command-line but not inside Magit383678 +Node: git-commit-mode isn't used when committing from the command-line384524 +Node: Point ends up inside invisible text when jumping to a file-visiting buffer386791 +Node: Debugging Tools387589 +Node: Keystroke Index389476 +Node: Command Index423263 +Node: Function Index460091 +Node: Variable Index476310 + +End Tag Table + + +Local Variables: +coding: utf-8 +End: diff --git a/elpa/magit-20191122.2040/magit.info-1 b/elpa/magit-20191122.2040/magit.info-1 new file mode 100644 index 00000000..9ffb9ba0 --- /dev/null +++ b/elpa/magit-20191122.2040/magit.info-1 @@ -0,0 +1,7784 @@ +This is magit.info, produced by makeinfo version 6.5 from magit.texi. + + Copyright (C) 2015-2019 Jonas Bernoulli + + You can redistribute this document and/or modify it under the terms + of the GNU General Public License as published by the Free Software + Foundation, either version 3 of the License, or (at your option) + any later version. + + This document is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + +INFO-DIR-SECTION Emacs +START-INFO-DIR-ENTRY +* Magit: (magit). Using Git from Emacs with Magit. +END-INFO-DIR-ENTRY + + +File: magit.info, Node: Top, Next: Introduction, Up: (dir) + +Magit User Manual +***************** + +Magit is an interface to the version control system Git, implemented as +an Emacs package. Magit aspires to be a complete Git porcelain. While +we cannot (yet) claim that Magit wraps and improves upon each and every +Git command, it is complete enough to allow even experienced Git users +to perform almost all of their daily version control tasks directly from +within Emacs. While many fine Git clients exist, only Magit and Git +itself deserve to be called porcelains. + +This manual is for Magit version 2.90.1 (v2.90.1-810-g8c4e8ed74+1). + + Copyright (C) 2015-2019 Jonas Bernoulli + + You can redistribute this document and/or modify it under the terms + of the GNU General Public License as published by the Free Software + Foundation, either version 3 of the License, or (at your option) + any later version. + + This document is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + +* Menu: + +* Introduction:: +* Installation:: +* Getting Started:: +* Interface Concepts:: +* Inspecting:: +* Manipulating:: +* Transferring:: +* Miscellaneous:: +* Customizing:: +* Plumbing:: +* FAQ:: +* Debugging Tools:: +* Keystroke Index:: +* Command Index:: +* Function Index:: +* Variable Index:: + +— The Detailed Node Listing — + +Installation + +* Installing from Melpa:: +* Installing from the Git Repository:: +* Post-Installation Tasks:: + +Interface Concepts + +* Modes and Buffers:: +* Sections:: +* Transient Commands:: +* Transient Arguments and Buffer Variables:: +* Completion, Confirmation and the Selection: Completion Confirmation and the Selection. +* Running Git:: + +Modes and Buffers + +* Switching Buffers:: +* Naming Buffers:: +* Quitting Windows:: +* Automatic Refreshing of Magit Buffers:: +* Automatic Saving of File-Visiting Buffers:: +* Automatic Reverting of File-Visiting Buffers:: + + +Sections + +* Section Movement:: +* Section Visibility:: +* Section Hooks:: +* Section Types and Values:: +* Section Options:: + + +Completion, Confirmation and the Selection + +* Action Confirmation:: +* Completion and Confirmation:: +* The Selection:: +* The hunk-internal region:: +* Support for Completion Frameworks:: +* Additional Completion Options:: + + +Running Git + +* Viewing Git Output:: +* Git Process Status:: +* Running Git Manually:: +* Git Executable:: +* Global Git Arguments:: + + +Inspecting + +* Status Buffer:: +* Repository List:: +* Logging:: +* Diffing:: +* Ediffing:: +* References Buffer:: +* Bisecting:: +* Visiting Files and Blobs:: +* Blaming:: + +Status Buffer + +* Status Sections:: +* Status Header Sections:: +* Status Module Sections:: +* Status Options:: + + +Logging + +* Refreshing Logs:: +* Log Buffer:: +* Log Margin:: +* Select from Log:: +* Reflog:: +* Cherries:: + + +Diffing + +* Refreshing Diffs:: +* Commands Available in Diffs:: +* Diff Options:: +* Revision Buffer:: + + +References Buffer + +* References Sections:: + + +Visiting Files and Blobs + +* General-Purpose Visit Commands:: +* Visiting Files and Blobs from a Diff:: + + +Manipulating + +* Creating Repository:: +* Cloning Repository:: +* Staging and Unstaging:: +* Applying:: +* Committing:: +* Branching:: +* Merging:: +* Resolving Conflicts:: +* Rebasing:: +* Cherry Picking:: +* Resetting:: +* Stashing:: + +Staging and Unstaging + +* Staging from File-Visiting Buffers:: + + +Committing + +* Initiating a Commit:: +* Editing Commit Messages:: + + +Branching + +* The Two Remotes:: +* Branch Commands:: +* Branch Git Variables:: +* Auxiliary Branch Commands:: + + +Rebasing + +* Editing Rebase Sequences:: +* Information About In-Progress Rebase:: + + +Cherry Picking + +* Reverting:: + + +Transferring + +* Remotes:: +* Fetching:: +* Pulling:: +* Pushing:: +* Plain Patches:: +* Maildir Patches:: + +Remotes + +* Remote Commands:: +* Remote Git Variables:: + + +Miscellaneous + +* Tagging:: +* Notes:: +* Submodules:: +* Subtree:: +* Worktree:: +* Common Commands:: +* Wip Modes:: +* Minor Mode for Buffers Visiting Files:: +* Minor Mode for Buffers Visiting Blobs:: + +Submodules + +* Listing Submodules:: +* Submodule Transient:: + + +Wip Modes + +* Wip Graph:: +* Legacy Wip Modes:: + + +Customizing + +* Per-Repository Configuration:: +* Essential Settings:: + +Essential Settings + +* Safety:: +* Performance:: + + +Plumbing + +* Calling Git:: +* Section Plumbing:: +* Refreshing Buffers:: +* Conventions:: + +Calling Git + +* Getting a Value from Git:: +* Calling Git for Effect:: + + +Section Plumbing + +* Creating Sections:: +* Section Selection:: +* Matching Sections:: + + +Conventions + +* Theming Faces:: + + +FAQ + +* FAQ - How to ...?:: +* FAQ - Issues and Errors:: + +FAQ - How to ...? + +* How to show git's output?:: +* How to install the gitman info manual?:: +* How to show diffs for gpg-encrypted files?:: +* How does branching and pushing work?:: +* Can Magit be used as ediff-version-control-package?:: + + +FAQ - Issues and Errors + +* Magit is slow:: +* I changed several thousand files at once and now Magit is unusable:: +* I am having problems committing:: +* I am using MS Windows and cannot push with Magit:: +* I am using OS X and SOMETHING works in shell, but not in Magit: I am using OS X and SOMETHING works in shell but not in Magit. +* Diffs contain control sequences:: +* Expanding a file to show the diff causes it to disappear:: +* Point is wrong in the COMMIT_EDITMSG buffer:: +* The mode-line information isn't always up-to-date:: +* A branch and tag sharing the same name breaks SOMETHING:: +* My Git hooks work on the command-line but not inside Magit:: +* git-commit-mode isn't used when committing from the command-line:: +* Point ends up inside invisible text when jumping to a file-visiting buffer:: + + + + +File: magit.info, Node: Introduction, Next: Installation, Prev: Top, Up: Top + +1 Introduction +************** + +Magit is an interface to the version control system Git, implemented as +an Emacs package. Magit aspires to be a complete Git porcelain. While +we cannot (yet) claim that Magit wraps and improves upon each and every +Git command, it is complete enough to allow even experienced Git users +to perform almost all of their daily version control tasks directly from +within Emacs. While many fine Git clients exist, only Magit and Git +itself deserve to be called porcelains. + + Staging and otherwise applying changes is one of the most important +features in a Git porcelain and here Magit outshines anything else, +including Git itself. Git’s own staging interface (‘git add --patch’) +is so cumbersome that many users only use it in exceptional cases. In +Magit staging a hunk or even just part of a hunk is as trivial as +staging all changes made to a file. + + The most visible part of Magit’s interface is the status buffer, +which displays information about the current repository. Its content is +created by running several Git commands and making their output +actionable. Among other things, it displays information about the +current branch, lists unpulled and unpushed changes and contains +sections displaying the staged and unstaged changes. That might sound +noisy, but, since sections are collapsible, it’s not. + + To stage or unstage a change one places the cursor on the change and +then types ‘s’ or ‘u’. The change can be a file or a hunk, or when the +region is active (i.e. when there is a selection) several files or +hunks, or even just part of a hunk. The change or changes that these +commands - and many others - would act on are highlighted. + + Magit also implements several other "apply variants" in addition to +staging and unstaging. One can discard or reverse a change, or apply it +to the working tree. Git’s own porcelain only supports this for staging +and unstaging and you would have to do something like ‘git diff ... | +??? | git apply ...’ to discard, revert, or apply a single hunk on the +command line. In fact that’s exactly what Magit does internally (which +is what lead to the term "apply variants"). + + Magit isn’t just for Git experts, but it does assume some prior +experience with Git as well as Emacs. That being said, many users have +reported that using Magit was what finally taught them what Git is +capable of and how to use it to its fullest. Other users wished they +had switched to Emacs sooner so that they would have gotten their hands +on Magit earlier. + + While one has to know the basic features of Emacs to be able to make +full use of Magit, acquiring just enough Emacs skills doesn’t take long +and is worth it, even for users who prefer other editors. Vim users are +advised to give Evil (https://bitbucket.org/lyro/evil/wiki/Home), the +"Extensible VI Layer for Emacs", and Spacemacs +(https://github.com/syl20bnr/spacemacs), an "Emacs starter-kit focused +on Evil" a try. + + Magit provides a consistent and efficient Git porcelain. After a +short learning period, you will be able to perform most of your daily +version control tasks faster than you would on the command line. You +will likely also start using features that seemed too daunting in the +past. + + Magit fully embraces Git. It exposes many advanced features using a +simple but flexible interface instead of only wrapping the trivial ones +like many GUI clients do. Of course Magit supports logging, cloning, +pushing, and other commands that usually don’t fail in spectacular ways; +but it also supports tasks that often cannot be completed in a single +step. Magit fully supports tasks such as merging, rebasing, +cherry-picking, reverting, and blaming by not only providing a command +to initiate these tasks but also by displaying context sensitive +information along the way and providing commands that are useful for +resolving conflicts and resuming the sequence after doing so. + + Magit wraps and in many cases improves upon at least the following +Git porcelain commands: ‘add’, ‘am’, ‘bisect’, ‘blame’, ‘branch’, +‘checkout’, ‘cherry’, ‘cherry-pick’, ‘clean’, ‘clone’, ‘commit’, +‘config’, ‘describe’, ‘diff’, ‘fetch’, ‘format-patch’, ‘init’, ‘log’, +‘merge’, ‘merge-tree’, ‘mv’, ‘notes’, ‘pull’, ‘rebase’, ‘reflog’, +‘remote’, ‘request-pull’, ‘reset’, ‘revert’, ‘rm’, ‘show’, ‘stash’, +‘submodule’, ‘subtree’, ‘tag’, and ‘worktree.’ Many more Magit porcelain +commands are implemented on top of Git plumbing commands. + + +File: magit.info, Node: Installation, Next: Getting Started, Prev: Introduction, Up: Top + +2 Installation +************** + +Magit can be installed using Emacs’ package manager or manually from its +development repository. + +* Menu: + +* Installing from Melpa:: +* Installing from the Git Repository:: +* Post-Installation Tasks:: + + +File: magit.info, Node: Installing from Melpa, Next: Installing from the Git Repository, Up: Installation + +2.1 Installing from Melpa +========================= + +Magit is available from Melpa and Melpa-Stable. If you haven’t used +Emacs’ package manager before, then it is high time you familiarize +yourself with it by reading the documentation in the Emacs manual, see +*note (emacs)Packages::. Then add one of the archives to +‘package-archives’: + + • To use Melpa: + + (require 'package) + (add-to-list 'package-archives + '("melpa" . "http://melpa.org/packages/") t) + + • To use Melpa-Stable: + + (require 'package) + (add-to-list 'package-archives + '("melpa-stable" . "http://stable.melpa.org/packages/") t) + + Once you have added your preferred archive, you need to update the +local package list using: + + M-x package-refresh-contents RET + + Once you have done that, you can install Magit and its dependencies +using: + + M-x package-install RET magit RET + + Now see *note Post-Installation Tasks::. + + +File: magit.info, Node: Installing from the Git Repository, Next: Post-Installation Tasks, Prev: Installing from Melpa, Up: Installation + +2.2 Installing from the Git Repository +====================================== + +Magit depends on the ‘dash’, ‘transient’ and ‘with-editor’ libraries +which are available from Melpa and Melpa-Stable. Install them using +‘M-x package-install RET RET’. Of course you may also install +them manually from their repository. + + Then clone the Magit repository: + + $ git clone https://github.com/magit/magit.git ~/.emacs.d/site-lisp/magit + $ cd ~/.emacs.d/site-lisp/magit + + Then compile the libraries and generate the info manuals: + + $ make + + If you haven’t installed ‘dash’, ‘transient’ and ‘with-editor’ from +Melpa or at ‘/path/to/magit/../’, then you have to tell ‘make’ +where to find them. To do so create the file ‘/path/to/magit/config.mk’ +with the following content before running ‘make’: + + LOAD_PATH = -L /path/to/magit/lisp + LOAD_PATH += -L /path/to/dash + LOAD_PATH += -L /path/to/transient + LOAD_PATH += -L /path/to/with-editor + + Finally add this to your init file: + + (add-to-list 'load-path "~/.emacs.d/site-lisp/magit/lisp") + (require 'magit) + + (with-eval-after-load 'info + (info-initialize) + (add-to-list 'Info-directory-list + "~/.emacs.d/site-lisp/magit/Documentation/")) + + Note that you have to add the ‘lisp’ subdirectory to the ‘load-path’, +not the top-level of the repository, and that elements of ‘load-path’ +should not end with a slash, while those of ‘Info-directory-list’ +should. + + Instead of requiring the feature ‘magit’, you could load just the +autoload definitions, by loading the file ‘magit-autoloads.el’. + + (load "/path/to/magit/lisp/magit-autoloads") + + Instead of running Magit directly from the repository by adding that +to the ‘load-path’, you might want to instead install it in some other +directory using ‘sudo make install’ and setting ‘load-path’ accordingly. + + To update Magit use: + + $ git pull + $ make + + At times it might be necessary to run ‘make clean all’ instead. + + To view all available targets use ‘make help’. + + Now see *note Post-Installation Tasks::. + + +File: magit.info, Node: Post-Installation Tasks, Prev: Installing from the Git Repository, Up: Installation + +2.3 Post-Installation Tasks +=========================== + +After installing Magit you should verify that you are indeed using the +Magit, Git, and Emacs releases you think you are using. It’s best to +restart Emacs before doing so, to make sure you are not using an +outdated value for ‘load-path’. + + M-x magit-version RET + + should display something like + + Magit 2.8.0, Git 2.10.2, Emacs 25.1.1, gnu/linux + + Then you might also want to read about options that many users likely +want to customize. See *note Essential Settings::. + + To be able to follow cross references to Git manpages found in this +manual, you might also have to manually install the ‘gitman’ info +manual, or advice ‘Info-follow-nearest-node’ to instead open the actual +manpage. See *note How to install the gitman info manual?::. + + If you are completely new to Magit then see *note Getting Started::. + + If you run into problems, then please see the *note FAQ::. Also see +the *note Debugging Tools::. + + And last but not least please consider making a donation, to ensure +that I can keep working on Magit. See . +for various donation options. + + +File: magit.info, Node: Getting Started, Next: Interface Concepts, Prev: Installation, Up: Top + +3 Getting Started +***************** + +This short tutorial describes the most essential features that many +Magitians use on a daily basis. It only scratches the surface but +should be enough to get you started. + + IMPORTANT: It is safest if you clone some repository just for this +tutorial. Alternatively you can use an existing local repository, but +if you do that, then you should commit all uncommitted changes before +proceeding. + + To display information about the current Git repository, type ‘M-x +magit-status RET’. You will be using this command a lot, and should +therefore give it a global key binding. This is what we recommend: + + (global-set-key (kbd "C-x g") 'magit-status) + + Most Magit commands are commonly invoked from the status buffer. It +can be considered the primary interface for interacting with Git using +Magit. Many other Magit buffers may exist at a given time, but they are +often created from this buffer. + + Depending on what state your repository is in, this buffer may +contain sections titled "Staged changes", "Unstaged changes", "Unmerged +into origin/master", "Unpushed to origin/master", and many others. + + Since we are starting from a safe state, which you can easily return +to (by doing a ‘git reset --hard PRE-MAGIT-STATE’), there currently are +no staged or unstaged changes. Edit some files and save the changes. +Then go back to the status buffer, while at the same time refreshing it, +by typing ‘C-x g’. (When the status buffer, or any Magit buffer for +that matter, is the current buffer, then you can also use just ‘g’ to +refresh it). + + Move between sections using ‘p’ and ‘n’. Note that the bodies of +some sections are hidden. Type ‘TAB’ to expand or collapse the section +at point. You can also use ‘C-tab’ to cycle the visibility of the +current section and its children. Move to a file section inside the +section named "Unstaged changes" and type ‘s’ to stage the changes you +have made to that file. That file now appears under "Staged changes". + + Magit can stage and unstage individual hunks, not just complete +files. Move to the file you have just staged, expand it using ‘TAB’, +move to one of the hunks using ‘n’, and unstage just that by typing ‘u’. +Note how the staging (‘s’) and unstaging (‘u’) commands operate on the +change at point. Many other commands behave the same way. + + You can also un-/stage just part of a hunk. Inside the body of a +hunk section (move there using ‘C-n’), set the mark using ‘C-SPC’ and +move down until some added and/or removed lines fall inside the region +but not all of them. Again type ‘s’ to stage. + + It is also possible to un-/stage multiple files at once. Move to a +file section, type ‘C-SPC’, move to the next file using ‘n’, and then +‘s’ to stage both files. Note that both the mark and point have to be +on the headings of sibling sections for this to work. If the region +looks like it does in other buffers, then it doesn’t select Magit +sections that can be acted on as a unit. + + And then of course you want to commit your changes. Type ‘c’. This +shows the available commit commands and arguments in a buffer at the +bottom of the frame. Each command and argument is prefixed with the key +that invokes/sets it. Do not worry about this for now. We want to +create a "normal" commit, which is done by typing ‘c’ again. + + Now two new buffers appear. One is for writing the commit message, +the other shows a diff with the changes that you are about to committed. +Write a message and then type ‘C-c C-c’ to actually create the commit. + + You probably don’t want to push the commit you just created because +you just committed some random changes, but if that is not the case you +could push it by typing ‘P’ to show all the available push commands and +arguments and then ‘p’ to push to a branch with the same name as the +local branch onto the remote configured as the push-remote. (If the +push-remote is not configured yet, then you would first be prompted for +the remote to push to.) + + So far we have mentioned the commit, push, and log transient prefix +commands. These are probably among the transients you will be using the +most, but many others exist. To show a transient that lists all other +transients (as well as the various apply commands and some other +essential commands), type ‘h’. Try a few. + + The key bindings in that transient correspond to the bindings in +Magit buffers, including but not limited to the status buffer. So you +could type ‘h d’ to bring up the diff transient, but once you remember +that "d" stands for "diff", you would usually do so by just typing ‘d’. +But this "prefix of prefixes" is useful even once you have memorized all +the bindings, as it can provide easy access to Magit commands from +non-Magit buffers. You should create a global key binding for this +command too: + + (global-set-key (kbd "C-x M-g") 'magit-dispatch) + + In the same vein, you might also want to enable +‘global-magit-file-mode’ to get some more Magit key bindings in regular +file-visiting buffers (see *note Minor Mode for Buffers Visiting +Files::). + + It is not necessary that you do so now, but if you stick with Magit, +then it is highly recommended that you read the next section too. + + +File: magit.info, Node: Interface Concepts, Next: Inspecting, Prev: Getting Started, Up: Top + +4 Interface Concepts +******************** + +* Menu: + +* Modes and Buffers:: +* Sections:: +* Transient Commands:: +* Transient Arguments and Buffer Variables:: +* Completion, Confirmation and the Selection: Completion Confirmation and the Selection. +* Running Git:: + + +File: magit.info, Node: Modes and Buffers, Next: Sections, Up: Interface Concepts + +4.1 Modes and Buffers +===================== + +Magit provides several major-modes. For each of these modes there +usually exists only one buffer per repository. Separate modes and thus +buffers exist for commits, diffs, logs, and some other things. + + Besides these special purpose buffers, there also exists an overview +buffer, called the *status buffer*. It’s usually from this buffer that +the user invokes Git commands, or creates or visits other buffers. + + In this manual we often speak about "Magit buffers". By that we mean +buffers whose major-modes derive from ‘magit-mode’. + +‘M-x magit-toggle-buffer-lock’ (‘magit-toggle-buffer-lock’) + + This command locks the current buffer to its value or if the buffer + is already locked, then it unlocks it. + + Locking a buffer to its value prevents it from being reused to + display another value. The name of a locked buffer contains its + value, which allows telling it apart from other locked buffers and + the unlocked buffer. + + Not all Magit buffers can be locked to their values; for example, + it wouldn’t make sense to lock a status buffer. + + There can only be a single unlocked buffer using a certain + major-mode per repository. So when a buffer is being unlocked and + another unlocked buffer already exists for that mode and + repository, then the former buffer is instead deleted and the + latter is displayed in its place. + +* Menu: + +* Switching Buffers:: +* Naming Buffers:: +* Quitting Windows:: +* Automatic Refreshing of Magit Buffers:: +* Automatic Saving of File-Visiting Buffers:: +* Automatic Reverting of File-Visiting Buffers:: + + +File: magit.info, Node: Switching Buffers, Next: Naming Buffers, Up: Modes and Buffers + +4.1.1 Switching Buffers +----------------------- + + -- Function: magit-display-buffer buffer &optional display-function + + This function is a wrapper around ‘display-buffer’ and is used to + display any Magit buffer. It displays BUFFER in some window and, + unlike ‘display-buffer’, also selects that window, provided + ‘magit-display-buffer-noselect’ is ‘nil’. It also runs the hooks + mentioned below. + + If optional DISPLAY-FUNCTION is non-nil, then that is used to + display the buffer. Usually that is ‘nil’ and the function + specified by ‘magit-display-buffer-function’ is used. + + -- Variable: magit-display-buffer-noselect + + When this is non-nil, then ‘magit-display-buffer’ only displays the + buffer but forgoes also selecting the window. This variable should + not be set globally, it is only intended to be let-bound, by code + that automatically updates "the other window". This is used for + example when the revision buffer is updated when you move inside + the log buffer. + + -- User Option: magit-display-buffer-function + + The function specified here is called by ‘magit-display-buffer’ + with one argument, a buffer, to actually display that buffer. This + function should call ‘display-buffer’ with that buffer as first and + a list of display actions as second argument. + + Magit provides several functions, listed below, that are suitable + values for this option. If you want to use different rules, then a + good way of doing that is to start with a copy of one of these + functions and then adjust it to your needs. + + Instead of using a wrapper around ‘display-buffer’, that function + itself can be used here, in which case the display actions have to + be specified by adding them to ‘display-buffer-alist’ instead. + + To learn about display actions, see *note (elisp)Choosing a Window + for Display::. + + -- Function: magit-display-buffer-traditional buffer + + This function is the current default value of the option + ‘magit-display-buffer-function’. Before that option and this + function were added, the behavior was hard-coded in many places all + over the code base but now all the rules are contained in this one + function (except for the "noselect" special case mentioned above). + + -- Function: magit-display-buffer-same-window-except-diff-v1 + + This function displays most buffers in the currently selected + window. If a buffer’s mode derives from ‘magit-diff-mode’ or + ‘magit-process-mode’, it is displayed in another window. + + -- Function: magit-display-buffer-fullframe-status-v1 + + This function fills the entire frame when displaying a status + buffer. Otherwise, it behaves like + ‘magit-display-buffer-traditional’. + + -- Function: magit-display-buffer-fullframe-status-topleft-v1 + + This function fills the entire frame when displaying a status + buffer. It behaves like ‘magit-display-buffer-fullframe-status-v1’ + except that it displays buffers that derive from ‘magit-diff-mode’ + or ‘magit-process-mode’ to the top or left of the current buffer + rather than to the bottom or right. As a result, Magit buffers + tend to pop up on the same side as they would if + ‘magit-display-buffer-traditional’ were in use. + + -- Function: magit-display-buffer-fullcolumn-most-v1 + + This function displays most buffers so that they fill the entire + height of the frame. However, the buffer is displayed in another + window if (1) the buffer’s mode derives from ‘magit-process-mode’, + or (2) the buffer’s mode derives from ‘magit-diff-mode’, provided + that the mode of the current buffer derives from ‘magit-log-mode’ + or ‘magit-cherry-mode’. + + -- User Option: magit-pre-display-buffer-hook + + This hook is run by ‘magit-display-buffer’ before displaying the + buffer. + + -- Function: magit-save-window-configuration + + This function saves the current window configuration. Later when + the buffer is buried, it may be restored by + ‘magit-restore-window-configuration’. + + -- User Option: magit-post-display-buffer-hook + + This hook is run by ‘magit-display-buffer’ after displaying the + buffer. + + -- Function: magit-maybe-set-dedicated + + This function remembers if a new window had to be created to + display the buffer, or whether an existing window was reused. This + information is later used by ‘magit-mode-quit-window’, to determine + whether the window should be deleted when its last Magit buffer is + buried. + + +File: magit.info, Node: Naming Buffers, Next: Quitting Windows, Prev: Switching Buffers, Up: Modes and Buffers + +4.1.2 Naming Buffers +-------------------- + + -- User Option: magit-generate-buffer-name-function + + The function used to generate the names of Magit buffers. + + Such a function should take the options + ‘magit-uniquify-buffer-names’ as well as ‘magit-buffer-name-format’ + into account. If it doesn’t, then should be clearly stated in the + doc-string. And if it supports %-sequences beyond those mentioned + in the doc-string of the option ‘magit-buffer-name-format’, then + its own doc-string should describe the additions. + + -- Function: magit-generate-buffer-name-default-function mode + + This function returns a buffer name suitable for a buffer whose + major-mode is MODE and which shows information about the repository + in which ‘default-directory’ is located. + + This function uses ‘magit-buffer-name-format’ and supporting all of + the %-sequences mentioned the documentation of that option. It + also respects the option ‘magit-uniquify-buffer-names’. + + -- User Option: magit-buffer-name-format + + The format string used to name Magit buffers. + + At least the following %-sequences are supported: + + • ‘%m’ + + The name of the major-mode, but with the ‘-mode’ suffix + removed. + + • ‘%M’ + + Like ‘%m’ but abbreviate ‘magit-status-mode’ as ‘magit’. + + • ‘%v’ + + The value the buffer is locked to, in parentheses, or an empty + string if the buffer is not locked to a value. + + • ‘%V’ + + Like ‘%v’, but the string is prefixed with a space, unless it + is an empty string. + + • ‘%t’ + + The top-level directory of the working tree of the repository, + or if ‘magit-uniquify-buffer-names’ is non-nil an abbreviation + of that. + + • ‘%x’ + + If ‘magit-uniquify-buffer-names’ is nil "*", otherwise the + empty string. Due to limitations of the ‘uniquify’ package, + buffer names must end with the path. + + • ‘%T’ + + Obsolete, use "%t%x" instead. Like ‘%t’, but append an + asterisk if and only if ‘magit-uniquify-buffer-names’ is nil. + + The value should always contain ‘%m’ or ‘%M’, ‘%v’ or ‘%V’, and + ‘%t’ (or the obsolete ‘%T’). If ‘magit-uniquify-buffer-names’ is + non-nil, then the value must end with ‘%t’ or ‘%t%x’ (or the + obsolete ‘%T’). See issue #2841. + + -- User Option: magit-uniquify-buffer-names + + This option controls whether the names of Magit buffers are + uniquified. If the names are not being uniquified, then they + contain the full path of the top-level of the working tree of the + corresponding repository. If they are being uniquified, then they + end with the basename of the top-level, or if that would conflict + with the name used for other buffers, then the names of all these + buffers are adjusted until they no longer conflict. + + This is done using the ‘uniquify’ package; customize its options to + control how buffer names are uniquified. + + +File: magit.info, Node: Quitting Windows, Next: Automatic Refreshing of Magit Buffers, Prev: Naming Buffers, Up: Modes and Buffers + +4.1.3 Quitting Windows +---------------------- + +‘q’ (‘magit-mode-bury-buffer’) + + This command buries the current Magit buffer. + + With a prefix argument, it instead kills the buffer. With a double + prefix argument, also kills all other Magit buffers associated with + the current project. + + -- User Option: magit-bury-buffer-function + + The function used to actually bury or kill the current buffer. + + ‘magit-mode-bury-buffer’ calls this function with one argument. If + the argument is non-nil, then the function has to kill the current + buffer. Otherwise it has to bury it alive. The default value + currently is ‘magit-restore-window-configuration’. + + -- Function: magit-restore-window-configuration kill-buffer + + Bury or kill the current buffer using ‘quit-window’, which is + called with KILL-BUFFER as first and the selected window as second + argument. + + Then restore the window configuration that existed right before the + current buffer was displayed in the selected frame. Unfortunately + that also means that point gets adjusted in all the buffers, which + are being displayed in the selected frame. + + -- Function: magit-mode-quit-window kill-buffer + + Bury or kill the current buffer using ‘quit-window’, which is + called with KILL-BUFFER as first and the selected window as second + argument. + + Then, if the window was originally created to display a Magit + buffer and the buried buffer was the last remaining Magit buffer + that was ever displayed in the window, then that is deleted. + + +File: magit.info, Node: Automatic Refreshing of Magit Buffers, Next: Automatic Saving of File-Visiting Buffers, Prev: Quitting Windows, Up: Modes and Buffers + +4.1.4 Automatic Refreshing of Magit Buffers +------------------------------------------- + +After running a command which may change the state of the current +repository, the current Magit buffer and the corresponding status buffer +are refreshed. The status buffer can be automatically refreshed +whenever a buffer is saved to a file inside the respective repository by +adding a hook, like so: + + (add-hook 'after-save-hook 'magit-after-save-refresh-status t) + + Automatically refreshing Magit buffers ensures that the displayed +information is up-to-date most of the time but can lead to a noticeable +delay in big repositories. Other Magit buffers are not refreshed to +keep the delay to a minimum and also because doing so can sometimes be +undesirable. + + Buffers can also be refreshed explicitly, which is useful in buffers +that weren’t current during the last refresh and after changes were made +to the repository outside of Magit. + +‘g’ (‘magit-refresh’) + + This command refreshes the current buffer if its major mode derives + from ‘magit-mode’ as well as the corresponding status buffer. + + If the option ‘magit-revert-buffers’ calls for it, then it also + reverts all unmodified buffers that visit files being tracked in + the current repository. + +‘G’ (‘magit-refresh-all’) + + This command refreshes all Magit buffers belonging to the current + repository and also reverts all unmodified buffers that visit files + being tracked in the current repository. + + The file-visiting buffers are always reverted, even if + ‘magit-revert-buffers’ is nil. + + -- User Option: magit-refresh-buffer-hook + + This hook is run in each Magit buffer that was refreshed during the + current refresh - normally the current buffer and the status + buffer. + + -- User Option: magit-refresh-status-buffer + + When this option is non-nil, then the status buffer is + automatically refreshed after running git for side-effects, in + addition to the current Magit buffer, which is always refreshed + automatically. + + Only set this to nil after exhausting all other options to improve + performance. + + -- Function: magit-after-save-refresh-status + + This function is intended to be added to ‘after-save-hook’. After + doing that the corresponding status buffer is refreshed whenever a + buffer is saved to a file inside a repository. + + Note that refreshing a Magit buffer is done by re-creating its + contents from scratch, which can be slow in large repositories. If + you are not satisfied with Magit’s performance, then you should + obviously not add this function to that hook. + + +File: magit.info, Node: Automatic Saving of File-Visiting Buffers, Next: Automatic Reverting of File-Visiting Buffers, Prev: Automatic Refreshing of Magit Buffers, Up: Modes and Buffers + +4.1.5 Automatic Saving of File-Visiting Buffers +----------------------------------------------- + +File-visiting buffers are by default saved at certain points in time. +This doesn’t guarantee that Magit buffers are always up-to-date, but, +provided one only edits files by editing them in Emacs and uses only +Magit to interact with Git, one can be fairly confident. When in doubt +or after outside changes, type ‘g’ (‘magit-refresh’) to save and refresh +explicitly. + + -- User Option: magit-save-repository-buffers + + This option controls whether file-visiting buffers are saved before + certain events. + + If this is non-nil then all modified file-visiting buffers + belonging to the current repository may be saved before running + commands, before creating new Magit buffers, and before explicitly + refreshing such buffers. If this is ‘dontask’ then this is done + without user intervention. If it is ‘t’ then the user has to + confirm each save. + + +File: magit.info, Node: Automatic Reverting of File-Visiting Buffers, Prev: Automatic Saving of File-Visiting Buffers, Up: Modes and Buffers + +4.1.6 Automatic Reverting of File-Visiting Buffers +-------------------------------------------------- + +By default Magit automatically reverts buffers that are visiting files +that are being tracked in a Git repository, after they have changed on +disk. When using Magit one often changes files on disk by running Git, +i.e. "outside Emacs", making this a rather important feature. + + For example, if you discard a change in the status buffer, then that +is done by running ‘git apply --reverse ...’, and Emacs considers the +file to have "changed on disk". If Magit did not automatically revert +the buffer, then you would have to type ‘M-x revert-buffer RET RET’ in +the visiting buffer before you could continue making changes. + + -- User Option: magit-auto-revert-mode + + When this mode is enabled, then buffers that visit tracked files + are automatically reverted after the visited files change on disk. + + -- User Option: global-auto-revert-mode + + When this mode is enabled, then any file-visiting buffer is + automatically reverted after the visited file changes on disk. + + If you like buffers that visit tracked files to be automatically + reverted, then you might also like any buffer to be reverted, not + just those visiting tracked files. If that is the case, then + enable this mode _instead of_ ‘magit-auto-revert-mode’. + + -- User Option: magit-auto-revert-immediately + + This option controls whether Magit reverts buffers immediately. + + If this is non-nil and either ‘global-auto-revert-mode’ or + ‘magit-auto-revert-mode’ is enabled, then Magit immediately reverts + buffers by explicitly calling ‘auto-revert-buffers’ after running + Git for side-effects. + + If ‘auto-revert-use-notify’ is non-nil (and file notifications are + actually supported), then ‘magit-auto-revert-immediately’ does not + have to be non-nil, because the reverts happen immediately anyway. + + If ‘magit-auto-revert-immediately’ and ‘auto-revert-use-notify’ are + both ‘nil’, then reverts happen after ‘auto-revert-interval’ + seconds of user inactivity. That is not desirable. + + -- User Option: auto-revert-use-notify + + This option controls whether file notification functions should be + used. Note that this variable unfortunately defaults to ‘t’ even + on systems on which file notifications cannot be used. + + -- User Option: magit-auto-revert-tracked-only + + This option controls whether ‘magit-auto-revert-mode’ only reverts + tracked files or all files that are located inside Git + repositories, including untracked files and files located inside + Git’s control directory. + + -- User Option: auto-revert-mode + + The global mode ‘magit-auto-revert-mode’ works by turning on this + local mode in the appropriate buffers (but + ‘global-auto-revert-mode’ is implemented differently). You can + also turn it on or off manually, which might be necessary if Magit + does not notice that a previously untracked file now is being + tracked or vice-versa. + + -- User Option: auto-revert-stop-on-user-input + + This option controls whether the arrival of user input suspends the + automatic reverts for ‘auto-revert-interval’ seconds. + + -- User Option: auto-revert-interval + + This option controls how many seconds Emacs waits for before + resuming suspended reverts. + + -- User Option: auto-revert-buffer-list-filter + + This option specifies an additional filter used by + ‘auto-revert-buffers’ to determine whether a buffer should be + reverted or not. + + This option is provided by Magit, which also advises + ‘auto-revert-buffers’ to respect it. Magit users who do not turn + on the local mode ‘auto-revert-mode’ themselves, are best served by + setting the value to ‘magit-auto-revert-repository-buffer-p’. + + However the default is nil, so as not to disturb users who do use + the local mode directly. If you experience delays when running + Magit commands, then you should consider using one of the + predicates provided by Magit - especially if you also use Tramp. + + Users who do turn on ‘auto-revert-mode’ in buffers in which Magit + doesn’t do that for them, should likely not use any filter. Users + who turn on ‘global-auto-revert-mode’, do not have to worry about + this option, because it is disregarded if the global mode is + enabled. + + -- User Option: auto-revert-verbose + + This option controls whether Emacs reports when a buffer has been + reverted. + + The options with the ‘auto-revert-’ prefix are located in the Custom +group named ‘auto-revert’. The other, Magit-specific, options are +located in the ‘magit’ group. + +* Menu: + +* Risk of Reverting Automatically:: + + +File: magit.info, Node: Risk of Reverting Automatically, Up: Automatic Reverting of File-Visiting Buffers + +Risk of Reverting Automatically +............................... + +For the vast majority of users, automatically reverting file-visiting +buffers after they have changed on disk is harmless. + + If a buffer is modified (i.e. it contains changes that haven’t been +saved yet), then Emacs will refuse to automatically revert it. If you +save a previously modified buffer, then that results in what is seen by +Git as an uncommitted change. Git will then refuse to carry out any +commands that would cause these changes to be lost. In other words, if +there is anything that could be lost, then either Git or Emacs will +refuse to discard the changes. + + However, if you use file-visiting buffers as a sort of ad hoc +"staging area", then the automatic reverts could potentially cause data +loss. So far I have heard from only one user who uses such a workflow. + + An example: You visit some file in a buffer, edit it, and save the +changes. Then, outside of Emacs (or at least not using Magit or by +saving the buffer) you change the file on disk again. At this point the +buffer is the only place where the intermediate version still exists. +You have saved the changes to disk, but that has since been overwritten. +Meanwhile Emacs considers the buffer to be unmodified (because you have +not made any changes to it since you last saved it to the visited file) +and therefore would not object to it being automatically reverted. At +this point an Auto-Revert mode would kick in. It would check whether +the buffer is modified and since that is not the case it would revert +it. The intermediate version would be lost. (Actually you could still +get it back using the ‘undo’ command.) + + If your workflow depends on Emacs preserving the intermediate version +in the buffer, then you have to disable all Auto-Revert modes. But +please consider that such a workflow would be dangerous even without +using an Auto-Revert mode, and should therefore be avoided. If Emacs +crashes or if you quit Emacs by mistake, then you would also lose the +buffer content. There would be no autosave file still containing the +intermediate version (because that was deleted when you saved the +buffer) and you would not be asked whether you want to save the buffer +(because it isn’t modified). + + +File: magit.info, Node: Sections, Next: Transient Commands, Prev: Modes and Buffers, Up: Interface Concepts + +4.2 Sections +============ + +Magit buffers are organized into nested sections, which can be collapsed +and expanded, similar to how sections are handled in Org mode. Each +section also has a type, and some sections also have a value. For each +section type there can also be a local keymap, shared by all sections of +that type. + + Taking advantage of the section value and type, many commands operate +on the current section, or when the region is active and selects +sections of the same type, all of the selected sections. Commands that +only make sense for a particular section type (as opposed to just +behaving differently depending on the type) are usually bound in section +type keymaps. + +* Menu: + +* Section Movement:: +* Section Visibility:: +* Section Hooks:: +* Section Types and Values:: +* Section Options:: + + +File: magit.info, Node: Section Movement, Next: Section Visibility, Up: Sections + +4.2.1 Section Movement +---------------------- + +To move within a section use the usual keys (‘C-p’, ‘C-n’, ‘C-b’, ‘C-f’ +etc), whose global bindings are not shadowed. To move to another +section use the following commands. + +‘p’ (‘magit-section-backward’) + + When not at the beginning of a section, then move to the beginning + of the current section. At the beginning of a section, instead + move to the beginning of the previous visible section. + +‘n’ (‘magit-section-forward’) + + Move to the beginning of the next visible section. + +‘M-p’ (‘magit-section-backward-siblings’) + + Move to the beginning of the previous sibling section. If there is + no previous sibling section, then move to the parent section + instead. + +‘M-n’ (‘magit-section-forward-siblings’) + + Move to the beginning of the next sibling section. If there is no + next sibling section, then move to the parent section instead. + +‘^’ (‘magit-section-up’) + + Move to the beginning of the parent of the current section. + + The above commands all call the hook ‘magit-section-movement-hook’. +Any of the functions listed below can be used as members of this hook. + + -- Variable: magit-section-movement-hook + + This hook is run by all of the above movement commands, after + arriving at the destination. + + -- Function: magit-hunk-set-window-start + + This hook function ensures that the beginning of the current + section is visible, provided it is a ‘hunk’ section. Otherwise, it + does nothing. This function is a member of the hook’s default + value. + + -- Function: magit-section-set-window-start + + This hook function ensures that the beginning of the current + section is visible, regardless of the section’s type. If you add + this to ‘magit-section-movement-hook’, then you must remove the + hunk-only variant in turn. + + -- Function: magit-log-maybe-show-more-commits + + This hook function only has an effect in log buffers, and ‘point’ + is on the "show more" section. If that is the case, then it + doubles the number of commits that are being shown. This function + is a member of the hook’s default value. + + -- Function: magit-log-maybe-update-revision-buffer + + When moving inside a log buffer, then this function updates the + revision buffer, provided it is already being displayed in another + window of the same frame. This function is a member of the hook’s + default value. + + -- Function: magit-log-maybe-update-blob-buffer + + When moving inside a log buffer and another window of the same + frame displays a blob buffer, then this function instead displays + the blob buffer for the commit at point in that window. + + -- Function: magit-status-maybe-update-revision-buffer + + When moving inside a status buffer, then this function updates the + revision buffer, provided it is already being displayed in another + window of the same frame. + + -- Function: magit-status-maybe-update-stash-buffer + + When moving inside a status buffer, then this function updates the + stash buffer, provided it is already being displayed in another + window of the same frame. + + -- Function: magit-status-maybe-update-blob-buffer + + When moving inside a status buffer and another window of the same + frame displays a blob buffer, then this function instead displays + the blob buffer for the commit at point in that window. + + -- Function: magit-stashes-maybe-update-stash-buffer + + When moving inside a buffer listing stashes, then this function + updates the stash buffer, provided it is already being displayed in + another window of the same frame. + + -- User Option: magit-update-other-window-delay + + Delay before automatically updating the other window. + + When moving around in certain buffers, then certain other buffers, + which are being displayed in another window, may optionally be + updated to display information about the section at point. + + When holding down a key to move by more than just one section, then + that would update that buffer for each section on the way. To + prevent that, updating the revision buffer is delayed, and this + option controls for how long. For optimal experience you might + have to adjust this delay and/or the keyboard repeat rate and delay + of your graphical environment or operating system. + + +File: magit.info, Node: Section Visibility, Next: Section Hooks, Prev: Section Movement, Up: Sections + +4.2.2 Section Visibility +------------------------ + +Magit provides many commands for changing the visibility of sections, +but all you need to get started are the next two. + +‘TAB’ (‘magit-section-toggle’) + + Toggle the visibility of the body of the current section. + +‘C-’ (‘magit-section-cycle’) + + Cycle the visibility of current section and its children. + +‘M-’ (‘magit-section-cycle-diffs’) + + Cycle the visibility of diff-related sections in the current + buffer. + +‘S-’ (‘magit-section-cycle-global’) + + Cycle the visibility of all sections in the current buffer. + +‘1’ (‘magit-section-show-level-1’) +‘2’ (‘magit-section-show-level-2’) +‘3’ (‘magit-section-show-level-3’) +‘4’ (‘magit-section-show-level-4’) + + Show sections surrounding the current section up to level N. + +‘M-1’ (‘magit-section-show-level-1-all’) +‘M-2’ (‘magit-section-show-level-2-all’) +‘M-3’ (‘magit-section-show-level-3-all’) +‘M-4’ (‘magit-section-show-level-4-all’) + + Show all sections up to level N. + + Some functions, which are used to implement the above commands, are +also exposed as commands themselves. By default no keys are bound to +these commands, as they are generally perceived to be much less useful. +But your mileage may vary. + + -- Command: magit-section-show + + Show the body of the current section. + + -- Command: magit-section-hide + + Hide the body of the current section. + + -- Command: magit-section-show-headings + + Recursively show headings of children of the current section. Only + show the headings. Previously shown text-only bodies are hidden. + + -- Command: magit-section-show-children + + Recursively show the bodies of children of the current section. + With a prefix argument show children down to the level of the + current section, and hide deeper children. + + -- Command: magit-section-hide-children + + Recursively hide the bodies of children of the current section. + + -- Command: magit-section-toggle-children + + Toggle visibility of bodies of children of the current section. + + When a buffer is first created then some sections are shown expanded +while others are not. This is hard coded. When a buffer is refreshed +then the previous visibility is preserved. The initial visibility of +certain sections can also be overwritten using the hook +‘magit-section-set-visibility-hook’. + + -- User Option: magit-section-initial-visibility-alist + + This options can be used to override the initial visibility of + sections. In the future it will also be used to define the + defaults, but currently a section’s default is still hardcoded. + + The value is an alist. Each element maps a section type or lineage + to the initial visibility state for such sections. The state has + to be one of ‘show’ or ‘hide’, or a function that returns one of + these symbols. A function is called with the section as the only + argument. + + Use the command ‘magit-describe-section-briefly’ to determine a + section’s lineage or type. The vector in the output is the section + lineage and the type is the first element of that vector. + Wildcards can be used, see ‘magit-section-match’. + + -- User Option: magit-section-cache-visibility + + This option controls for which sections the previous visibility + state should be restored if a section disappears and later appears + again. The value is a boolean or a list of section types. If t, + then the visibility of all sections is cached. Otherwise this is + only done for sections whose type matches one of the listed types. + + This requires that the function ‘magit-section-cached-visibility’ + is a member of ‘magit-section-set-visibility-hook’. + + -- Variable: magit-section-set-visibility-hook + + This hook is run when first creating a buffer and also when + refreshing an existing buffer, and is used to determine the + visibility of the section currently being inserted. + + Each function is called with one argument, the section being + inserted. It should return ‘hide’ or ‘show’, or to leave the + visibility undefined ‘nil’. If no function decides on the + visibility and the buffer is being refreshed, then the visibility + is preserved; or if the buffer is being created, then the hard + coded default is used. + + Usually this should only be used to set the initial visibility but + not during refreshes. If ‘magit-insert-section--oldroot’ is + non-nil, then the buffer is being refreshed and these functions + should immediately return ‘nil’. + + -- User Option: magit-section-visibility-indicator + + This option controls whether and how to indicate that a section can + be expanded/collapsed. + + If nil, then no visibility indicators are shown. Otherwise the + value has to have one of these two forms: + + • ‘(EXPANDABLE-BITMAP . COLLAPSIBLE-BITMAP)’ + + Both values have to be variables whose values are fringe + bitmaps. In this case every section that can be expanded or + collapsed gets an indicator in the left fringe. + + To provide extra padding around the indicator, set + ‘left-fringe-width’ in ‘magit-mode-hook’, e.g.: + + (add-hook 'magit-mode-hook (lambda () + (setq left-fringe-width 20))) + + • ‘(STRING . BOOLEAN)’ + + In this case STRING (usually an ellipsis) is shown at the end + of the heading of every collapsed section. Expanded sections + get no indicator. The cdr controls whether the appearance of + these ellipsis take section highlighting into account. Doing + so might potentially have an impact on performance, while not + doing so is kinda ugly. + + +File: magit.info, Node: Section Hooks, Next: Section Types and Values, Prev: Section Visibility, Up: Sections + +4.2.3 Section Hooks +------------------- + +Which sections are inserted into certain buffers is controlled with +hooks. This includes the status and the refs buffers. For other +buffers, e.g. log and diff buffers, this is not possible. The command +‘magit-describe-section’ can be used to see which hook (if any) was +responsible for inserting the section at point. + + For buffers whose sections can be customized by the user, a hook +variable called ‘magit-TYPE-sections-hook’ exists. This hook should be +changed using ‘magit-add-section-hook’. Avoid using ‘add-hooks’ or the +Custom interface. + + The various available section hook variables are described later in +this manual along with the appropriate "section inserter functions". + + -- Function: magit-add-section-hook hook function &optional at append + local + + Add the function FUNCTION to the value of section hook HOOK. + + Add FUNCTION at the beginning of the hook list unless optional + APPEND is non-nil, in which case FUNCTION is added at the end. If + FUNCTION already is a member then move it to the new location. + + If optional AT is non-nil and a member of the hook list, then add + FUNCTION next to that instead. Add before or after AT, or replace + AT with FUNCTION depending on APPEND. If APPEND is the symbol + ‘replace’, then replace AT with FUNCTION. For any other non-nil + value place FUNCTION right after AT. If nil, then place FUNCTION + right before AT. If FUNCTION already is a member of the list but + AT is not, then leave FUNCTION where ever it already is. + + If optional LOCAL is non-nil, then modify the hook’s buffer-local + value rather than its global value. This makes the hook local by + copying the default value. That copy is then modified. + + HOOK should be a symbol. If HOOK is void, it is first set to nil. + HOOK’s value must not be a single hook function. FUNCTION should + be a function that takes no arguments and inserts one or multiple + sections at point, moving point forward. FUNCTION may choose not + to insert its section(s), when doing so would not make sense. It + should not be abused for other side-effects. + + To remove a function from a section hook, use ‘remove-hook’. + + +File: magit.info, Node: Section Types and Values, Next: Section Options, Prev: Section Hooks, Up: Sections + +4.2.4 Section Types and Values +------------------------------ + +Each section has a type, for example ‘hunk’, ‘file’, and ‘commit’. +Instances of certain section types also have a value. The value of a +section of type ‘file’, for example, is a file name. + + Users usually do not have to worry about a section’s type and value, +but knowing them can be handy at times. + +‘M-x magit-describe-section-briefly’ (‘magit-describe-section-briefly’) + + Show information about the section at point in the echo area, as + "#". + + Many commands behave differently depending on the type of the section +at point and/or somehow consume the value of that section. But that is +only one of the reasons why the same key may do something different, +depending on what section is current. + + Additionally for each section type a keymap *might* be defined, named +‘magit-TYPE-section-map’. That keymap is used as text property keymap +of all text belonging to any section of the respective type. If such a +map does not exist for a certain type, then you can define it yourself, +and it will automatically be used. + + +File: magit.info, Node: Section Options, Prev: Section Types and Values, Up: Sections + +4.2.5 Section Options +--------------------- + +This section describes options that have an effect on more than just a +certain type of sections. As you can see there are not many of those. + + -- User Option: magit-section-show-child-count + + Whether to append the number of children to section headings. This + only affects sections that could benefit from this information. + + +File: magit.info, Node: Transient Commands, Next: Transient Arguments and Buffer Variables, Prev: Sections, Up: Interface Concepts + +4.3 Transient Commands +====================== + +Many Magit commands are implemented as *transient* commands. First the +user invokes a *prefix* command, which causes its *infix* arguments and +*suffix* commands to be displayed in the echo area. The user then +optionally sets some infix arguments and finally invokes one of the +suffix commands. + + This is implemented in the library ‘transient’. Earlier Magit +releases used the package ‘magit-popup’ and even earlier versions +library ‘magit-key-mode’. + + Transient is documented in *note (transient)Top::. + +‘C-c C-c’ (‘magit-dispatch’) + + This transient prefix command binds most of Magit’s other prefix + commands as suffix commands and displays them in a temporary buffer + until one of them is invoked. Invoking such a sub-prefix causes + the suffixes of that command to be bound and displayed instead of + those of ‘magit-dispatch’. + + This command is also, or especially, useful outside Magit buffers, so +you should setup a global binding: + + (global-set-key (kbd "C-x M-g") 'magit-dispatch) + + +File: magit.info, Node: Transient Arguments and Buffer Variables, Next: Completion Confirmation and the Selection, Prev: Transient Commands, Up: Interface Concepts + +4.4 Transient Arguments and Buffer Variables +============================================ + +The infix arguments of many of Magit’s transient prefix commands cease +to have an effect once the ‘git’ command that is called with those +arguments has returned. Commands that create a commit are a good +example for this. If the user changes the arguments, then that only +affects the next invocation of a suffix command. If the same transient +prefix command is later invoked again, then the arguments are initially +reset to the default value. This default value can be set for the +current Emacs session or saved permanently, see *note (transient)Saving +Values::. It is also possible to cycle through previously used sets of +arguments using ‘M-p’ and ‘M-n’, see *note (transient)Using History::. + + However the infix arguments of many other transient commands continue +to have an effect even after the ‘git’ command that was called with +those arguments has returned. The most important commands like this are +those that display a diff or log in a dedicated buffer. Their arguments +obviously continue to have an effect for as long as the respective diff +or log is being displayed. Furthermore the used arguments are stored in +buffer-local variables for future reference. + + For commands in the second group it isn’t always desirable to reset +their arguments to the global value when the transient prefix command is +invoked again. + + As mentioned above, it is possible to cycle through previously used +sets of arguments while a transient popup is visible. That means that +we could always reset the infix arguments to the default because the set +of arguments that is active in the existing buffer is only a few ‘M-p’ +away. Magit can be configured to behave like that, but because I expect +that most users would not find that very convenient, it is not the +default. + + Also note that it is possible to change the diff and log arguments +used in the current buffer (including the status buffer, which contains +both diff and log sections) using the respective "refresh" transient +prefix commands on ‘D’ and ‘L’. (‘d’ and ‘l’ on the other hand are +intended to change *what* diff or log is being displayed. It is +possible to also change *how* the diff or log is being displayed at the +same time, but if you only want to do the latter, then you should use +the refresh variants.) Because these secondary diff and log transient +prefixes are about *changing* the arguments used in the current buffer, +they *always* start out with the set of arguments that are currently in +effect in that buffer. + + Some commands are usually invoked directly even though they can also +be invoked as the suffix of a transient prefix command. Most +prominently ‘magit-show-commit’ is usually invoked by typing ‘RET’ while +point is on a commit in a log, but it can also be invoked from the +‘magit-diff’ transient prefix. + + When such a command is invoked directly, then it is important to +reuse the arguments as specified by the respective buffer-local values, +instead of using the default arguments. Imagine you press ‘RET’ in a +log to display the commit at point in a different buffer and then use +‘D’ to change how the diff is displayed in that buffer. And then you +press ‘RET’ on another commit to show that instead and the diff +arguments are reset to the default. Not cool; so Magit does not do that +by default. + + -- User Option: magit-prefix-use-buffer-arguments + + This option controls whether the infix arguments initially shown in + certain transient prefix commands are based on the arguments that + are currently in effect in the buffer that their suffixes update. + + The ‘magit-diff’ and ‘magit-log’ transient prefix commands are + affected by this option. + + -- User Option: magit-direct-use-buffer-arguments + + This option controls whether certain commands, when invoked + directly (i.e. not as the suffix of a transient prefix command), + use the arguments that are currently active in the buffer that they + are about to update. The alternative is to use the default value + for these arguments, which might change the arguments that are used + in the buffer. + +Valid values for both of the above options are: + + • ‘always’: Always use the set of arguments that is currently active + in the respective buffer, provided that buffer exists of course. + + • ‘selected’ or ‘t’: Use the set of arguments from the respective + buffer, but only if it is displayed in a window of the current + frame. This is the default for both variables. + + • ‘current’: Use the set of arguments from the respective buffer, but + only if it is the current buffer. + + • ‘never’: Never use the set of arguments from the respective buffer. + +I am afraid it gets more complicated still: + + • The global diff and log arguments are set for each support mode + individually. The diff arguments for example have different values + in ‘magit-diff-mode’, ‘magit-revision-mode’, + ‘magit-merge-preview-mode’ and ‘magit-status-mode’ buffers. + Setting or saving the value for one mode does not change the value + for other modes. The history however is shared. + + • When ‘magit-show-commit’ is invoked directly from a log buffer, + then the file filter is picked up from that buffer, not from the + revision buffer and or the mode’s global diff arguments. + + • Even though they are suffixes of the diff prefix + ‘magit-show-commit’ and ‘magit-stash-show’ do not use the diff + buffer used by the diff commands, instead they use the dedicated + revision and stash buffers. + + At the time you invoke the diff prefix it is unknown to Magit which + of the suffix commands you are going to invoke. While not certain, + more often than not users invoke one of the commands that use the + diff buffer, so the initial infix arguments are those used in that + buffer. However if you invoke one of these commands directly, then + Magit knows that it should use the arguments from the revision + resp. stash buffer. + + • The log prefix also features reflog commands, but these commands do + not use the log arguments. + + • If ‘magit-show-refs’ is invoked from a ‘magit-refs-mode’ buffer, + then it acts as a refresh prefix and therefore unconditionally uses + the buffer’s arguments as initial arguments. If it is invoked + elsewhere with a prefix argument, then it acts as regular prefix + and therefore respects ‘magit-prefix-use-buffer-arguments’. If it + is invoked elsewhere without a prefix argument, then it acts as a + direct command and therefore respects + ‘magit-direct-use-buffer-arguments’. + + +File: magit.info, Node: Completion Confirmation and the Selection, Next: Running Git, Prev: Transient Arguments and Buffer Variables, Up: Interface Concepts + +4.5 Completion, Confirmation and the Selection +============================================== + +* Menu: + +* Action Confirmation:: +* Completion and Confirmation:: +* The Selection:: +* The hunk-internal region:: +* Support for Completion Frameworks:: +* Additional Completion Options:: + + +File: magit.info, Node: Action Confirmation, Next: Completion and Confirmation, Up: Completion Confirmation and the Selection + +4.5.1 Action Confirmation +------------------------- + +By default many actions that could potentially lead to data loss have to +be confirmed. This includes many very common actions, so this can +quickly become annoying. Many of these actions can be undone and if you +have thought about how to undo certain mistakes, then it should be safe +to disable confirmation for the respective actions. + + The option ‘magit-no-confirm’ can be used to tell Magit to perform +certain actions without the user having to confirm them. Note that +while this option can only be used to disable confirmation for a +specific set of actions, the next section explains another way of +telling Magit to ask fewer questions. + + -- User Option: magit-no-confirm + + The value of this option is a list of symbols, representing actions + that do not have to be confirmed by the user before being carried + out. + + By default many potentially dangerous commands ask the user for + confirmation. Each of the below symbols stands for an action + which, when invoked unintentionally or without being fully aware of + the consequences, could lead to tears. In many cases there are + several commands that perform variations of a certain action, so we + don’t use the command names but more generic symbols. + + • Applying changes: + + • ‘discard’ Discarding one or more changes (i.e. hunks or + the complete diff for a file) loses that change, + obviously. + + • ‘reverse’ Reverting one or more changes can usually be + undone by reverting the reversion. + + • ‘stage-all-changes’, ‘unstage-all-changes’ When there are + both staged and unstaged changes, then un-/staging + everything would destroy that distinction. Of course + that also applies when un-/staging a single change, but + then less is lost and one does that so often that having + to confirm every time would be unacceptable. + + • Files: + + • ‘delete’ When a file that isn’t yet tracked by Git is + deleted, then it is completely lost, not just the last + changes. Very dangerous. + + • ‘trash’ Instead of deleting a file it can also be move to + the system trash. Obviously much less dangerous than + deleting it. + + Also see option ‘magit-delete-by-moving-to-trash’. + + • ‘resurrect’ A deleted file can easily be resurrected by + "deleting" the deletion, which is done using the same + command that was used to delete the same file in the + first place. + + • ‘untrack’ Untracking a file can be undone by tracking it + again. + + • ‘rename’ Renaming a file can easily be undone. + + • Sequences: + + • ‘reset-bisect’ Aborting (known to Git as "resetting") a + bisect operation loses all information collected so far. + + • ‘abort-rebase’ Aborting a rebase throws away all already + modified commits, but it’s possible to restore those from + the reflog. + + • ‘abort-merge’ Aborting a merge throws away all conflict + resolutions which have already been carried out by the + user. + + • ‘merge-dirty’ Merging with a dirty worktree can make it + hard to go back to the state before the merge was + initiated. + + • References: + + • ‘delete-unmerged-branch’ Once a branch has been deleted, + it can only be restored using low-level recovery tools + provided by Git. And even then the reflog is gone. The + user always has to confirm the deletion of a branch by + accepting the default choice (or selecting another + branch), but when a branch has not been merged yet, also + make sure the user is aware of that. + + • ‘delete-pr-remote’ When deleting a branch that was + created from a pull-request and if no other branches + still exist on that remote, then ‘magit-branch-delete’ + offers to delete the remote as well. This should be safe + because it only happens if no other refs exist in the + remotes namespace, and you can recreate the remote if + necessary. + + • ‘drop-stashes’ Dropping a stash is dangerous because Git + stores stashes in the reflog. Once a stash is removed, + there is no going back without using low-level recovery + tools provided by Git. When a single stash is dropped, + then the user always has to confirm by accepting the + default (or selecting another). This action only + concerns the deletion of multiple stashes at once. + + • Edit published history: + + Without adding these symbols here, you will be warned before + editing commits that have already been pushed to one of the + branches listed in ‘magit-published-branches’. + + • ‘amend-published’ Affects most commands that amend to + "HEAD". + + • ‘rebase-published’ Affects commands that perform + interactive rebases. This includes commands from the + commit transient that modify a commit other than "HEAD", + namely the various fixup and squash variants. + + • ‘edit-published’ Affects the commands + ‘magit-edit-line-commit’ and + ‘magit-diff-edit-hunk-commit’. These two commands make + it quite easy to accidentally edit a published commit, so + you should think twice before configuring them not to ask + for confirmation. + + To disable confirmation completely, add all three symbols here + or set ‘magit-published-branches’ to ‘nil’. + + • Various: + + • ‘kill-process’ There seldom is a reason to kill a + process. + + • Global settings: + + Instead of adding all of the above symbols to the value of + this option, you can also set it to the atom ‘t’, which has + the same effect as adding all of the above symbols. Doing + that most certainly is a bad idea, especially because other + symbols might be added in the future. So even if you don’t + want to be asked for confirmation for any of these actions, + you are still better of adding all of the respective symbols + individually. + + When ‘magit-wip-before-change-mode’ is enabled, then the + following actions can be undone fairly easily: ‘discard’, + ‘reverse’, ‘stage-all-changes’, and ‘unstage-all-changes’. If + and only if this mode is enabled, then ‘safe-with-wip’ has the + same effect as adding all of these symbols individually. + + +File: magit.info, Node: Completion and Confirmation, Next: The Selection, Prev: Action Confirmation, Up: Completion Confirmation and the Selection + +4.5.2 Completion and Confirmation +--------------------------------- + +Many Magit commands ask the user to select from a list of possible +things to act on, while offering the most likely choice as the default. +For many of these commands the default is the thing at point, provided +that it actually is a valid thing to act on. For many commands that act +on a branch, the current branch serves as the default if there is no +branch at point. + + These commands combine asking for confirmation and asking for a +target to act on into a single action. The user can confirm the default +target using ‘RET’ or abort using ‘C-g’. This is similar to a +‘y-or-n-p’ prompt, but the keys to confirm or abort differ. + + At the same time the user is also given the opportunity to select +another target, which is useful because for some commands and/or in some +situations you might want to select the action before selecting the +target by moving to it. + + However you might find that for some commands you always want to use +the default target, if any, or even that you want the command to act on +the default without requiring any confirmation at all. The option +‘magit-dwim-selection’ can be used to configure certain commands to that +effect. + + Note that when the region is active then many commands act on the +things that are selected using a mechanism based on the region, in many +cases after asking for confirmation. This region-based mechanism is +called the "selection" and is described in detail in the next section. +When a selection exists that is valid for the invoked command, then that +command never offers to act on something else, and whether it asks for +confirmation is not controlled by this option. + + Also note that Magit asks for confirmation of certain actions that +are not coupled with completion (or the selection). Such dialogs are +also not affected by this option and are described in the previous +section. + + -- User Option: magit-dwim-selection + + This option can be used to tell certain commands to use the thing at +point instead of asking the user to select a candidate to act on, with +or without confirmation. + + The value has the form ‘((COMMAND nil|PROMPT DEFAULT)...)’. + + • COMMAND is the command that should not prompt for a choice. To + have an effect, the command has to use the function + ‘magit-completing-read’ or a utility function which in turn uses + that function. + + • If the command uses ‘magit-completing-read’ multiple times, then + PROMPT can be used to only affect one of these uses. PROMPT, if + non-nil, is a regular expression that is used to match against the + PROMPT argument passed to ‘magit-completing-read’. + + • DEFAULT specifies how to use the default. If it is ‘t’, then the + DEFAULT argument passed to ‘magit-completing-read’ is used without + confirmation. If it is ‘ask’, then the user is given a chance to + abort. DEFAULT can also be ‘nil’, in which case the entry has no + effect. + + +File: magit.info, Node: The Selection, Next: The hunk-internal region, Prev: Completion and Confirmation, Up: Completion Confirmation and the Selection + +4.5.3 The Selection +------------------- + +If the region is active, then many Magit commands act on the things that +are selected using a mechanism based on the region instead of one single +thing. When the region is not active, then these commands act on the +thing at point or read a single thing to act on. This is described in +the previous section — this section only covers how multiple things are +selected, how that is visualized, and how certain commands behave when +that is the case. + + Magit’s mechanism for selecting multiple things, or rather sections +that represent these things, is based on the Emacs region, but the area +that Magit considers to be selected is typically larger than the region +and additional restrictions apply. + + Magit makes a distinction between a region that qualifies as forming +a valid Magit selection and a region that does not. If the region does +not qualify, then it is displayed as it is in other Emacs buffers. If +the region does qualify as a Magit selection, then the selection is +always visualized, while the region itself is only visualized if it +begins and ends on the same line. + + For a region to qualify as a Magit selection, it must begin in the +heading of one section and end in the heading of a sibling section. +Note that if the end of the region is at the very beginning of section +heading (i.e. at the very beginning of a line) then that section is +considered to be *inside* the selection. + + This is not consistent with how the region is normally treated in +Emacs — if the region ends at the beginning of a line, then that line is +outside the region. Due to how Magit visualizes the selection, it +should be obvious that this difference exists. + + Not every command acts on every valid selection. Some commands do +not even consider the location of point, others may act on the section +at point but not support acting on the selection, and even commands that +do support the selection of course only do so if it selects things that +they can act on. + + This is the main reason why the selection must include the section at +point. Even if a selection exists, the invoked command may disregard +it, in which case it may act on the current section only. It is much +safer to only act on the current section but not the other selected +sections than it is to act on the current section *instead* of the +selected sections. The latter would be much more surprising and if the +current section always is part of the selection, then that cannot +happen. + + -- Variable: magit-keep-region-overlay + + This variable controls whether the region is visualized as usual + even when a valid Magit selection or a hunk-internal region exists. + See the doc-string for more information. + + +File: magit.info, Node: The hunk-internal region, Next: Support for Completion Frameworks, Prev: The Selection, Up: Completion Confirmation and the Selection + +4.5.4 The hunk-internal region +------------------------------ + +Somewhat related to the Magit selection described in the previous +section is the hunk-internal region. + + Like the selection, the hunk-internal region is based on the Emacs +region but causes that region to not be visualized as it would in other +Emacs buffers, and includes the line on which the region ends even if it +ends at the very beginning of that line. + + Unlike the selection, which is based on a region that must begin in +the heading of one section and ends in the section of a sibling section, +the hunk-internal region must begin inside the *body* of a hunk section +and end in the body of the *same* section. + + The hunk-internal region is honored by "apply" commands, which can, +among other targets, act on a hunk. If the hunk-internal region is +active, then such commands act only on the marked part of the hunk +instead of on the complete hunk. + + +File: magit.info, Node: Support for Completion Frameworks, Next: Additional Completion Options, Prev: The hunk-internal region, Up: Completion Confirmation and the Selection + +4.5.5 Support for Completion Frameworks +--------------------------------------- + +The built-in option ‘completing-read-function’ specifies the low-level +function used by ‘completing-read’ to ask a user to select from a list +of choices. Its default value is ‘completing-read-default’. +Alternative completion frameworks typically activate themselves by +substituting their own implementation. + + Mostly for historic reasons Magit provides a similar option named +‘magit-completing-read-function’, which only controls the low-level +function used by ‘magit-completing-read’. This option also makes it +possible to use a different completing mechanism for Magit than for the +rest of Emacs, but doing that is not recommend. + + You most likely don’t have to customize the magit-specific option to +use an alternative completion framework. For example, if you enable +‘ivy-mode’, then Magit will respect that, and if you enable ‘helm-mode’, +then you are done too. + + However if you want to use Ido, then ‘ido-mode’ won’t do the trick. +You will also have to install the ‘ido-completing-read+’ package and use +‘magit-ido-completing-read’ as ‘magit-completing-read-function’. + + -- User Option: magit-completing-read-function + + The value of this variable is the low-level function used to + perform completion by code that uses ‘magit-completing-read’ (as + opposed to the built-in ‘completing-read’). + + The default value, ‘magit-builtin-completing-read’, is suitable for + the standard completion mechanism, ‘ivy-mode’, and ‘helm-mode’ at + least. + + The built-in ‘completing-read’ and ‘completing-read-default’ are + *not* suitable to be used here. ‘magit-builtin-completing-read’ + performs some additional work, and any function used in its place + has to do the same. + + -- Function: magit-builtin-completing-read prompt choices &optional + predicate require-match initial-input hist def + + This function performs completion using the built-in + ‘completing-read’ and does some additional magit-specific work. + + -- Function: magit-ido-completing-read prompt choices &optional + predicate require-match initial-input hist def + + This function performs completion using ‘ido-completing-read+’ from + the package by the same name (which you have to explicitly install) + and does some additional magit-specific work. + + We have to use ‘ido-completing-read+’ instead of the + ‘ido-completing-read’ that comes with Ido itself, because the + latter, while intended as a drop-in replacement, cannot serve that + purpose because it violates too many of the implicit conventions. + + -- Function: magit-completing-read prompt choices &optional predicate + require-match initial-input hist def fallback + + This is the function that Magit commands use when they need the + user to select a single thing to act on. The arguments have the + same meaning as for ‘completing-read’, except for FALLBACK, which + is unique to this function and is described below. + + Instead of asking the user to choose from a list of possible + candidates, this function may just return the default specified by + DEF, with or without requiring user confirmation. Whether that is + the case depends on PROMPT, ‘this-command’ and + ‘magit-dwim-selection’. See the documentation of the latter for + more information. + + If it does read a value in the minibuffer, then this function acts + similar to ‘completing-read’, except for the following: + + • COLLECTION must be a list of choices. A function is not + supported. + + • If REQUIRE-MATCH is ‘nil’ and the user exits without a choice, + then ‘nil’ is returned instead of an empty string. + + • If REQUIRE-MATCH is non-nil and the users exits without a + choice, an user-error is raised. + + • FALLBACK specifies a secondary default that is only used if + the primary default DEF is ‘nil’. The secondary default is + not subject to ‘magit-dwim-selection’ — if DEF is ‘nil’ but + FALLBACK is not, then this function always asks the user to + choose a candidate, just as if both defaults were ‘nil’. + + • ": " is appended to PROMPT. + + • PROMPT is modified to end with \" (default DEF|FALLBACK): \" + provided that DEF or FALLBACK is non-nil, that neither + ‘ivy-mode’ nor ‘helm-mode’ is enabled, and that + ‘magit-completing-read-function’ is set to its default value + of ‘magit-builtin-completing-read’. + + +File: magit.info, Node: Additional Completion Options, Prev: Support for Completion Frameworks, Up: Completion Confirmation and the Selection + +4.5.6 Additional Completion Options +----------------------------------- + + -- User Option: magit-list-refs-sortby + + For many commands that read a ref or refs from the user, the value + of this option can be used to control the order of the refs. Valid + values include any key accepted by the ‘--sort’ flag of ‘git + for-each-ref’. By default, refs are sorted alphabetically by their + full name (e.g., "refs/heads/master"). + + +File: magit.info, Node: Running Git, Prev: Completion Confirmation and the Selection, Up: Interface Concepts + +4.6 Running Git +=============== + +* Menu: + +* Viewing Git Output:: +* Git Process Status:: +* Running Git Manually:: +* Git Executable:: +* Global Git Arguments:: + + +File: magit.info, Node: Viewing Git Output, Next: Git Process Status, Up: Running Git + +4.6.1 Viewing Git Output +------------------------ + +Magit runs Git either for side-effects (e.g. when pushing) or to get +some value (e.g. the name of the current branch). + + When Git is run for side-effects, the process output is logged in a +per-repository log buffer, which can be consulted using the +‘magit-process’ command when things don’t go as expected. + + The output/errors for up to ‘magit-process-log-max’ Git commands are +retained. + +‘$’ (‘magit-process’) + + This commands displays the process buffer for the current + repository. + + Inside that buffer, the usual key bindings for navigating and showing +sections are available. There is one additional command. + +‘k’ (‘magit-process-kill’) + + This command kills the process represented by the section at point. + + -- User Option: magit-git-debug + + When this is non-nil then the output of all calls to git are logged + in the process buffer. This is useful when debugging, otherwise it + just negatively affects performance. + + +File: magit.info, Node: Git Process Status, Next: Running Git Manually, Prev: Viewing Git Output, Up: Running Git + +4.6.2 Git Process Status +------------------------ + +When a Git process is running for side-effects, Magit displays an +indicator in the mode line, using the ‘magit-mode-line-process’ face. + + If the Git process exits successfully, the process indicator is +removed from the mode line immediately. + + In the case of a Git error, the process indicator is not removed, but +is instead highlighted with the ‘magit-mode-line-process-error’ face, +and the error details from the process buffer are provided as a tooltip +for mouse users. This error indicator persists in the mode line until +the next magit buffer refresh. + + If you do not wish process errors to be indicated in the mode line, +customize the ‘magit-process-display-mode-line-error’ user option. + + Process errors are additionally indicated at the top of the status +buffer. + + +File: magit.info, Node: Running Git Manually, Next: Git Executable, Prev: Git Process Status, Up: Running Git + +4.6.3 Running Git Manually +-------------------------- + +While Magit provides many Emacs commands to interact with Git, it does +not cover everything. In those cases your existing Git knowledge will +come in handy. Magit provides some commands for running arbitrary Git +commands by typing them into the minibuffer, instead of having to switch +to a shell. + +‘!’ (‘magit-run’) + + This transient prefix command binds the following suffix commands + and displays them in a temporary buffer until a suffix is invoked. + +‘! !’ (‘magit-git-command-topdir’) + + This command reads a command from the user and executes it in the + top-level directory of the current working tree. + + The string "git " is used as initial input when prompting the user + for the command. It can be removed to run another command. + +‘! p’ (‘magit-git-command’) + + This command reads a command from the user and executes it in + ‘default-directory’. With a prefix argument the command is + executed in the top-level directory of the current working tree + instead. + + The string "git " is used as initial input when prompting the user + for the command. It can be removed to run another command. + +‘! s’ (‘magit-shell-command-topdir’) + + This command reads a command from the user and executes it in the + top-level directory of the current working tree. + +‘! S’ (‘magit-shell-command’) + + This command reads a command from the user and executes it in + ‘default-directory’. With a prefix argument the command is + executed in the top-level directory of the current working tree + instead. + + -- User Option: magit-shell-command-verbose-prompt + + Whether the prompt, used by the above commands when reading a shell + command, shows the directory in which it will be run. + + These suffix commands start external gui tools. + +‘! k’ (‘magit-run-gitk’) + + This command runs ‘gitk’ in the current repository. + +‘! a’ (‘magit-run-gitk-all’) + + This command runs ‘gitk --all’ in the current repository. + +‘! b’ (‘magit-run-gitk-branches’) + + This command runs ‘gitk --branches’ in the current repository. + +‘! g’ (‘magit-run-git-gui’) + + This command runs ‘git gui’ in the current repository. + + +File: magit.info, Node: Git Executable, Next: Global Git Arguments, Prev: Running Git Manually, Up: Running Git + +4.6.4 Git Executable +-------------------- + +Except on MS Windows, Magit defaults to running Git without specifying +the path to the git executable. Instead the first executable found by +Emacs on ‘exec-path’ is used (whose value in turn is set based on the +value of the environment variable ‘$PATH’ when Emacs was started). + + This has the advantage that it continues to work even when using +Tramp to connect to a remote machine on which the executable is found in +a different place. The downside is that if you have multiple versions +of Git installed, then you might end up using another version than the +one you think you are using. + +‘M-x magit-version’ (‘magit-version’) + + This command shows the currently used versions of Magit, Git, and + Emacs in the echo area. Non-interactively this just returns the + Magit version. + + When the ‘system-type’ is ‘windows-nt’, then ‘magit-git-executable’ +is set to an absolute path when Magit is first loaded. This is +necessary because Git on that platform comes with several wrapper +scripts for the actual git binary, which are also placed on ‘$PATH’, and +using one of these wrappers instead of the binary would degrade +performance horribly. + + If Magit doesn’t find the correct executable then you *can* work +around that by setting ‘magit-git-executable’ to an absolute path. But +note that doing so is a kludge. It is better to make sure the order in +the environment variable ‘$PATH’ is correct, and that Emacs is started +with that environment in effect. The command +‘magit-debug-git-executable’ can be useful to find out where Emacs is +searching for git. If you have to connect from Windows to a non-Windows +machine, then you must change the value to "git". + + -- User Option: magit-git-executable + + The git executable used by Magit, either the full path to the + executable or the string "git" to let Emacs find the executable + itself, using the standard mechanism for doing such things. + +‘M-x magit-debug-git-executable’ (‘magit-debug-git-executable’) + + Display a buffer with information about ‘magit-git-executable’. + + +File: magit.info, Node: Global Git Arguments, Prev: Git Executable, Up: Running Git + +4.6.5 Global Git Arguments +-------------------------- + + -- User Option: magit-git-global-arguments + + The arguments set here are used every time the git executable is + run as a subprocess. They are placed right after the executable + itself and before the git command - as in ‘git HERE... COMMAND + REST’. For valid arguments see *note (gitman)git::. + + Be careful what you add here, especially if you are using Tramp to + connect to servers with ancient Git versions. Never remove + anything that is part of the default value, unless you really know + what you are doing. And think very hard before adding something; + it will be used every time Magit runs Git for any purpose. + + +File: magit.info, Node: Inspecting, Next: Manipulating, Prev: Interface Concepts, Up: Top + +5 Inspecting +************ + +The functionality provided by Magit can be roughly divided into three +groups: inspecting existing data, manipulating existing data or adding +new data, and transferring data. Of course that is a rather crude +distinction that often falls short, but it’s more useful than no +distinction at all. This section is concerned with inspecting data, the +next two with manipulating and transferring it. Then follows a section +about miscellaneous functionality, which cannot easily be fit into this +distinction. + + Of course other distinctions make sense too, e.g. Git’s distinction +between porcelain and plumbing commands, which for the most part is +equivalent to Emacs’ distinction between interactive commands and +non-interactive functions. All of the sections mentioned before are +mainly concerned with the porcelain – Magit’s plumbing layer is +described later. + +* Menu: + +* Status Buffer:: +* Repository List:: +* Logging:: +* Diffing:: +* Ediffing:: +* References Buffer:: +* Bisecting:: +* Visiting Files and Blobs:: +* Blaming:: + + +File: magit.info, Node: Status Buffer, Next: Repository List, Up: Inspecting + +5.1 Status Buffer +================= + +While other Magit buffers contain e.g. one particular diff or one +particular log, the status buffer contains the diffs for staged and +unstaged changes, logs for unpushed and unpulled commits, lists of +stashes and untracked files, and information related to the current +branch. + + During certain incomplete operations – for example when a merge +resulted in a conflict – additional information is displayed that helps +proceeding with or aborting the operation. + + The command ‘magit-status’ displays the status buffer belonging to +the current repository in another window. This command is used so often +that it should be bound globally. We recommend using ‘C-x g’: + + (global-set-key (kbd "C-x g") 'magit-status) + +‘C-x g’ (‘magit-status’) + + When invoked from within an existing Git repository, then this + command shows the status of that repository in a buffer. + + If the current directory isn’t located within a Git repository, + then this command prompts for an existing repository or an + arbitrary directory, depending on the option + ‘magit-repository-directories’, and the status for the selected + repository is shown instead. + + • If that option specifies any existing repositories, then the + user is asked to select one of them. + + • Otherwise the user is asked to select an arbitrary directory + using regular file-name completion. If the selected directory + is the top-level directory of an existing working tree, then + the status buffer for that is shown. + + • Otherwise the user is offered to initialize the selected + directory as a new repository. After creating the repository + its status buffer is shown. + + These fallback behaviors can also be forced using one or more + prefix arguments: + + • With two prefix arguments (or more precisely a numeric prefix + value of 16 or greater) an arbitrary directory is read, which + is then acted on as described above. The same could be + accomplished using the command ‘magit-init’. + + • With a single prefix argument an existing repository is read + from the user, or if no repository can be found based on the + value of ‘magit-repository-directories’, then the behavior is + the same as with two prefix arguments. + + -- User Option: magit-repository-directories + + List of directories that are Git repositories or contain Git + repositories. + + Each element has the form ‘(DIRECTORY . DEPTH)’. DIRECTORY has to + be a directory or a directory file-name, a string. DEPTH, an + integer, specifies the maximum depth to look for Git repositories. + If it is 0, then only add DIRECTORY itself. + + This option controls which repositories are being listed by + ‘magit-list-repositories’. It also affects ‘magit-status’ (which + see) in potentially surprising ways (see above). + + -- Command: ido-enter-magit-status + + From an Ido prompt used to open a file, instead drop into + ‘magit-status’. This is similar to ‘ido-magic-delete-char’, which, + despite its name, usually causes a Dired buffer to be created. + + To make this command available, use something like: + + (add-hook 'ido-setup-hook + (lambda () + (define-key ido-completion-map + (kbd \"C-x g\") 'ido-enter-magit-status))) + + Starting with Emacs 25.1 the Ido keymaps are defined just once + instead of every time Ido is invoked, so now you can modify it like + pretty much every other keymap: + + (define-key ido-common-completion-map + (kbd \"C-x g\") 'ido-enter-magit-status) + +* Menu: + +* Status Sections:: +* Status Header Sections:: +* Status Module Sections:: +* Status Options:: + + +File: magit.info, Node: Status Sections, Next: Status Header Sections, Up: Status Buffer + +5.1.1 Status Sections +--------------------- + +The contents of status buffers is controlled using the hook +‘magit-status-sections-hook’. See *note Section Hooks:: to learn about +such hooks and how to customize them. + + -- User Option: magit-status-sections-hook + + Hook run to insert sections into a status buffer. + + The first function on that hook by default is +‘magit-insert-status-headers’; it is described in the next section. By +default the following functions are also members of that hook: + + -- Function: magit-insert-merge-log + + Insert section for the on-going merge. Display the heads that are + being merged. If no merge is in progress, do nothing. + + -- Function: magit-insert-rebase-sequence + + Insert section for the on-going rebase sequence. If no such + sequence is in progress, do nothing. + + -- Function: magit-insert-am-sequence + + Insert section for the on-going patch applying sequence. If no + such sequence is in progress, do nothing. + + -- Function: magit-insert-sequencer-sequence + + Insert section for the on-going cherry-pick or revert sequence. If + no such sequence is in progress, do nothing. + + -- Function: magit-insert-bisect-output + + While bisecting, insert section with output from ‘git bisect’. + + -- Function: magit-insert-bisect-rest + + While bisecting, insert section visualizing the bisect state. + + -- Function: magit-insert-bisect-log + + While bisecting, insert section logging bisect progress. + + -- Function: magit-insert-untracked-files + + Maybe insert a list or tree of untracked files. + + Do so depending on the value of ‘status.showUntrackedFiles’. Note + that even if the value is ‘all’, Magit still initially only shows + directories. But the directory sections can then be expanded using + ‘TAB’. + + -- Function: magit-insert-unstaged-changes + + Insert section showing unstaged changes. + + -- Function: magit-insert-staged-changes + + Insert section showing staged changes. + + -- Function: magit-insert-stashes &optional ref heading + + Insert the ‘stashes’ section showing reflog for "refs/stash". If + optional REF is non-nil show reflog for that instead. If optional + HEADING is non-nil use that as section heading instead of + "Stashes:". + + -- Function: magit-insert-unpulled-from-upstream + + Insert section showing commits that haven’t been pulled from the + upstream branch yet. + + -- Function: magit-insert-unpulled-from-pushremote + + Insert section showing commits that haven’t been pulled from the + push-remote branch yet. + + -- Function: magit-insert-unpushed-to-upstream + + Insert section showing commits that haven’t been pushed to the + upstream yet. + + -- Function: magit-insert-unpushed-to-pushremote + + Insert section showing commits that haven’t been pushed to the + push-remote yet. + + The following functions can also be added to the above hook: + + -- Function: magit-insert-tracked-files + + Insert a tree of tracked files. + + -- Function: magit-insert-ignored-files + + Insert a tree of ignored files. Its possible to limit the logs in + the current buffer to a certain directory using ‘D = f + RET g’. If you do that, then that that also affects this command. + + The log filter can be used to limit to multiple files. In that + case this function only respects the first of the files and only if + it is a directory. + + -- Function: magit-insert-skip-worktree-files + + Insert a tree of skip-worktree files. If the first element of + ‘magit-buffer-diff-files’ is a directory, then limit the list to + files below that. The value of that variable can be set using ‘D + -- DIRECTORY RET g’. + + -- Function: magit-insert-assumed-unchanged-files + + Insert a tree of files that are assumed to be unchanged. If the + first element of ‘magit-buffer-diff-files’ is a directory, then + limit the list to files below that. The value of that variable can + be set using ‘D -- DIRECTORY RET g’. + + -- Function: magit-insert-unpulled-or-recent-commits + + Insert section showing unpulled or recent commits. If an upstream + is configured for the current branch and it is ahead of the current + branch, then show the missing commits. Otherwise, show the last + ‘magit-log-section-commit-count’ commits. + + -- Function: magit-insert-recent-commits + + Insert section showing the last ‘magit-log-section-commit-count’ + commits. + + -- User Option: magit-log-section-commit-count + + How many recent commits ‘magit-insert-recent-commits’ and + ‘magit-insert-unpulled-or-recent-commits’ (provided there are no + unpulled commits) show. + + -- Function: magit-insert-unpulled-cherries + + Insert section showing unpulled commits. Like + ‘magit-insert-unpulled-commits’ but prefix each commit that has not + been applied yet (i.e. a commit with a patch-id not shared with + any local commit) with "+", and all others with "-". + + -- Function: magit-insert-unpushed-cherries + + Insert section showing unpushed commits. Like + ‘magit-insert-unpushed-commits’ but prefix each commit which has + not been applied to upstream yet (i.e. a commit with a patch-id + not shared with any upstream commit) with "+" and all others with + "-". + + See *note References Buffer:: for some more section inserters, which +could be used here. + + +File: magit.info, Node: Status Header Sections, Next: Status Module Sections, Prev: Status Sections, Up: Status Buffer + +5.1.2 Status Header Sections +---------------------------- + +The contents of status buffers is controlled using the hook +‘magit-status-sections-hook’ (see *note Status Sections::). + + By default ‘magit-insert-status-headers’ is the first member of that +hook variable. + + -- Function: magit-insert-status-headers + + Insert headers sections appropriate for ‘magit-status-mode’ + buffers. The sections are inserted by running the functions on the + hook ‘magit-status-headers-hook’. + + -- User Option: magit-status-headers-hook + + Hook run to insert headers sections into the status buffer. + + This hook is run by ‘magit-insert-status-headers’, which in turn + has to be a member of ‘magit-status-sections-hook’ to be used at + all. + + By default the following functions are members of the above hook: + + -- Function: magit-insert-error-header + + Insert a header line showing the message about the Git error that + just occurred. + + This function is only aware of the last error that occur when Git + was run for side-effects. If, for example, an error occurs while + generating a diff, then that error won’t be inserted. Refreshing + the status buffer causes this section to disappear again. + + -- Function: magit-insert-diff-filter-header + + Insert a header line showing the effective diff filters. + + -- Function: magit-insert-head-branch-header + + Insert a header line about the current branch or detached ‘HEAD’. + + -- Function: magit-insert-upstream-branch-header + + Insert a header line about the branch that is usually pulled into + the current branch. + + -- Function: magit-insert-push-branch-header + + Insert a header line about the branch that the current branch is + usually pushed to. + + -- Function: magit-insert-tags-header + + Insert a header line about the current and/or next tag, along with + the number of commits between the tag and ‘HEAD’. + + The following functions can also be added to the above hook: + + -- Function: magit-insert-repo-header + + Insert a header line showing the path to the repository top-level. + + -- Function: magit-insert-remote-header + + Insert a header line about the remote of the current branch. + + If no remote is configured for the current branch, then fall back + showing the "origin" remote, or if that does not exist the first + remote in alphabetic order. + + -- Function: magit-insert-user-header + + Insert a header line about the current user. + + +File: magit.info, Node: Status Module Sections, Next: Status Options, Prev: Status Header Sections, Up: Status Buffer + +5.1.3 Status Module Sections +---------------------------- + +The contents of status buffers is controlled using the hook +‘magit-status-sections-hook’ (see *note Status Sections::). + + By default ‘magit-insert-modules’ is _not_ a member of that hook +variable. + + -- Function: magit-insert-modules + + Insert submodule sections. + + Hook ‘magit-module-sections-hook’ controls which module sections + are inserted, and option ‘magit-module-sections-nested’ controls + whether they are wrapped in an additional section. + + -- User Option: magit-module-sections-hook + + Hook run by ‘magit-insert-modules’. + + -- User Option: magit-module-sections-nested + + This option controls whether ‘magit-insert-modules’ wraps inserted + sections in an additional section. + + If this is non-nil, then only a single top-level section is + inserted. If it is nil, then all sections listed in + ‘magit-module-sections-hook’ become top-level sections. + + -- Function: magit-insert-modules-overview + + Insert sections for all submodules. For each section insert the + path, the branch, and the output of ‘git describe --tags’, or, + failing that, the abbreviated HEAD commit hash. + + Press ‘RET’ on such a submodule section to show its own status + buffer. Press ‘RET’ on the "Modules" section to display a list of + submodules in a separate buffer. This shows additional information + not displayed in the super-repository’s status buffer. + + -- Function: magit-insert-modules-unpulled-from-upstream + + Insert sections for modules that haven’t been pulled from the + upstream yet. These sections can be expanded to show the + respective commits. + + -- Function: magit-insert-modules-unpulled-from-pushremote + + Insert sections for modules that haven’t been pulled from the + push-remote yet. These sections can be expanded to show the + respective commits. + + -- Function: magit-insert-modules-unpushed-to-upstream + + Insert sections for modules that haven’t been pushed to the + upstream yet. These sections can be expanded to show the + respective commits. + + -- Function: magit-insert-modules-unpushed-to-pushremote + + Insert sections for modules that haven’t been pushed to the + push-remote yet. These sections can be expanded to show the + respective commits. + + +File: magit.info, Node: Status Options, Prev: Status Module Sections, Up: Status Buffer + +5.1.4 Status Options +-------------------- + + -- User Option: magit-status-refresh-hook + + Hook run after a status buffer has been refreshed. + + -- User Option: magit-status-margin + + This option specifies whether the margin is initially shown in + Magit-Status mode buffers and how it is formatted. + + The value has the form ‘(INIT STYLE WIDTH AUTHOR AUTHOR-WIDTH)’. + + • If INIT is non-nil, then the margin is shown initially. + + • STYLE controls how to format the author or committer date. It + can be one of ‘age’ (to show the age of the commit), + ‘age-abbreviated’ (to abbreviate the time unit to a + character), or a string (suitable for ‘format-time-string’) to + show the actual date. Option + ‘magit-log-margin-show-committer-date’ controls which date is + being displayed. + + • WIDTH controls the width of the margin. This exists for + forward compatibility and currently the value should not be + changed. + + • AUTHOR controls whether the name of the author is also shown + by default. + + • AUTHOR-WIDTH has to be an integer. When the name of the + author is shown, then this specifies how much space is used to + do so. + + -- User Option: magit-log-section-args + + Additional Git arguments used when creating log sections. Only + ‘--graph’, ‘--decorate’, and ‘--show-signature’ are supported. + This option is only a temporary kludge and will be removed. + + Note that due to an issue in Git the use of ‘--graph’ is very slow + with long histories, so you probably don’t want to add this here. + + Also see the proceeding section for more options concerning status +buffers. + + +File: magit.info, Node: Repository List, Next: Logging, Prev: Status Buffer, Up: Inspecting + +5.2 Repository List +=================== + + -- Command: magit-list-repositories + + This command displays a list of repositories in a separate buffer. + + The options ‘magit-repository-directories’ and + ‘magit-repository-directories-depth’ control which repositories are + displayed. + + -- User Option: magit-repolist-columns + + This option controls what columns are displayed by the command + ‘magit-list-repositories’ and how they are displayed. + + Each element has the form ‘(HEADER WIDTH FORMAT PROPS)’. + + HEADER is the string displayed in the header. WIDTH is the width + of the column. FORMAT is a function that is called with one + argument, the repository identification (usually its basename), and + with ‘default-directory’ bound to the toplevel of its working tree. + It has to return a string to be inserted or nil. PROPS is an alist + that supports the keys ‘:right-align’ and ‘:pad-right’. + + The following functions can be added to the above option: + + -- Function: magit-repolist-column-ident + + This function inserts the identification of the repository. + Usually this is just its basename. + + -- Function: magit-repolist-column-path + + This function inserts the absolute path of the repository. + + -- Function: magit-repolist-column-version + + This function inserts a description of the repository’s ‘HEAD’ + revision. + + -- Function: magit-repolist-column-branch + + This function inserts the name of the current branch. + + -- Function: magit-repolist-column-upstream + + This function inserts the name of the upstream branch of the + current branch. + + -- Function: magit-repolist-column-branches + + This function inserts the number of branches. + + -- Function: magit-repolist-column-stashes + + This function inserts the number of stashes. + + -- Function: magit-repolist-column-flag + + This function inserts a flag as specified by + ‘magit-repolist-column-flag-alist’. + + By default this indicates whether there are uncommitted changes. + + • ‘N’ if there is at least one untracked file. + + • ‘U’ if there is at least one unstaged file. + + • ‘S’ if there is at least one staged file. + + Only the first one of these that applies is shown. + + -- Function: magit-repolist-column-unpulled-from-upstream + + This function inserts the number of upstream commits not in the + current branch. + + -- Function: magit-repolist-column-unpulled-from-pushremote + + This function inserts the number of commits in the push branch but + not the current branch. + + -- Function: magit-repolist-column-unpushed-to-upstream + + This function inserts the number of commits in the current branch + but not its upstream. + + -- Function: magit-repolist-column-unpushed-to-pushremote + + This function inserts the number of commits in the current branch + but not its push branch. + + +File: magit.info, Node: Logging, Next: Diffing, Prev: Repository List, Up: Inspecting + +5.3 Logging +=========== + +The status buffer contains logs for the unpushed and unpulled commits, +but that obviously isn’t enough. The transient prefix command +‘magit-log’, on ‘l’, features several suffix commands, which show a +specific log in a separate log buffer. + + Like other transient prefix commands, ‘magit-log’ also features +several infix arguments that can be changed before invoking one of the +suffix commands. However, in the case of the log transient, these +arguments may be taken from those currently in use in the current +repository’s log buffer, depending on the value of +‘magit-prefix-use-buffer-arguments’ (see *note Transient Arguments and +Buffer Variables::). + + For information about the various arguments, see *note +(gitman)git-log::. + + The switch ‘++order=VALUE’ is converted to one of +‘--author-date-order’, ‘--date-order’, or ‘--topo-order’ before being +passed to ‘git log’. + + The log transient also features several reflog commands. See *note +Reflog::. + +‘l’ (‘magit-log’) + + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. + +‘l l’ (‘magit-log-current’) + + Show log for the current branch. When ‘HEAD’ is detached or with a + prefix argument, show log for one or more revs read from the + minibuffer. + +‘l o’ (‘magit-log-other’) + + Show log for one or more revs read from the minibuffer. The user + can input any revision or revisions separated by a space, or even + ranges, but only branches, tags, and a representation of the commit + at point are available as completion candidates. + +‘l h’ (‘magit-log-head’) + + Show log for ‘HEAD’. + +‘l L’ (‘magit-log-branches’) + + Show log for all local branches and ‘HEAD’. + +‘l b’ (‘magit-log-all-branches’) + + Show log for all local and remote branches and ‘HEAD’. + +‘l a’ (‘magit-log-all’) + + Show log for all references and ‘HEAD’. + + Two additional commands that show the log for the file or blob that +is being visited in the current buffer exists, see *note Minor Mode for +Buffers Visiting Files::. The command ‘magit-cherry’ also shows a log, +see *note Cherries::. + +* Menu: + +* Refreshing Logs:: +* Log Buffer:: +* Log Margin:: +* Select from Log:: +* Reflog:: +* Cherries:: + + +File: magit.info, Node: Refreshing Logs, Next: Log Buffer, Up: Logging + +5.3.1 Refreshing Logs +--------------------- + +The transient prefix command ‘magit-log-refresh’, on ‘L’, can be used to +change the log arguments used in the current buffer, without changing +which log is shown. This works in dedicated log buffers, but also in +the status buffer. + +‘L’ (‘magit-log-refresh’) + + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. + +‘L g’ (‘magit-log-refresh’) + + This suffix command sets the local log arguments for the current + buffer. + +‘L s’ (‘magit-log-set-default-arguments’) + + This suffix command sets the default log arguments for buffers of + the same type as that of the current buffer. Other existing + buffers of the same type are not affected because their local + values have already been initialized. + +‘L w’ (‘magit-log-save-default-arguments’) + + This suffix command sets the default log arguments for buffers of + the same type as that of the current buffer, and saves the value + for future sessions. Other existing buffers of the same type are + not affected because their local values have already been + initialized. + +‘L t’ (‘magit-toggle-margin’) + + Show or hide the margin. + + +File: magit.info, Node: Log Buffer, Next: Log Margin, Prev: Refreshing Logs, Up: Logging + +5.3.2 Log Buffer +---------------- + +‘L’ (‘magit-log-refresh’) + + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. + + See *note Refreshing Logs::. + +‘q’ (‘magit-log-bury-buffer’) + + Bury the current buffer or the revision buffer in the same frame. + Like ‘magit-mode-bury-buffer’ (which see) but with a negative + prefix argument instead bury the revision buffer, provided it is + displayed in the current frame. + +‘C-c C-b’ (‘magit-go-backward’) + + Move backward in current buffer’s history. + +‘C-c C-f’ (‘magit-go-forward’) + + Move forward in current buffer’s history. + +‘C-c C-n’ (‘magit-log-move-to-parent’) + + Move to a parent of the current commit. By default, this is the + first parent, but a numeric prefix can be used to specify another + parent. + +‘SPC’ (‘magit-diff-show-or-scroll-up’) + + Update the commit or diff buffer for the thing at point. + + Either show the commit or stash at point in the appropriate buffer, + or if that buffer is already being displayed in the current frame + and contains information about that commit or stash, then instead + scroll the buffer up. If there is no commit or stash at point, + then prompt for a commit. + +‘DEL’ (‘magit-diff-show-or-scroll-down’) + + Update the commit or diff buffer for the thing at point. + + Either show the commit or stash at point in the appropriate buffer, + or if that buffer is already being displayed in the current frame + and contains information about that commit or stash, then instead + scroll the buffer down. If there is no commit or stash at point, + then prompt for a commit. + +‘=’ (‘magit-log-toggle-commit-limit’) + + Toggle the number of commits the current log buffer is limited to. + If the number of commits is currently limited, then remove that + limit. Otherwise set it to 256. + +‘+’ (‘magit-log-double-commit-limit’) + + Double the number of commits the current log buffer is limited to. + +‘-’ (‘magit-log-half-commit-limit’) + + Half the number of commits the current log buffer is limited to. + + -- User Option: magit-log-auto-more + + Insert more log entries automatically when moving past the last + entry. Only considered when moving past the last entry with + ‘magit-goto-*-section’ commands. + + -- User Option: magit-log-show-refname-after-summary + + Whether to show the refnames after the commit summaries. This is + useful if you use really long branch names. + + Magit displays references in logs a bit differently from how Git does +it. + + Local branches are blue and remote branches are green. Of course +that depends on the used theme, as do the colors used for other types of +references. The current branch has a box around it, as do remote +branches that are their respective remote’s ‘HEAD’ branch. + + If a local branch and its push-target point at the same commit, then +their names are combined to preserve space and to make that relationship +visible. For example: + + origin/feature + [green][blue-] + + instead of + + feature origin/feature + [blue-] [green-------] + + Also note that while the transient features the ‘--show-signature’ +argument, that won’t actually be used when enabled, because Magit +defaults to use just one line per commit. Instead the commit colorized +to indicate the validity of the signed commit object, using the faces +named ‘magit-signature-*’ (which see). + + For a description of ‘magit-log-margin’ see *note Log Margin::. + + +File: magit.info, Node: Log Margin, Next: Select from Log, Prev: Log Buffer, Up: Logging + +5.3.3 Log Margin +---------------- + +In buffers which show one or more logs, it is possible to show +additional information about each commit in the margin. The options +used to configure the margin are named ‘magit-INFIX-margin’, where INFIX +is the same as in the respective major-mode ‘magit-INFIX-mode’. In +regular log buffers that would be ‘magit-log-margin’. + + -- User Option: magit-log-margin + + This option specifies whether the margin is initially shown in + Magit-Log mode buffers and how it is formatted. + + The value has the form ‘(INIT STYLE WIDTH AUTHOR AUTHOR-WIDTH)’. + + • If INIT is non-nil, then the margin is shown initially. + + • STYLE controls how to format the author or committer date. It + can be one of ‘age’ (to show the age of the commit), + ‘age-abbreviated’ (to abbreviate the time unit to a + character), or a string (suitable for ‘format-time-string’) to + show the actual date. Option + ‘magit-log-margin-show-committer-date’ controls which date is + being displayed. + + • WIDTH controls the width of the margin. This exists for + forward compatibility and currently the value should not be + changed. + + • AUTHOR controls whether the name of the author is also shown + by default. + + • AUTHOR-WIDTH has to be an integer. When the name of the + author is shown, then this specifies how much space is used to + do so. + + You can change the STYLE and AUTHOR-WIDTH of all ‘magit-INFIX-margin’ +options to the same values by customizing ‘magit-log-margin’ *before* +‘magit’ is loaded. If you do that, then the respective values for the +other options will default to what you have set for that variable. +Likewise if you set INIT in ‘magit-log-margin’ to ‘nil’, then that is +used in the default of all other options. But setting it to ‘t’, i.e. +re-enforcing the default for that option, does not carry to other +options. + + -- User Option: magit-log-margin-show-committer-date + + This option specifies whether to show the committer date in the + margin. This option only controls whether the committer date is + displayed instead of the author date. Whether some date is + displayed in the margin and whether the margin is displayed at all + is controlled by other options. + +‘L’ (‘magit-margin-settings’) + + This transient prefix command binds the following suffix commands, + each of which changes the appearance of the margin in some way. + + In some buffers that support the margin, ‘L’ is instead bound to +‘magit-log-refresh’, but that transient features the same commands, and +then some other unrelated commands. + +‘L L’ (‘magit-toggle-margin’) + + This command shows or hides the margin. + +‘L l’ (‘magit-cycle-margin-style’) + + This command cycles the style used for the margin. + +‘L d’ (‘magit-toggle-margin-details’) + + This command shows or hides details in the margin. + + +File: magit.info, Node: Select from Log, Next: Reflog, Prev: Log Margin, Up: Logging + +5.3.4 Select from Log +--------------------- + +When the user has to select a recent commit that is reachable from +‘HEAD’, using regular completion would be inconvenient (because most +humans cannot remember hashes or "HEAD~5", at least not without double +checking). Instead a log buffer is used to select the commit, which has +the advantage that commits are presented in order and with the commit +message. + + Such selection logs are used when selecting the beginning of a rebase +and when selecting the commit to be squashed into. + + In addition to the key bindings available in all log buffers, the +following additional key bindings are available in selection log +buffers: + +‘C-c C-c’ (‘magit-log-select-pick’) + + Select the commit at point and act on it. Call + ‘magit-log-select-pick-function’ with the selected commit as + argument. + +‘C-c C-k’ (‘magit-log-select-quit’) + + Abort selecting a commit, don’t act on any commit. + + -- User Option: magit-log-select-margin + + This option specifies whether the margin is initially shown in + Magit-Log-Select mode buffers and how it is formatted. + + The value has the form ‘(INIT STYLE WIDTH AUTHOR AUTHOR-WIDTH)’. + + • If INIT is non-nil, then the margin is shown initially. + + • STYLE controls how to format the author or committer date. It + can be one of ‘age’ (to show the age of the commit), + ‘age-abbreviated’ (to abbreviate the time unit to a + character), or a string (suitable for ‘format-time-string’) to + show the actual date. Option + ‘magit-log-margin-show-committer-date’ controls which date is + being displayed. + + • WIDTH controls the width of the margin. This exists for + forward compatibility and currently the value should not be + changed. + + • AUTHOR controls whether the name of the author is also shown + by default. + + • AUTHOR-WIDTH has to be an integer. When the name of the + author is shown, then this specifies how much space is used to + do so. + + +File: magit.info, Node: Reflog, Next: Cherries, Prev: Select from Log, Up: Logging + +5.3.5 Reflog +------------ + +Also see *note (gitman)git-reflog::. + + These reflog commands are available from the log transient. See +*note Logging::. + +‘l r’ (‘magit-reflog-current’) + + Display the reflog of the current branch. + +‘l O’ (‘magit-reflog-other’) + + Display the reflog of a branch or another ref. + +‘l H’ (‘magit-reflog-head’) + + Display the ‘HEAD’ reflog. + + -- User Option: magit-reflog-margin + + This option specifies whether the margin is initially shown in + Magit-Reflog mode buffers and how it is formatted. + + The value has the form ‘(INIT STYLE WIDTH AUTHOR AUTHOR-WIDTH)’. + + • If INIT is non-nil, then the margin is shown initially. + + • STYLE controls how to format the author or committer date. It + can be one of ‘age’ (to show the age of the commit), + ‘age-abbreviated’ (to abbreviate the time unit to a + character), or a string (suitable for ‘format-time-string’) to + show the actual date. Option + ‘magit-log-margin-show-committer-date’ controls which date is + being displayed. + + • WIDTH controls the width of the margin. This exists for + forward compatibility and currently the value should not be + changed. + + • AUTHOR controls whether the name of the author is also shown + by default. + + • AUTHOR-WIDTH has to be an integer. When the name of the + author is shown, then this specifies how much space is used to + do so. + + +File: magit.info, Node: Cherries, Prev: Reflog, Up: Logging + +5.3.6 Cherries +-------------- + +Cherries are commits that haven’t been applied upstream (yet), and are +usually visualized using a log. Each commit is prefixed with ‘-’ if it +has an equivalent in the upstream and ‘+’ if it does not, i.e. if it is +a cherry. + + The command ‘magit-cherry’ shows cherries for a single branch, but +the references buffer (see *note References Buffer::) can show cherries +for multiple "upstreams" at once. + + Also see *note (gitman)git-reflog::. + +‘Y’ (‘magit-cherry’) + + Show commits that are in a certain branch but that have not been + merged in the upstream branch. + + -- User Option: magit-cherry-margin + + This option specifies whether the margin is initially shown in + Magit-Cherry mode buffers and how it is formatted. + + The value has the form ‘(INIT STYLE WIDTH AUTHOR AUTHOR-WIDTH)’. + + • If INIT is non-nil, then the margin is shown initially. + + • STYLE controls how to format the author or committer date. It + can be one of ‘age’ (to show the age of the commit), + ‘age-abbreviated’ (to abbreviate the time unit to a + character), or a string (suitable for ‘format-time-string’) to + show the actual date. Option + ‘magit-log-margin-show-committer-date’ controls which date is + being displayed. + + • WIDTH controls the width of the margin. This exists for + forward compatibility and currently the value should not be + changed. + + • AUTHOR controls whether the name of the author is also shown + by default. + + • AUTHOR-WIDTH has to be an integer. When the name of the + author is shown, then this specifies how much space is used to + do so. + + +File: magit.info, Node: Diffing, Next: Ediffing, Prev: Logging, Up: Inspecting + +5.4 Diffing +=========== + +The status buffer contains diffs for the staged and unstaged commits, +but that obviously isn’t enough. The transient prefix command +‘magit-diff’, on ‘d’, features several suffix commands, which show a +specific diff in a separate diff buffer. + + Like other transient prefix commands, ‘magit-diff’ also features +several infix arguments that can be changed before invoking one of the +suffix commands. However, in the case of the diff transient, these +arguments may be taken from those currently in use in the current +repository’s diff buffer, depending on the value of +‘magit-prefix-use-buffer-arguments’ (see *note Transient Arguments and +Buffer Variables::). + + Also see *note (gitman)git-diff::. + +‘d’ (‘magit-diff’) + + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. + +‘d d’ (‘magit-diff-dwim’) + + Show changes for the thing at point. + +‘d r’ (‘magit-diff-range’) + + Show differences between two commits. + + RANGE should be a range (A..B or A...B) but can also be a single + commit. If one side of the range is omitted, then it defaults to + ‘HEAD’. If just a commit is given, then changes in the working + tree relative to that commit are shown. + + If the region is active, use the revisions on the first and last + line of the region. With a prefix argument, instead of diffing the + revisions, choose a revision to view changes along, starting at the + common ancestor of both revisions (i.e., use a "..." range). + +‘d w’ (‘magit-diff-working-tree’) + + Show changes between the current working tree and the ‘HEAD’ + commit. With a prefix argument show changes between the working + tree and a commit read from the minibuffer. + +‘d s’ (‘magit-diff-staged’) + + Show changes between the index and the ‘HEAD’ commit. With a + prefix argument show changes between the index and a commit read + from the minibuffer. + +‘d u’ (‘magit-diff-unstaged’) + + Show changes between the working tree and the index. + +‘d p’ (‘magit-diff-paths’) + + Show changes between any two files on disk. + + All of the above suffix commands update the repository’s diff buffer. +The diff transient also features two commands which show differences in +another buffer: + +‘d c’ (‘magit-show-commit’) + + Show the commit at point. If there is no commit at point or with a + prefix argument, prompt for a commit. + +‘d t’ (‘magit-stash-show’) + + Show all diffs of a stash in a buffer. + + Two additional commands that show the diff for the file or blob that +is being visited in the current buffer exists, see *note Minor Mode for +Buffers Visiting Files::. + +* Menu: + +* Refreshing Diffs:: +* Commands Available in Diffs:: +* Diff Options:: +* Revision Buffer:: + + +File: magit.info, Node: Refreshing Diffs, Next: Commands Available in Diffs, Up: Diffing + +5.4.1 Refreshing Diffs +---------------------- + +The transient prefix command ‘magit-diff-refresh’, on ‘D’, can be used +to change the diff arguments used in the current buffer, without +changing which diff is shown. This works in dedicated diff buffers, but +also in the status buffer. + +‘D’ (‘magit-diff-refresh’) + + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. + +‘D g’ (‘magit-diff-refresh’) + + This suffix command sets the local diff arguments for the current + buffer. + +‘D s’ (‘magit-diff-set-default-arguments’) + + This suffix command sets the default diff arguments for buffers of + the same type as that of the current buffer. Other existing + buffers of the same type are not affected because their local + values have already been initialized. + +‘D w’ (‘magit-diff-save-default-arguments’) + + This suffix command sets the default diff arguments for buffers of + the same type as that of the current buffer, and saves the value + for future sessions. Other existing buffers of the same type are + not affected because their local values have already been + initialized. + +‘D t’ (‘magit-diff-toggle-refine-hunk’) + + This command toggles hunk refinement on or off. + +‘D r’ (‘magit-diff-switch-range-type’) + + This command converts the diff range type from "revA..revB" to + "revB...revA", or vice versa. + +‘D f’ (‘magit-diff-flip-revs’) + + This command swaps revisions in the diff range from "revA..revB" to + "revB..revA", or vice versa. + +‘D F’ (‘magit-diff-toggle-file-filter’) + + This command toggles the file restriction of the diffs in the + current buffer, allowing you to quickly switch between viewing all + the changes in the commit and the restricted subset. As a special + case, when this command is called from a log buffer, it toggles the + file restriction in the repository’s revision buffer, which is + useful when you display a revision from a log buffer that is + restricted to a file or files. + + In addition to the above transient, which allows changing any of the +supported arguments, there also exist some commands that change only a +particular argument. + +‘-’ (‘magit-diff-less-context’) + + This command decreases the context for diff hunks by COUNT lines. + +‘+’ (‘magit-diff-more-context’) + + This command increases the context for diff hunks by COUNT lines. + +‘0’ (‘magit-diff-default-context’) + + This command resets the context for diff hunks to the default + height. + + The following commands quickly change what diff is being displayed +without having to using one of the diff transient. + +‘C-c C-d’ (‘magit-diff-while-committing’) + + While committing, this command shows the changes that are about to + be committed. While amending, invoking the command again toggles + between showing just the new changes or all the changes that will + be committed. + + This binding is available in the diff buffer as well as the commit + message buffer. + +‘C-c C-b’ (‘magit-go-backward’) + + This command moves backward in current buffer’s history. + +‘C-c C-f’ (‘magit-go-forward’) + + This command moves forward in current buffer’s history. + + +File: magit.info, Node: Commands Available in Diffs, Next: Diff Options, Prev: Refreshing Diffs, Up: Diffing + +5.4.2 Commands Available in Diffs +--------------------------------- + +Some commands are only available if point is inside a diff. + + ‘magit-diff-visit-file’ and related commands visit the appropriate +version of the file that the diff at point is about. Likewise +‘magit-diff-visit-worktree-file’ and related commands visit the worktree +version of the file that the diff at point is about. See *note Visiting +Files and Blobs from a Diff:: for more information and the key bindings. + +‘C-c C-t’ (‘magit-diff-trace-definition’) + + This command shows a log for the definition at point. + + -- User Option: magit-log-trace-definition-function + + The function specified by this option is used by + ‘magit-log-trace-definition’ to determine the function at point. + For major-modes that have special needs, you could set the local + value using the mode’s hook. + +‘C-c C-e’ (‘magit-diff-edit-hunk-commit’) + + From a hunk, this command edits the respective commit and visits + the file. + + First it visits the file being modified by the hunk at the correct + location using ‘magit-diff-visit-file’. This actually visits a + blob. When point is on a diff header, not within an individual + hunk, then this visits the blob the first hunk is about. + + Then it invokes ‘magit-edit-line-commit’, which uses an interactive + rebase to make the commit editable, or if that is not possible + because the commit is not reachable from ‘HEAD’ by checking out + that commit directly. This also causes the actual worktree file to + be visited. + + Neither the blob nor the file buffer are killed when finishing the + rebase. If that is undesirable, then it might be better to use + ‘magit-rebase-edit-command’ instead of this command. + +‘j’ (‘magit-jump-to-diffstat-or-diff’) + + This command jumps to the diffstat or diff. When point is on a + file inside the diffstat section, then jump to the respective diff + section. Otherwise, jump to the diffstat section or a child + thereof. + + The next two commands are not specific to Magit-Diff mode (or and +Magit buffer for that matter), but it might be worth pointing out that +they are available here too. + +‘SPC’ (‘scroll-up’) + + This command scrolls text upward. + +‘DEL’ (‘scroll-down’) + + This command scrolls text downward. + + +File: magit.info, Node: Diff Options, Next: Revision Buffer, Prev: Commands Available in Diffs, Up: Diffing + +5.4.3 Diff Options +------------------ + + -- User Option: magit-diff-refine-hunk + + Whether to show word-granularity differences within diff hunks. + + • ‘nil’ Never show fine differences. + + • ‘t’ Show fine differences for the current diff hunk only. + + • ‘all’ Show fine differences for all displayed diff hunks. + + -- User Option: magit-diff-refine-ignore-whitespace + + Whether to ignore whitespace changes in word-granularity + differences. + + -- User Option: magit-diff-adjust-tab-width + + Whether to adjust the width of tabs in diffs. + + Determining the correct width can be expensive if it requires + opening large and/or many files, so the widths are cached in the + variable ‘magit-diff--tab-width-cache’. Set that to nil to + invalidate the cache. + + • ‘nil’ Never adjust tab width. Use ‘tab-width’s value from the + Magit buffer itself instead. + + • ‘t’ If the corresponding file-visiting buffer exits, then use + ‘tab-width’’s value from that buffer. Doing this is cheap, so + this value is used even if a corresponding cache entry exists. + + • ‘always’ If there is no such buffer, then temporarily visit + the file to determine the value. + + • NUMBER Like ‘always’, but don’t visit files larger than NUMBER + bytes. + + -- User Option: magit-diff-paint-whitespace + + Specify where to highlight whitespace errors. + + See ‘magit-diff-highlight-trailing’, + ‘magit-diff-highlight-indentation’. The symbol ‘t’ means in all + diffs, ‘status’ means only in the status buffer, and nil means + nowhere. + + • ‘nil’ Never highlight whitespace errors. + + • ‘t’ Highlight whitespace errors everywhere. + + • ‘uncommitted’ Only highlight whitespace errors in diffs + showing uncommitted changes. For backward compatibility + ‘status’ is treated as a synonym. + + -- User Option: magit-diff-paint-whitespace-lines + + Specify in what kind of lines to highlight whitespace errors. + + • ‘t’ Highlight only in added lines. + + • ‘both’ Highlight in added and removed lines. + + • ‘all’ Highlight in added, removed and context lines. + + -- User Option: magit-diff-highlight-trailing + + Whether to highlight whitespace at the end of a line in diffs. + Used only when ‘magit-diff-paint-whitespace’ is non-nil. + + -- User Option: magit-diff-highlight-indentation + + This option controls whether to highlight the indentation in case + it used the "wrong" indentation style. Indentation is only + highlighted if ‘magit-diff-paint-whitespace’ is also non-nil. + + The value is an alist of the form ‘((REGEXP . INDENT)...)’. The + path to the current repository is matched against each element in + reverse order. Therefore if a REGEXP matches, then earlier + elements are not tried. + + If the used INDENT is ‘tabs’, highlight indentation with tabs. If + INDENT is an integer, highlight indentation with at least that many + spaces. Otherwise, highlight neither. + + -- User Option: magit-diff-hide-trailing-cr-characters + + Whether to hide ^M characters at the end of a line in diffs. + + -- User Option: magit-diff-highlight-hunk-region-functions + + This option specifies the functions used to highlight the + hunk-internal region. + + ‘magit-diff-highlight-hunk-region-dim-outside’ overlays the outside + of the hunk internal selection with a face that causes the added + and removed lines to have the same background color as context + lines. This function should not be removed from the value of this + option. + + ‘magit-diff-highlight-hunk-region-using-overlays’ and + ‘magit-diff-highlight-hunk-region-using-underline’ emphasize the + region by placing delimiting horizontal lines before and after it. + Both of these functions have glitches which cannot be fixed due to + limitations of Emacs’ display engine. For more information see + ff. + + Instead of, or in addition to, using delimiting horizontal lines, + to emphasize the boundaries, you may which to emphasize the text + itself, using ‘magit-diff-highlight-hunk-region-using-face’. + + In terminal frames it’s not possible to draw lines as the overlay + and underline variants normally do, so there they fall back to + calling the face function instead. + + -- User Option: magit-diff-unmarked-lines-keep-foreground + + This option controls whether added and removed lines outside the + hunk-internal region only lose their distinct background color or + also the foreground color. Whether the outside of the region is + dimmed at all depends on + ‘magit-diff-highlight-hunk-region-functions’. + + +File: magit.info, Node: Revision Buffer, Prev: Diff Options, Up: Diffing + +5.4.4 Revision Buffer +--------------------- + + -- User Option: magit-revision-insert-related-refs + + Whether to show related branches in revision buffers. + + • ‘nil’ Don’t show any related branches. + + • ‘t’ Show related local branches. + + • ‘all’ Show related local and remote branches. + + • ‘mixed’ Show all containing branches and local merged + branches. + + -- User Option: magit-revision-show-gravatars + + Whether to show gravatar images in revision buffers. + + If ‘nil’, then don’t insert any gravatar images. If ‘t’, then + insert both images. If ‘author’ or ‘committer’, then insert only + the respective image. + + If you have customized the option ‘magit-revision-headers-format’ + and want to insert the images then you might also have to specify + where to do so. In that case the value has to be a cons-cell of + two regular expressions. The car specifies where to insert the + author’s image. The top half of the image is inserted right after + the matched text, the bottom half on the next line in the same + column. The cdr specifies where to insert the committer’s image, + accordingly. Either the car or the cdr may be nil." + + -- User Option: magit-revision-use-hash-sections + + Whether to turn hashes inside the commit message into sections. + + If non-nil, then hashes inside the commit message are turned into + ‘commit’ sections. There is a trade off to be made between + performance and reliability: + + • ‘slow’ calls git for every word to be absolutely sure. + + • ‘quick’ skips words less than seven characters long. + + • ‘quicker’ additionally skips words that don’t contain a + number. + + • ‘quickest’ uses all words that are at least seven characters + long and which contain at least one number as well as at least + one letter. + + If nil, then no hashes are turned into sections, but you can still + visit the commit at point using "RET". + + The diffs shown in the revision buffer may be automatically +restricted to a subset of the changed files. If the revision buffer is +displayed from a log buffer, the revision buffer will share the same +file restriction as that log buffer (also see the command +‘magit-diff-toggle-file-filter’). + + -- User Option: magit-revision-filter-files-on-follow + + Whether showing a commit from a log buffer honors the log’s file + filter when the log arguments include ‘--follow’. + + When this option is nil, displaying a commit from a log ignores the + log’s file filter if the log arguments include ‘--follow’. Doing + so avoids showing an empty diff in revision buffers for commits + before a rename event. In such cases, the ‘--patch’ argument of + the log transient can be used to show the file-restricted diffs + inline. + + Set this option to non-nil to keep the log’s file restriction even + if ‘--follow’ is present in the log arguments. + + If the revision buffer is not displayed from a log buffer, the file +restriction is determined as usual (see *note Transient Arguments and +Buffer Variables::). + + +File: magit.info, Node: Ediffing, Next: References Buffer, Prev: Diffing, Up: Inspecting + +5.5 Ediffing +============ + +This section describes how to enter Ediff from Magit buffers. For +information on how to use Ediff itself, see *note (ediff)Top::. + +‘e’ (‘magit-ediff-dwim’) + + Compare, stage, or resolve using Ediff. + + This command tries to guess what file, and what commit or range the + user wants to compare, stage, or resolve using Ediff. It might + only be able to guess either the file, or range/commit, in which + case the user is asked about the other. It might not always guess + right, in which case the appropriate ‘magit-ediff-*’ command has to + be used explicitly. If it cannot read the user’s mind at all, then + it asks the user for a command to run. + +‘E’ (‘magit-ediff’) + + This transient prefix command binds the following suffix commands + and displays them in a temporary buffer until a suffix is invoked. + +‘E r’ (‘magit-ediff-compare’) + + Compare two revisions of a file using Ediff. + + If the region is active, use the revisions on the first and last + line of the region. With a prefix argument, instead of diffing the + revisions, choose a revision to view changes along, starting at the + common ancestor of both revisions (i.e., use a "..." range). + +‘E m’ (‘magit-ediff-resolve’) + + Resolve outstanding conflicts in a file using Ediff, defaulting to + the file at point. + + Provided that the value of ‘merge.conflictstyle’ is ‘diff3’, you + can view the file’s merge-base revision using ‘/’ in the Ediff + control buffer. + + In the rare event that you want to manually resolve all conflicts, + including those already resolved by Git, use + ‘ediff-merge-revisions-with-ancestor’. + +‘E s’ (‘magit-ediff-stage’) + + Stage and unstage changes to a file using Ediff, defaulting to the + file at point. + +‘E u’ (‘magit-ediff-show-unstaged’) + + Show unstaged changes to a file using Ediff. + +‘E i’ (‘magit-ediff-show-staged’) + + Show staged changes to a file using Ediff. + +‘E w’ (‘magit-ediff-show-working-tree’) + + Show changes in a file between ‘HEAD’ and working tree using Ediff. + +‘E c’ (‘magit-ediff-show-commit’) + + Show changes to a file introduced by a commit using Ediff. + +‘E z’ (‘magit-ediff-show-stash’) + + Show changes to a file introduced by a stash using Ediff. + + -- User Option: magit-ediff-dwim-show-on-hunks + + This option controls what command ‘magit-ediff-dwim’ calls when + point is on uncommitted hunks. When nil, always run + ‘magit-ediff-stage’. Otherwise, use ‘magit-ediff-show-staged’ and + ‘magit-ediff-show-unstaged’ to show staged and unstaged changes, + respectively. + + -- User Option: magit-ediff-show-stash-with-index + + This option controls whether ‘magit-ediff-show-stash’ includes a + buffer containing the file’s state in the index at the time the + stash was created. This makes it possible to tell which changes in + the stash were staged. + + -- User Option: magit-ediff-quit-hook + + This hook is run after quitting an Ediff session that was created + using a Magit command. The hook functions are run inside the Ediff + control buffer, and should not change the current buffer. + + This is similar to ‘ediff-quit-hook’ but takes the needs of Magit + into account. The regular ‘ediff-quit-hook’ is ignored by Ediff + sessions that were created using a Magit command. + + +File: magit.info, Node: References Buffer, Next: Bisecting, Prev: Ediffing, Up: Inspecting + +5.6 References Buffer +===================== + +‘y’ (‘magit-show-refs’) + + This command lists branches and tags in a dedicated buffer. + + However if this command is invoked again from this buffer or if it + is invoked with a prefix argument, then it acts as a transient + prefix command, which binds the following suffix commands and some + infix arguments. + + All of the following suffix commands list exactly the same branches +and tags. The only difference the optional feature that can be enabled +by changing the value of ‘magit-refs-show-commit-count’ (see below). +These commands specify a different branch or commit against which all +the other references are compared. + +‘y y’ (‘magit-show-refs-head’) + + This command lists branches and tags in a dedicated buffer. Each + reference is being compared with ‘HEAD’. + +‘y c’ (‘magit-show-refs-current’) + + This command lists branches and tags in a dedicated buffer. Each + reference is being compared with the current branch or ‘HEAD’ if it + is detached. + +‘y o’ (‘magit-show-refs-other’) + + This command lists branches and tags in a dedicated buffer. Each + reference is being compared with a branch read from the user. + + -- User Option: magit-refs-show-commit-count + + Whether to show commit counts in Magit-Refs mode buffers. + + • ‘all’ Show counts for branches and tags. + + • ‘branch’ Show counts for branches only. + + • ‘nil’ Never show counts. + + The default is ‘nil’ because anything else can be very expensive. + + -- User Option: magit-refs-pad-commit-counts + + Whether to pad all commit counts on all sides in Magit-Refs mode + buffers. + + If this is nil, then some commit counts are displayed right next to + one of the branches that appear next to the count, without any + space in between. This might look bad if the branch name faces + look too similar to ‘magit-dimmed’. + + If this is non-nil, then spaces are placed on both sides of all + commit counts. + + -- User Option: magit-refs-show-remote-prefix + + Whether to show the remote prefix in lists of remote branches. + + Showing the prefix is redundant because the name of the remote is + already shown in the heading preceding the list of its branches. + + -- User Option: magit-refs-primary-column-width + + Width of the primary column in ‘magit-refs-mode’ buffers. The + primary column is the column that contains the name of the branch + that the current row is about. + + If this is an integer, then the column is that many columns wide. + Otherwise it has to be a cons-cell of two integers. The first + specifies the minimal width, the second the maximal width. In that + case the actual width is determined using the length of the names + of the shown local branches. (Remote branches and tags are not + taken into account when calculating to optimal width.) + + -- User Option: magit-refs-focus-column-width + + Width of the focus column in ‘magit-refs-mode’ buffers. + + The focus column is the first column, which marks one branch + (usually the current branch) as the focused branch using ‘*’ or + ‘@’. For each other reference, this column optionally shows how + many commits it is ahead of the focused branch and ‘<’, or if it + isn’t ahead then the commits it is behind and ‘>’, or if it isn’t + behind either, then a ‘=’. + + This column may also display only ‘*’ or ‘@’ for the focused + branch, in which case this option is ignored. Use ‘L v’ to change + the verbosity of this column. + + -- User Option: magit-refs-margin + + This option specifies whether the margin is initially shown in + Magit-Refs mode buffers and how it is formatted. + + The value has the form ‘(INIT STYLE WIDTH AUTHOR AUTHOR-WIDTH)’. + + • If INIT is non-nil, then the margin is shown initially. + + • STYLE controls how to format the author or committer date. It + can be one of ‘age’ (to show the age of the commit), + ‘age-abbreviated’ (to abbreviate the time unit to a + character), or a string (suitable for ‘format-time-string’) to + show the actual date. Option + ‘magit-log-margin-show-committer-date’ controls which date is + being displayed. + + • WIDTH controls the width of the margin. This exists for + forward compatibility and currently the value should not be + changed. + + • AUTHOR controls whether the name of the author is also shown + by default. + + • AUTHOR-WIDTH has to be an integer. When the name of the + author is shown, then this specifies how much space is used to + do so. + + -- User Option: magit-refs-margin-for-tags + + This option specifies whether to show information about tags in the + margin. This is disabled by default because it is slow if there + are many tags. + + The following variables control how individual refs are displayed. +If you change one of these variables (especially the "%c" part), then +you should also change the others to keep things aligned. The following +%-sequences are supported: + + • ‘%a’ Number of commits this ref has over the one we compare to. + + • ‘%b’ Number of commits the ref we compare to has over this one. + + • ‘%c’ Number of commits this ref has over the one we compare to. + For the ref which all other refs are compared this is instead "@", + if it is the current branch, or "#" otherwise. + + • ‘%C’ For the ref which all other refs are compared this is "@", if + it is the current branch, or "#" otherwise. For all other refs " + ". + + • ‘%h’ Hash of this ref’s tip. + + • ‘%m’ Commit summary of the tip of this ref. + + • ‘%n’ Name of this ref. + + • ‘%u’ Upstream of this local branch. + + • ‘%U’ Upstream of this local branch and additional local vs. + upstream information. + + -- User Option: magit-refs-filter-alist + + The purpose of this option is to forgo displaying certain refs + based on their name. If you want to not display any refs of a + certain type, then you should remove the appropriate function from + ‘magit-refs-sections-hook’ instead. + + This alist controls which tags and branches are omitted from being + displayed in ‘magit-refs-mode’ buffers. If it is ‘nil’, then all + refs are displayed (subject to ‘magit-refs-sections-hook’). + + All keys are tried in order until one matches. Then its value is + used and subsequent elements are ignored. If the value is non-nil, + then the reference is displayed, otherwise it is not. If no + element matches, then the reference is displayed. + + A key can either be a regular expression that the refname has to + match, or a function that takes the refname as only argument and + returns a boolean. A remote branch such as "origin/master" is + displayed as just "master", however for this comparison the former + is used. + +‘RET’ (‘magit-visit-ref’) + + This command visits the reference or revision at point in another + buffer. If there is no revision at point or with a prefix argument + then it prompts for a revision. + + This command behaves just like ‘magit-show-commit’ as described + above, except if point is on a reference in a ‘magit-refs-mode’ + buffer, in which case the behavior may be different, but only if + you have customized the option ‘magit-visit-ref-behavior’. + + -- User Option: magit-visit-ref-behavior + + This option controls how ‘magit-visit-ref’ behaves in + ‘magit-refs-mode’ buffers. + + By default ‘magit-visit-ref’ behaves like ‘magit-show-commit’, in + all buffers, including ‘magit-refs-mode’ buffers. When the type of + the section at point is ‘commit’ then "RET" is bound to + ‘magit-show-commit’, and when the type is either ‘branch’ or ‘tag’ + then it is bound to ‘magit-visit-ref’. + + "RET" is one of Magit’s most essential keys and at least by default + it should behave consistently across all of Magit, especially + because users quickly learn that it does something very harmless; + it shows more information about the thing at point in another + buffer. + + However "RET" used to behave differently in ‘magit-refs-mode’ + buffers, doing surprising things, some of which cannot really be + described as "visit this thing". If you’ve grown accustomed this + behavior, you can restore it by adding one or more of the below + symbols to the value of this option. But keep in mind that by + doing so you don’t only introduce inconsistencies, you also lose + some functionality and might have to resort to ‘M-x + magit-show-commit’ to get it back. + + ‘magit-visit-ref’ looks for these symbols in the order in which + they are described here. If the presence of a symbol applies to + the current situation, then the symbols that follow do not affect + the outcome. + + • ‘focus-on-ref’ + + With a prefix argument update the buffer to show commit counts + and lists of cherry commits relative to the reference at point + instead of relative to the current buffer or ‘HEAD’. + + Instead of adding this symbol, consider pressing "C-u y o + RET". + + • ‘create-branch’ + + If point is on a remote branch, then create a new local branch + with the same name, use the remote branch as its upstream, and + then check out the local branch. + + Instead of adding this symbol, consider pressing "b c RET + RET", like you would do in other buffers. + + • ‘checkout-any’ + + Check out the reference at point. If that reference is a tag + or a remote branch, then this results in a detached ‘HEAD’. + + Instead of adding this symbol, consider pressing "b b RET", + like you would do in other buffers. + + • ‘checkout-branch’ + + Check out the local branch at point. + + Instead of adding this symbol, consider pressing "b b RET", + like you would do in other buffers. + +* Menu: + +* References Sections:: + + +File: magit.info, Node: References Sections, Up: References Buffer + +5.6.1 References Sections +------------------------- + +The contents of references buffers is controlled using the hook +‘magit-refs-sections-hook’. See *note Section Hooks:: to learn about +such hooks and how to customize them. All of the below functions are +members of the default value. Note that it makes much less sense to +customize this hook than it does for the respective hook used for the +status buffer. + + -- User Option: magit-refs-sections-hook + + Hook run to insert sections into a references buffer. + + -- Function: magit-insert-local-branches + + Insert sections showing all local branches. + + -- Function: magit-insert-remote-branches + + Insert sections showing all remote-tracking branches. + + -- Function: magit-insert-tags + + Insert sections showing all tags. + + +File: magit.info, Node: Bisecting, Next: Visiting Files and Blobs, Prev: References Buffer, Up: Inspecting + +5.7 Bisecting +============= + +Also see *note (gitman)git-bisect::. + +‘B’ (‘magit-bisect’) + + This transient prefix command binds the following suffix commands + and displays them in a temporary buffer until a suffix is invoked. + + When bisecting is not in progress, then the transient features the +following suffix commands. + +‘B B’ (‘magit-bisect-start’) + + Start a bisect session. + + Bisecting a bug means to find the commit that introduced it. This + command starts such a bisect session by asking for a known good and + a bad commit. + +‘B s’ (‘magit-bisect-run’) + + Bisect automatically by running commands after each step. + + When bisecting in progress, then the transient instead features the +following suffix commands. + +‘B b’ (‘magit-bisect-bad’) + + Mark the current commit as bad. Use this after you have asserted + that the commit does contain the bug in question. + +‘B g’ (‘magit-bisect-good’) + + Mark the current commit as good. Use this after you have asserted + that the commit does not contain the bug in question. + +‘B k’ (‘magit-bisect-skip’) + + Skip the current commit. Use this if for some reason the current + commit is not a good one to test. This command lets Git choose a + different one. + +‘B r’ (‘magit-bisect-reset’) + + After bisecting, cleanup bisection state and return to original + ‘HEAD’. + + By default the status buffer shows information about the ongoing +bisect session. + + -- User Option: magit-bisect-show-graph + + This option controls whether a graph is displayed for the log of + commits that still have to be bisected. + + +File: magit.info, Node: Visiting Files and Blobs, Next: Blaming, Prev: Bisecting, Up: Inspecting + +5.8 Visiting Files and Blobs +============================ + +Magit provides several commands that visit a file or blob (the version +of a file that is stored in a certain commit). Actually it provides +several *groups* of such commands and the several *variants* within each +group. + +* Menu: + +* General-Purpose Visit Commands:: +* Visiting Files and Blobs from a Diff:: + + +File: magit.info, Node: General-Purpose Visit Commands, Next: Visiting Files and Blobs from a Diff, Up: Visiting Files and Blobs + +5.8.1 General-Purpose Visit Commands +------------------------------------ + +These commands can be used anywhere to open any blob. Currently no keys +are bound to these commands by default, but that is likely to change. + + -- Command: magit-find-file + + This command reads a filename and revision from the user and visits + the respective blob in a buffer. The buffer is displayed in the + selected window. + + -- Command: magit-find-file-other-window + + This command reads a filename and revision from the user and visits + the respective blob in a buffer. The buffer is displayed in + another window. + + -- Command: magit-find-file-other-frame + + This command reads a filename and revision from the user and visits + the respective blob in a buffer. The buffer is displayed in + another frame. + + +File: magit.info, Node: Visiting Files and Blobs from a Diff, Prev: General-Purpose Visit Commands, Up: Visiting Files and Blobs + +5.8.2 Visiting Files and Blobs from a Diff +------------------------------------------ + +These commands can only be used when point is inside a diff. + +‘RET’ (‘magit-diff-visit-file’) + + This command visits the appropriate version of the file that the + diff at point is about. + + This commands visits the worktree version of the appropriate file. + The location of point inside the diff determines which file is + being visited. The visited version depends on what changes the + diff is about. + + • If the diff shows uncommitted changes (i.e. staged or + unstaged changes), then visit the file in the working tree + (i.e. the same "real" file that ‘find-file’ would visit. In + all other cases visit a "blob" (i.e. the version of a file as + stored in some commit). + + • If point is on a removed line, then visit the blob for the + first parent of the commit that removed that line, i.e. the + last commit where that line still exists. + + • If point is on an added or context line, then visit the blob + that adds that line, or if the diff shows from more than a + single commit, then visit the blob from the last of these + commits. + + In the file-visiting buffer this command goes to the line that + corresponds to the line that point is on in the diff. + + The buffer is displayed in the selected window. With a prefix + argument the buffer is displayed in another window instead. + + -- User Option: magit-diff-visit-previous-blob + + This option controls whether ‘magit-diff-visit-file’ may visit the + previous blob. When this is ‘t’ (the default) and point is on a + removed line in a diff for a committed change, then + ‘magit-diff-visit-file’ visits the blob from the last revision + which still had that line. + + Currently this is only supported for committed changes, for staged + and unstaged changes ‘magit-diff-visit-file’ always visits the file + in the working tree. + +‘C-’ (‘magit-diff-visit-file-worktree’) + + This command visits the worktree version of the appropriate file. + The location of point inside the diff determines which file is + being visited. Unlike ‘magit-diff-visit-file’ it always visits the + "real" file in the working tree, i.e the "current version" of the + file. + + In the file-visiting buffer this command goes to the line that + corresponds to the line that point is on in the diff. Lines that + were added or removed in the working tree, the index and other + commits in between are automatically accounted for. + + The buffer is displayed in the selected window. With a prefix + argument the buffer is displayed in another window instead. + + Variants of the above two commands exist that instead visit the file +in another window or in another frame. If you prefer such behavior, +then you may want to change the above key bindings, but note that the +above commands also use another window when invoked with a prefix +argument. + + -- Command: magit-diff-visit-file-other-window + -- Command: magit-diff-visit-file-other-frame + -- Command: magit-diff-visit-worktree-file-other-window + -- Command: magit-diff-visit-worktree-file-other-frame + + +File: magit.info, Node: Blaming, Prev: Visiting Files and Blobs, Up: Inspecting + +5.9 Blaming +=========== + +Also see *note (gitman)git-blame::. + + To start blaming invoke the ‘magit-file-dispatch’ transient prefix +command by pressing ‘C-c M-g’. (This is only the default binding and +the recommended binding is ‘C-c g’. Also neither binding may be +available if you disabled ‘global-magit-file-mode’. Also see *note +Minor Mode for Buffers Visiting Files::.) + + The blaming suffix commands can be invoked from the dispatch +transient. However if you want to set an infix argument, then you have +to enter the blaming sub-transient first. + + The key bindings shown below assume that you enter the dispatch +transient using the default binding. + +‘C-c M-g B’ (‘magit-blame’) + + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. + + Note that not all of the following suffixes are available at all +times. For example if ‘magit-blame-mode’ is not enabled, then the +command whose purpose is to turn off that mode would not be of any use +and therefore isn’t available. + +‘C-c M-g b’ (‘magit-blame-addition’) +‘C-c M-g B b’ (‘magit-blame-addition’) + + This command augments each line or chunk of lines in the current + file-visiting or blob-visiting buffer with information about what + commits last touched these lines. + + If the buffer visits a revision of that file, then history up to + that revision is considered. Otherwise, the file’s full history is + considered, including uncommitted changes. + + If Magit-Blame mode is already turned on in the current buffer then + blaming is done recursively, by visiting REVISION:FILE (using + ‘magit-find-file’), where REVISION is a parent of the revision that + added the current line or chunk of lines. + +‘C-c M-g r’ (‘magit-blame-removal’) +‘C-c M-g B r’ (‘magit-blame-removal’) + + This command augments each line or chunk of lines in the current + blob-visiting buffer with information about the revision that + removes it. It cannot be used in file-visiting buffers. + + Like ‘magit-blame-addition’, this command can be used recursively. + +‘C-c M-g f’ (‘magit-blame-reverse’) +‘C-c M-g B f’ (‘magit-blame-reverse’) + + This command augments each line or chunk of lines in the current + file-visiting or blob-visiting buffer with information about the + last revision in which a line still existed. + + Like ‘magit-blame-addition’, this command can be used recursively. + +‘C-c M-g e’ (‘magit-blame-echo’) +‘C-c M-g B e’ (‘magit-blame-echo’) + + This command is like ‘magit-blame-addition’ except that it doesn’t + turn on ‘read-only-mode’ and that it initially uses the + visualization style specified by option ‘magit-blame-echo-style’. + + The following key bindings are available when Magit-Blame mode is +enabled and Read-Only mode is not enabled. These commands are also +available in other buffers; here only the behavior is described that is +relevant in file-visiting buffers that are being blamed. + +‘RET’ (‘magit-show-commit’) + + This command shows the commit that last touched the line at point. + +‘SPC’ (‘magit-diff-show-or-scroll-up’) + + This command updates the commit buffer. + + This either shows the commit that last touched the line at point in + the appropriate buffer, or if that buffer is already being + displayed in the current frame and if that buffer contains + information about that commit, then the buffer is scrolled up + instead. + +‘DEL’ (‘magit-diff-show-or-scroll-down’) + + This command updates the commit buffer. + + This either shows the commit that last touched the line at point in + the appropriate buffer, or if that buffer is already being + displayed in the current frame and if that buffer contains + information about that commit, then the buffer is scrolled down + instead. + + The following key bindings are available when both Magit-Blame mode +and Read-Only mode are enabled. + +‘b’ (‘magit-blame’) + + See above. + +‘n’ (‘magit-blame-next-chunk’) + + This command moves to the next chunk. + +‘N’ (‘magit-blame-next-chunk-same-commit’) + + This command moves to the next chunk from the same commit. + +‘p’ (‘magit-blame-previous-chunk’) + + This command moves to the previous chunk. + +‘P’ (‘magit-blame-previous-chunk-same-commit’) + + This command moves to the previous chunk from the same commit. + +‘q’ (‘magit-blame-quit’) + + This command turns off Magit-Blame mode. If the buffer was created + during a recursive blame, then it also kills the buffer. + +‘M-w’ (‘magit-blame-copy-hash’) + + This command saves the hash of the current chunk’s commit to the + kill ring. + + When the region is active, the command saves the region’s content + instead of the hash, like ‘kill-ring-save’ would. + +‘c’ (‘magit-blame-cycle-style’) + + This command changes how blame information is visualized in the + current buffer by cycling through the styles specified using the + option ‘magit-blame-styles’. + + Blaming is also controlled using the following options. + + -- User Option: magit-blame-styles + + This option defines a list of styles used to visualize blame + information. For now see its doc-string to learn more. + + -- User Option: magit-blame-echo-style + + This option specifies the blame visualization style used by the + command ‘magit-blame-echo’. This must be a symbol that is used as + the identifier for one of the styles defined in + ‘magit-blame-styles’. + + -- User Option: magit-blame-time-format + + This option specifies the format string used to display times when + showing blame information. + + -- User Option: magit-blame-read-only + + This option controls whether blaming a buffer also makes + temporarily read-only. + + -- User Option: magit-blame-disable-modes + + This option lists incompatible minor-modes that should be disabled + temporarily when a buffer contains blame information. They are + enabled again when the buffer no longer shows blame information. + + -- User Option: magit-blame-goto-chunk-hook + + This hook is run when moving between chunks. + + +File: magit.info, Node: Manipulating, Next: Transferring, Prev: Inspecting, Up: Top + +6 Manipulating +************** + +* Menu: + +* Creating Repository:: +* Cloning Repository:: +* Staging and Unstaging:: +* Applying:: +* Committing:: +* Branching:: +* Merging:: +* Resolving Conflicts:: +* Rebasing:: +* Cherry Picking:: +* Resetting:: +* Stashing:: + + +File: magit.info, Node: Creating Repository, Next: Cloning Repository, Up: Manipulating + +6.1 Creating Repository +======================= + +‘M-x magit-init’ (‘magit-init’) + + This command initializes a repository and then shows the status + buffer for the new repository. + + If the directory is below an existing repository, then the user has + to confirm that a new one should be created inside. If the + directory is the root of the existing repository, then the user has + to confirm that it should be reinitialized. + + +File: magit.info, Node: Cloning Repository, Next: Staging and Unstaging, Prev: Creating Repository, Up: Manipulating + +6.2 Cloning Repository +====================== + +To clone a remote or local repository use ‘C’, which is bound to the +command ‘magit-clone’. This command either act as a transient prefix +command, which binds several infix arguments and suffix commands, or it +can invoke ‘git clone’ directly, depending on whether a prefix argument +is used and on the value of ‘magit-clone-always-transient’. + + -- User Option: magit-clone-always-transient + + This option controls whether the command ‘magit-clone’ always acts + as a transient prefix command, regardless of whether a prefix + argument is used or not. If ‘t’, then that command always acts as + a transient prefix. If ‘nil’, then a prefix argument has to be + used for it to act as a transient. + +‘C’ (‘magit-clone’) + + This command either acts as a transient prefix command as described + above or does the same thing as ‘transient-clone-regular’ as + described below. + + If it acts as a transient prefix, then it binds the following + suffix commands and several infix arguments. + +‘C C’ (‘magit-clone-regular’) + + This command creates a regular clone of an existing repository. + The repository and the target directory are read from the user. + +‘C s’ (‘magit-clone-shallow’) + + This command creates a shallow clone of an existing repository. + The repository and the target directory are read from the user. By + default the depth of the cloned history is a single commit, but + with a prefix argument the depth is read from the user. + +‘C b’ (‘magit-clone-bare’) + + This command creates a bare clone of an existing repository. The + repository and the target directory are read from the user. + +‘C m’ (‘magit-clone-mirror’) + + This command creates a mirror of an existing repository. The + repository and the target directory are read from the user. + + The following suffixes are disabled by default. See *note +(transient)Enabling and Disabling Suffixes:: for how to enable them. + +‘C d’ (‘magit-clone-shallow-since’) + + This command creates a shallow clone of an existing repository. + Only commits that were committed after a date are cloned, which is + read from the user. The repository and the target directory are + also read from the user. + +‘C e’ (‘magit-clone-shallow-exclude’) + + This command creates a shallow clone of an existing repository. + This reads a branch or tag from the user. Commits that are + reachable from that are not cloned. The repository and the target + directory are also read from the user. + + -- User Option: magit-clone-set-remote-head + + This option controls whether cloning causes the reference + ‘refs/remotes//HEAD’ to be created in the clone. The + default is to do so. + + Actually ‘git clone’ itself does that and cannot be told to not do + it. Therefore setting this to ‘nil’ causes Magit to remove that + reference after cloning. + + -- User Option: magit-clone-set-remote.pushDefault + + This option controls whether the value of the Git variable + ‘remote.pushDefault’ is set after cloning. + + • If ‘t’, then it is always set without asking. + + • If ‘ask’, then the users are asked every time they clone a + repository. + + • If ‘nil’, then it is never set. + + -- User Option: magit-clone-default-directory + + This option control the default directory name used when reading + the destination for a cloning operation. + + • If ‘nil’ (the default), then the value of ‘default-directory’ + is used. + + • If a directory, then that is used. + + • If a function, then that is called with the remote url as the + only argument and the returned value is used. + + -- User Option: magit-clone-name-alist + + This option maps regular expressions, which match repository names, + to repository urls, making it possible for users to enter short + names instead of urls when cloning repositories. + + Each element has the form ‘(REGEXP HOSTNAME USER)’. When the user + enters a name when a cloning command asks for a name or url, then + that is looked up in this list. The first element whose REGEXP + matches is used. + + The format specified by option ‘magit-clone-url-format’ is used to + turn the name into an url, using HOSTNAME and the repository name. + If the provided name contains a slash, then that is used. + Otherwise if the name omits the owner of the repository, then the + default user specified in the matched entry is used. + + If USER contains a dot, then it is treated as a Git variable and + the value of that is used as the username. Otherwise it is used as + the username itself. + + -- User Option: magit-clone-url-format + + The format specified by this option is used when turning repository + names into urls. ‘%h’ is the hostname and ‘%n’ is the repository + name, including the name of the owner. + + +File: magit.info, Node: Staging and Unstaging, Next: Applying, Prev: Cloning Repository, Up: Manipulating + +6.3 Staging and Unstaging +========================= + +Like Git, Magit can of course stage and unstage complete files. Unlike +Git, it also allows users to gracefully un-/stage individual hunks and +even just part of a hunk. To stage individual hunks and parts of hunks +using Git directly, one has to use the very modal and rather clumsy +interface of a ‘git add --interactive’ session. + + With Magit, on the other hand, one can un-/stage individual hunks by +just moving point into the respective section inside a diff displayed in +the status buffer or a separate diff buffer and typing ‘s’ or ‘u’. To +operate on just parts of a hunk, mark the changes that should be +un-/staged using the region and then press the same key that would be +used to un-/stage. To stage multiple files or hunks at once use a +region that starts inside the heading of such a section and ends inside +the heading of a sibling section of the same type. + + Besides staging and unstaging, Magit also provides several other +"apply variants" that can also operate on a file, multiple files at +once, a hunk, multiple hunks at once, and on parts of a hunk. These +apply variants are described in the next section. + + You can also use Ediff to stage and unstage. See *note Ediffing::. + +‘s’ (‘magit-stage’) + + Add the change at point to the staging area. + + With a prefix argument and an untracked file (or files) at point, + stage the file but not its content. This makes it possible to + stage only a subset of the new file’s changes. + +‘S’ (‘magit-stage-modified’) + + Stage all changes to files modified in the worktree. Stage all new + content of tracked files and remove tracked files that no longer + exist in the working tree from the index also. With a prefix + argument also stage previously untracked (but not ignored) files. + +‘u’ (‘magit-unstage’) + + Remove the change at point from the staging area. + + Only staged changes can be unstaged. But by default this command + performs an action that is somewhat similar to unstaging, when it + is called on a committed change: it reverses the change in the + index but not in the working tree. + +‘U’ (‘magit-unstage-all’) + + Remove all changes from the staging area. + + -- User Option: magit-unstage-committed + + This option controls whether ‘magit-unstage’ "unstages" committed + changes by reversing them in the index but not the working tree. + The alternative is to raise an error. + +‘M-x magit-reverse-in-index’ (‘magit-reverse-in-index’) + + This command reverses the committed change at point in the index + but not the working tree. By default no key is bound directly to + this command, but it is indirectly called when ‘u’ + (‘magit-unstage’) is pressed on a committed change. + + This allows extracting a change from ‘HEAD’, while leaving it in + the working tree, so that it can later be committed using a + separate commit. A typical workflow would be: + + • Optionally make sure that there are no uncommitted changes. + + • Visit the ‘HEAD’ commit and navigate to the change that should + not have been included in that commit. + + • Type ‘u’ (‘magit-unstage’) to reverse it in the index. This + assumes that ‘magit-unstage-committed-changes’ is non-nil. + + • Type ‘c e’ to extend ‘HEAD’ with the staged changes, including + those that were already staged before. + + • Optionally stage the remaining changes using ‘s’ or ‘S’ and + then type ‘c c’ to create a new commit. + +‘M-x magit-reset-index’ (‘magit-reset-index’) + + Reset the index to some commit. The commit is read from the user + and defaults to the commit at point. If there is no commit at + point, then it defaults to ‘HEAD’. + +* Menu: + +* Staging from File-Visiting Buffers:: + + +File: magit.info, Node: Staging from File-Visiting Buffers, Up: Staging and Unstaging + +6.3.1 Staging from File-Visiting Buffers +---------------------------------------- + +Fine-grained un-/staging has to be done from the status or a diff +buffer, but it’s also possible to un-/stage all changes made to the file +visited in the current buffer right from inside that buffer. + +‘M-x magit-stage-file’ (‘magit-stage-file’) + + When invoked inside a file-visiting buffer, then stage all changes + to that file. In a Magit buffer, stage the file at point if any. + Otherwise prompt for a file to be staged. With a prefix argument + always prompt the user for a file, even in a file-visiting buffer + or when there is a file section at point. + +‘M-x magit-unstage-file’ (‘magit-unstage-file’) + + When invoked inside a file-visiting buffer, then unstage all + changes to that file. In a Magit buffer, unstage the file at point + if any. Otherwise prompt for a file to be unstaged. With a prefix + argument always prompt the user for a file, even in a file-visiting + buffer or when there is a file section at point. + + +File: magit.info, Node: Applying, Next: Committing, Prev: Staging and Unstaging, Up: Manipulating + +6.4 Applying +============ + +Magit provides several "apply variants": stage, unstage, discard, +reverse, and "regular apply". At least when operating on a hunk they +are all implemented using ‘git apply’, which is why they are called +"apply variants". + + • Stage. Apply a change from the working tree to the index. The + change also remains in the working tree. + + • Unstage. Remove a change from the index. The change remains in + the working tree. + + • Discard. On a staged change, remove it from the working tree and + the index. On an unstaged change, remove it from the working tree + only. + + • Reverse. Reverse a change in the working tree. Both committed and + staged changes can be reversed. Unstaged changes cannot be + reversed. Discard them instead. + + • Apply. Apply a change to the working tree. Both committed and + staged changes can be applied. Unstaged changes cannot be applied + - as they already have been applied. + + The previous section described the staging and unstaging commands. +What follows are the commands which implement the remaining apply +variants. + +‘a’ (‘magit-apply’) + + Apply the change at point to the working tree. + + With a prefix argument fallback to a 3-way merge. Doing so causes + the change to be applied to the index as well. + +‘k’ (‘magit-discard’) + + Remove the change at point from the working tree. + +‘v’ (‘magit-reverse’) + + Reverse the change at point in the working tree. + + With a prefix argument fallback to a 3-way merge. Doing so causes + the change to be applied to the index as well. + + With a prefix argument all apply variants attempt a 3-way merge when +appropriate (i.e. when ‘git apply’ is used internally). + + +File: magit.info, Node: Committing, Next: Branching, Prev: Applying, Up: Manipulating + +6.5 Committing +============== + +When the user initiates a commit, Magit calls ‘git commit’ without any +arguments, so Git has to get it from the user. It creates the file +‘.git/COMMIT_EDITMSG’ and then opens that file in an editor. Magit +arranges for that editor to be the Emacsclient. Once the user finishes +the editing session, the Emacsclient exits and Git creates the commit +using the file’s content as message. + +* Menu: + +* Initiating a Commit:: +* Editing Commit Messages:: + + +File: magit.info, Node: Initiating a Commit, Next: Editing Commit Messages, Up: Committing + +6.5.1 Initiating a Commit +------------------------- + +Also see *note (gitman)git-commit::. + +‘c’ (‘magit-commit’) + + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. + +‘c c’ (‘magit-commit-create’) + + Create a new commit on ‘HEAD’. With a prefix argument amend to the + commit at ‘HEAD’ instead. + +‘c a’ (‘magit-commit-amend’) + + Amend the last commit. + +‘c e’ (‘magit-commit-extend’) + + Amend the last commit, without editing the message. With a prefix + argument keep the committer date, otherwise change it. The option + ‘magit-commit-extend-override-date’ can be used to inverse the + meaning of the prefix argument. + + Non-interactively respect the optional OVERRIDE-DATE argument and + ignore the option. + +‘c w’ (‘magit-commit-reword’) + + Reword the last commit, ignoring staged changes. With a prefix + argument keep the committer date, otherwise change it. The option + ‘magit-commit-reword-override-date’ can be used to inverse the + meaning of the prefix argument. + + Non-interactively respect the optional OVERRIDE-DATE argument and + ignore the option. + +‘c f’ (‘magit-commit-fixup’) + + Create a fixup commit. + + With a prefix argument the target commit has to be confirmed. + Otherwise the commit at point may be used without confirmation + depending on the value of option ‘magit-commit-squash-confirm’. + +‘c F’ (‘magit-commit-instant-fixup’) + + Create a fixup commit and instantly rebase. + +‘c s’ (‘magit-commit-squash’) + + Create a squash commit, without editing the squash message. + + With a prefix argument the target commit has to be confirmed. + Otherwise the commit at point may be used without confirmation + depending on the value of option ‘magit-commit-squash-confirm’. + +‘c S’ (‘magit-commit-instant-squash’) + + Create a squash commit and instantly rebase. + +‘c A’ (‘magit-commit-augment’) + + Create a squash commit, editing the squash message. + + With a prefix argument the target commit has to be confirmed. + Otherwise the commit at point may be used without confirmation + depending on the value of option ‘magit-commit-squash-confirm’. + + -- User Option: magit-commit-ask-to-stage + + Whether to ask to stage all unstaged changes when committing and + nothing is staged. + + -- User Option: magit-commit-extend-override-date + + Whether using ‘magit-commit-extend’ changes the committer date. + + -- User Option: magit-commit-reword-override-date + + Whether using ‘magit-commit-reword’ changes the committer date. + + -- User Option: magit-commit-squash-confirm + + Whether the commit targeted by squash and fixup has to be + confirmed. When non-nil then the commit at point (if any) is used + as default choice. Otherwise it has to be confirmed. This option + only affects ‘magit-commit-squash’ and ‘magit-commit-fixup’. The + "instant" variants always require confirmation because making an + error while using those is harder to recover from. + + +File: magit.info, Node: Editing Commit Messages, Prev: Initiating a Commit, Up: Committing + +6.5.2 Editing Commit Messages +----------------------------- + +After initiating a commit as described in the previous section, two new +buffers appear. One shows the changes that are about to committed, +while the other is used to write the message. All regular editing +commands are available in the commit message buffer. This section only +describes the additional commands. + + Commit messages are edited in an edit session - in the background Git +is waiting for the editor, in our case the Emacsclient, to save the +commit message in a file (in most cases ‘.git/COMMIT_EDITMSG’) and then +return. If the Emacsclient returns with a non-zero exit status then Git +does not create the commit. So the most important commands are those +for finishing and aborting the commit. + +‘C-c C-c’ (‘with-editor-finish’) + + Finish the current editing session by returning with exit code 0. + Git then creates the commit using the message it finds in the file. + +‘C-c C-k’ (‘with-editor-cancel’) + + Cancel the current editing session by returning with exit code 1. + Git then cancels the commit, but leaves the file untouched. + + In addition to being used by Git, these messages may also be stored +in a ring that persists until Emacs is closed. By default the message +is stored at the beginning and the end of an edit session (regardless of +whether the session is finished successfully or was canceled). It is +sometimes useful to bring back messages from that ring. + +‘C-c M-s’ (‘git-commit-save-message’) + + Save the current buffer content to the commit message ring. + +‘M-p’ (‘git-commit-prev-message’) + + Cycle backward through the commit message ring, after saving the + current message to the ring. With a numeric prefix ARG, go back + ARG comments. + +‘M-n’ (‘git-commit-next-message’) + + Cycle forward through the commit message ring, after saving the + current message to the ring. With a numeric prefix ARG, go back + ARG comments. + + By default the diff for the changes that are about to be committed +are automatically shown when invoking the commit. When amending to an +existing commit it may be useful to show either the changes that are +about to be added to that commit or to show those changes together with +those that are already committed. + +‘C-c C-d’ (‘magit-diff-while-committing’) + + While committing, show the changes that are about to be committed. + While amending, invoking the command again toggles between showing + just the new changes or all the changes that will be committed. + +‘C-c C-w’ (‘magit-pop-revision-stack’) + + This command inserts a representation of a revision into the + current buffer. It can be used inside buffers used to write commit + messages but also in other buffers such as buffers used to edit + emails or ChangeLog files. + + By default this command pops the revision which was last added to + the ‘magit-revision-stack’ and inserts it into the current buffer + according to ‘magit-pop-revision-stack-format’. Revisions can be + put on the stack using ‘magit-copy-section-value’ and + ‘magit-copy-buffer-revision’. + + If the stack is empty or with a prefix argument it instead reads a + revision in the minibuffer. By using the minibuffer history this + allows selecting an item which was popped earlier or to insert an + arbitrary reference or revision without first pushing it onto the + stack. + + When reading the revision from the minibuffer, then it might not be + possible to guess the correct repository. When this command is + called inside a repository (e.g. while composing a commit + message), then that repository is used. Otherwise (e.g. while + composing an email) then the repository recorded for the top + element of the stack is used (even though we insert another + revision). If not called inside a repository and with an empty + stack, or with two prefix arguments, then read the repository in + the minibuffer too. + + -- User Option: magit-pop-revision-stack-format + + This option controls how the command ‘magit-pop-revision-stack’ + inserts a revision into the current buffer. + + The entries on the stack have the format ‘(HASH TOPLEVEL)’ and this + option has the format ‘(POINT-FORMAT EOB-FORMAT INDEX-REGEXP)’, all + of which may be nil or a string (though either one of EOB-FORMAT or + POINT-FORMAT should be a string, and if INDEX-REGEXP is non-nil, + then the two formats should be too). + + First INDEX-REGEXP is used to find the previously inserted entry, + by searching backward from point. The first submatch must match + the index number. That number is incremented by one, and becomes + the index number of the entry to be inserted. If you don’t want to + number the inserted revisions, then use nil for INDEX-REGEXP. + + If INDEX-REGEXP is non-nil then both POINT-FORMAT and EOB-FORMAT + should contain \"%N\", which is replaced with the number that was + determined in the previous step. + + Both formats, if non-nil and after removing %N, are then expanded + using ‘git show –format=FORMAT ...’ inside TOPLEVEL. + + The expansion of POINT-FORMAT is inserted at point, and the + expansion of EOB-FORMAT is inserted at the end of the buffer (if + the buffer ends with a comment, then it is inserted right before + that). + + Some projects use pseudo headers in commit messages. Magit colorizes +such headers and provides some commands to insert such headers. + + -- User Option: git-commit-known-pseudo-headers + + A list of Git pseudo headers to be highlighted. + +‘C-c C-a’ (‘git-commit-ack’) + + Insert a header acknowledging that you have looked at the commit. + +‘C-c C-r’ (‘git-commit-review’) + + Insert a header acknowledging that you have reviewed the commit. + +‘C-c C-s’ (‘git-commit-signoff’) + + Insert a header to sign off the commit. + +‘C-c C-t’ (‘git-commit-test’) + + Insert a header acknowledging that you have tested the commit. + +‘C-c C-o’ (‘git-commit-cc’) + + Insert a header mentioning someone who might be interested. + +‘C-c C-p’ (‘git-commit-reported’) + + Insert a header mentioning the person who reported the issue being + fixed by the commit. + +‘C-c C-i’ (‘git-commit-suggested’) + + Insert a header mentioning the person who suggested the change. + + ‘git-commit-mode’ is a minor mode that is only used to establish the +above key bindings. This allows using an arbitrary major mode when +editing the commit message. It’s even possible to use a different major +mode in different repositories, which is useful when different projects +impose different commit message conventions. + + -- User Option: git-commit-major-mode + + The value of this option is the major mode used to edit Git commit + messages. + + Because ‘git-commit-mode’ is a minor mode, we don’t use its mode hook +to setup the buffer, except for the key bindings. All other setup +happens in the function ‘git-commit-setup’, which among other things +runs the hook ‘git-commit-setup-hook’. The following functions are +suitable for that hook. + + -- User Option: git-commit-setup-hook + + Hook run at the end of ‘git-commit-setup’. + + -- Function: magit-revert-buffers &optional force + + Revert unmodified file-visiting buffers of the current repository. + + If either ‘magit-revert-buffers’ is non-nil and + ‘inhibit-magit-revert’ is nil, or if optional FORCE is non-nil, + then revert all unmodified buffers that visit files being tracked + in the current repository. + + -- Function: git-commit-save-message + + Save the current buffer content to the commit message ring. + + -- Function: git-commit-setup-changelog-support + + After this function is called, ChangeLog entries are treated as + paragraphs. + + -- Function: git-commit-turn-on-auto-fill + + Turn on ‘auto-fill-mode’ and set ‘fill-column’ to the value of + ‘git-commit-fill-column’. + + -- Function: git-commit-turn-on-flyspell + + Turn on Flyspell mode. Also prevent comments from being checked + and finally check current non-comment text. + + -- Function: git-commit-propertize-diff + + Propertize the diff shown inside the commit message buffer. Git + inserts such diffs into the commit message template when the + ‘--verbose’ argument is used. ‘magit-commit’ by default does not + offer that argument because the diff that is shown in a separate + buffer is more useful. But some users disagree, which is why this + function exists. + + -- Function: with-editor-usage-message + + Show usage information in the echo area. + + Magit also helps with writing *good* commit messages by complaining +when certain rules are violated. + + -- User Option: git-commit-summary-max-length + + The intended maximal length of the summary line of commit messages. + Characters beyond this column are colorized to indicate that this + preference has been violated. + + -- User Option: git-commit-fill-column + + Column beyond which automatic line-wrapping should happen in commit + message buffers. + + -- User Option: git-commit-finish-query-functions + + List of functions called to query before performing commit. + + The commit message buffer is current while the functions are + called. If any of them returns nil, then the commit is not + performed and the buffer is not killed. The user should then fix + the issue and try again. + + The functions are called with one argument. If it is non-nil then + that indicates that the user used a prefix argument to force + finishing the session despite issues. Functions should usually + honor this wish and return non-nil. + + -- Function: git-commit-check-style-conventions + + Check for violations of certain basic style conventions. For each + violation ask the user if she wants to proceed anyway. This makes + sure the summary line isn’t too long and that the second line is + empty. + + To show no diff while committing remove ‘magit-commit-diff’ from +‘server-switch-hook’. + + +File: magit.info, Node: Branching, Next: Merging, Prev: Committing, Up: Manipulating + +6.6 Branching +============= + +* Menu: + +* The Two Remotes:: +* Branch Commands:: +* Branch Git Variables:: +* Auxiliary Branch Commands:: + + +File: magit.info, Node: The Two Remotes, Next: Branch Commands, Up: Branching + +6.6.1 The Two Remotes +--------------------- + +The upstream branch of some local branch is the branch into which the +commits on that local branch should eventually be merged, usually +something like ‘origin/master’. For the ‘master’ branch itself the +upstream branch and the branch it is being pushed to, are usually the +same remote branch. But for a feature branch the upstream branch and +the branch it is being pushed to should differ. + + The commits on feature branches too should _eventually_ end up in a +remote branch such as ‘origin/master’ or ‘origin/maint’. Such a branch +should therefore be used as the upstream. But feature branches +shouldn’t be pushed directly to such branches. Instead a feature branch +‘my-feature’ is usually pushed to ‘my-fork/my-feature’ or if you are a +contributor ‘origin/my-feature’. After the new feature has been +reviewed, the maintainer merges the feature into ‘master’. And finally +‘master’ (not ‘my-feature’ itself) is pushed to ‘origin/master’. + + But new features seldom are perfect on the first try, and so feature +branches usually have to be reviewed, improved, and re-pushed several +times. Pushing should therefore be easy to do, and for that reason many +Git users have concluded that it is best to use the remote branch to +which the local feature branch is being pushed as its upstream. + + But luckily Git has long ago gained support for a push-remote which +can be configured separately from the upstream branch, using the +variables ‘branch..pushRemote’ and ‘remote.pushDefault’. So we no +longer have to choose which of the two remotes should be used as "the +remote". + + Each of the fetching, pulling, and pushing transient commands +features three suffix commands that act on the current branch and some +other branch. Of these, ‘p’ is bound to a command which acts on the +push-remote, ‘u’ is bound to a command which acts on the upstream, and +‘e’ is bound to a command which acts on any other branch. The status +buffer shows unpushed and unpulled commits for both the push-remote and +the upstream. + + It’s fairly simple to configure these two remotes. The values of all +the variables that are related to fetching, pulling, and pushing (as +well as some other branch-related variables) can be inspected and +changed using the command ‘magit-branch-configure’, which is available +from many transient prefix commands that deal with branches. It is also +possible to set the push-remote or upstream while pushing (see *note +Pushing::). + + +File: magit.info, Node: Branch Commands, Next: Branch Git Variables, Prev: The Two Remotes, Up: Branching + +6.6.2 Branch Commands +--------------------- + +The transient prefix command ‘magit-branch’ is used to create and +checkout branches, and to make changes to existing branches. It is not +used to fetch, pull, merge, rebase, or push branches, i.e. this command +deals with branches themselves, not with the commits reachable from +them. Those features are available from separate transient command. + +‘b’ (‘magit-branch’) + + This transient prefix command binds the following suffix commands + and displays them in a temporary buffer until a suffix is invoked. + + By default it also binds and displays the values of some + branch-related Git variables and allows changing their values. + + -- User Option: magit-branch-direct-configure + + This option controls whether the transient command ‘magit-branch’ + can be used directly change the values Git variables. This + defaults to ‘t’ (to avoid changing key bindings). When set to + ‘nil’, then no variables are displayed by that transient command, + and its suffix command ‘magit-branch-configure’ has to be used + instead to view and change branch related variables. + +‘b C’ (‘magit-branch-configure’) +‘f C’ (‘magit-branch-configure’) +‘F C’ (‘magit-branch-configure’) +‘P C’ (‘magit-branch-configure’) + + This transient prefix command binds commands that set the value of + branch-related variables and displays them in a temporary buffer + until the transient is exited. + + With a prefix argument, this command always prompts for a branch. + + Without a prefix argument this depends on whether it was invoked as + a suffix of ‘magit-branch’ and on the + ‘magit-branch-direct-configure’ option. If ‘magit-branch’ already + displays the variables for the current branch, then it isn’t useful + to invoke another transient that displays them for the same branch. + In that case this command prompts for a branch. + + The variables are described in *note Branch Git Variables::. + +‘b b’ (‘magit-checkout’) + + Checkout a revision read in the minibuffer and defaulting to the + branch or arbitrary revision at point. If the revision is a local + branch then that becomes the current branch. If it is something + else then ‘HEAD’ becomes detached. Checkout fails if the working + tree or the staging area contain changes. + +‘b n’ (‘magit-branch-create’) + + Create a new branch. The user is asked for a branch or arbitrary + revision to use as the starting point of the new branch. When a + branch name is provided, then that becomes the upstream branch of + the new branch. The name of the new branch is also read in the + minibuffer. + + Also see option ‘magit-branch-prefer-remote-upstream’. + +‘b c’ (‘magit-branch-and-checkout’) + + This command creates a new branch like ‘magit-branch’, but then + also checks it out. + + Also see option ‘magit-branch-prefer-remote-upstream’. + +‘b l’ (‘magit-branch-checkout’) + + This command checks out an existing or new local branch. It reads + a branch name from the user offering all local branches and a + subset of remote branches as candidates. Remote branches for which + a local branch by the same name exists are omitted from the list of + candidates. The user can also enter a completely new branch name. + + • If the user selects an existing local branch, then that is + checked out. + + • If the user selects a remote branch, then it creates and + checks out a new local branch with the same name, and + configures the selected remote branch as the push target. + + • If the user enters a new branch name, then it creates and + checks that out, after also reading the starting-point from + the user. + + In the latter two cases the upstream is also set. Whether it is + set to the chosen starting point or something else depends on the + value of ‘magit-branch-adjust-remote-upstream-alist’. + +‘b s’ (‘magit-branch-spinoff’) + + This command creates and checks out a new branch starting at and + tracking the current branch. That branch in turn is reset to the + last commit it shares with its upstream. If the current branch has + no upstream or no unpushed commits, then the new branch is created + anyway and the previously current branch is not touched. + + This is useful to create a feature branch after work has already + began on the old branch (likely but not necessarily "master"). + + If the current branch is a member of the value of option + ‘magit-branch-prefer-remote-upstream’ (which see), then the current + branch will be used as the starting point as usual, but the + upstream of the starting-point may be used as the upstream of the + new branch, instead of the starting-point itself. + + If optional FROM is non-nil, then the source branch is reset to + ‘FROM~’, instead of to the last commit it shares with its upstream. + Interactively, FROM is only ever non-nil, if the region selects + some commits, and among those commits, FROM is the commit that is + the fewest commits ahead of the source branch. + + The commit at the other end of the selection actually does not + matter, all commits between FROM and ‘HEAD’ are moved to the new + branch. If FROM is not reachable from ‘HEAD’ or is reachable from + the source branch’s upstream, then an error is raised. + +‘b S’ (‘magit-branch-spinout’) + + This command behaves like ‘magit-branch-spinoff’, except that it + does not change the current branch. If there are any uncommitted + changes, then it behaves exactly like ‘magit-branch-spinoff’. + +‘b x’ (‘magit-branch-reset’) + + This command resets a branch, defaulting to the branch at point, to + the tip of another branch or any other commit. + + When the branch being reset is the current branch, then a hard + reset is performed. If there are any uncommitted changes, then the + user has to confirm the reset because those changes would be lost. + + This is useful when you have started work on a feature branch but + realize it’s all crap and want to start over. + + When resetting to another branch and a prefix argument is used, + then the target branch is set as the upstream of the branch that is + being reset. + +‘b k’ (‘magit-branch-delete’) + + Delete one or multiple branches. If the region marks multiple + branches, then offer to delete those. Otherwise, prompt for a + single branch to be deleted, defaulting to the branch at point. + +‘b r’ (‘magit-branch-rename’) + + Rename a branch. The branch and the new name are read in the + minibuffer. With prefix argument the branch is renamed even if + that name conflicts with an existing branch. + + -- User Option: magit-branch-read-upstream-first + + When creating a branch, whether to read the upstream branch before + the name of the branch that is to be created. The default is + ‘nil’, and I recommend you leave it at that. + + -- User Option: magit-branch-prefer-remote-upstream + + This option specifies whether remote upstreams are favored over + local upstreams when creating new branches. + + When a new branch is created, then the branch, commit, or stash at + point is suggested as the starting point of the new branch, or if + there is no such revision at point the current branch. In either + case the user may choose another starting point. + + If the chosen starting point is a branch, then it may also be set + as the upstream of the new branch, depending on the value of the + Git variable ‘branch.autoSetupMerge’. By default this is done for + remote branches, but not for local branches. + + You might prefer to always use some remote branch as upstream. If + the chosen starting point is (1) a local branch, (2) whose name + matches a member of the value of this option, (3) the upstream of + that local branch is a remote branch with the same name, and (4) + that remote branch can be fast-forwarded to the local branch, then + the chosen branch is used as starting point, but its own upstream + is used as the upstream of the new branch. + + Members of this option’s value are treated as branch names that + have to match exactly unless they contain a character that makes + them invalid as a branch name. Recommended characters to use to + trigger interpretation as a regexp are "*" and "^". Some other + characters which you might expect to be invalid, actually are not, + e.g. ".+$" are all perfectly valid. More precisely, if ‘git + check-ref-format –branch STRING’ exits with a non-zero status, then + treat STRING as a regexp. + + Assuming the chosen branch matches these conditions you would end + up with with e.g.: + + feature --upstream--> origin/master + + instead of + + feature --upstream--> master --upstream--> origin/master + + Which you prefer is a matter of personal preference. If you do + prefer the former, then you should add branches such as ‘master’, + ‘next’, and ‘maint’ to the value of this options. + + -- User Option: magit-branch-adjust-remote-upstream-alist + + The value of this option is an alist of branches to be used as the + upstream when branching a remote branch. + + When creating a local branch from an ephemeral branch located on a + remote, e.g. a feature or hotfix branch, then that remote branch + should usually not be used as the upstream branch, since the + push-remote already allows accessing it and having both the + upstream and the push-remote reference the same related branch + would be wasteful. Instead a branch like "maint" or "master" + should be used as the upstream. + + This option allows specifying the branch that should be used as the + upstream when branching certain remote branches. The value is an + alist of the form ‘((UPSTREAM . RULE)...)’. The first matching + element is used, the following elements are ignored. + + UPSTREAM is the branch to be used as the upstream for branches + specified by RULE. It can be a local or a remote branch. + + RULE can either be a regular expression, matching branches whose + upstream should be the one specified by UPSTREAM. Or it can be a + list of the only branches that should *not* use UPSTREAM; all other + branches will. Matching is done after stripping the remote part of + the name of the branch that is being branched from. + + If you use a finite set of non-ephemeral branches across all your + repositories, then you might use something like: + + (("origin/master" "master" "next" "maint")) + + Or if the names of all your ephemeral branches contain a slash, at + least in some repositories, then a good value could be: + + (("origin/master" . "/")) + + Of course you can also fine-tune: + + (("origin/maint" . "\\`hotfix/") + ("origin/master" . "\\`feature/")) + + -- Command: magit-branch-orphan + + This command creates and checks out a new orphan branch with + contents from a given revision. + + -- Command: magit-branch-or-checkout + + This command is a hybrid between ‘magit-checkout’ and + ‘magit-branch-and-checkout’ and is intended as a replacement for + the former in ‘magit-branch’. + + It first asks the user for an existing branch or revision. If the + user input actually can be resolved as a branch or revision, then + it checks that out, just like ‘magit-checkout’ would. + + Otherwise it creates and checks out a new branch using the input as + its name. Before doing so it reads the starting-point for the new + branch. This is similar to what ‘magit-branch-and-checkout’ does. + + To use this command instead of ‘magit-checkout’ add this to your + init file: + + (transient-replace-suffix 'magit-branch 'magit-checkout + '("b" "dwim" magit-branch-or-checkout)) + + +File: magit.info, Node: Branch Git Variables, Next: Auxiliary Branch Commands, Prev: Branch Commands, Up: Branching + +6.6.3 Branch Git Variables +-------------------------- + +These variables can be set from the transient prefix command +‘magit-branch-configure’. By default they can also be set from +‘magit-branch’. See *note Branch Commands::. + + -- Variable: branch.NAME.merge + + Together with ‘branch.NAME.remote’ this variable defines the + upstream branch of the local branch named NAME. The value of this + variable is the full reference of the upstream _branch_. + + -- Variable: branch.NAME.remote + + Together with ‘branch.NAME.merge’ this variable defines the + upstream branch of the local branch named NAME. The value of this + variable is the name of the upstream _remote_. + + -- Variable: branch.NAME.rebase + + This variable controls whether pulling into the branch named NAME + is done by rebasing or by merging the fetched branch. + + • When ‘true’ then pulling is done by rebasing. + + • When ‘false’ then pulling is done by merging. + + • When undefined then the value of ‘pull.rebase’ is used. The + default of that variable is ‘false’. + + -- Variable: branch.NAME.pushRemote + + This variable specifies the remote that the branch named NAME is + usually pushed to. The value has to be the name of an existing + remote. + + It is not possible to specify the name of _branch_ to push the + local branch to. The name of the remote branch is always the same + as the name of the local branch. + + If this variable is undefined but ‘remote.pushDefault’ is defined, + then the value of the latter is used. By default + ‘remote.pushDefault’ is undefined. + + -- Variable: branch.NAME.description + + This variable can be used to describe the branch named NAME. That + description is used e.g. when turning the branch into a series of + patches. + + The following variables specify defaults which are used if the above +branch-specific variables are not set. + + -- Variable: pull.rebase + + This variable specifies whether pulling is done by rebasing or by + merging. It can be overwritten using ‘branch.NAME.rebase’. + + • When ‘true’ then pulling is done by rebasing. + + • When ‘false’ (the default) then pulling is done by merging. + + Since it is never a good idea to merge the upstream branch into a + feature or hotfix branch and most branches are such branches, you + should consider setting this to ‘true’, and ‘branch.master.rebase’ + to ‘false’. + + -- Variable: remote.pushDefault + + This variable specifies what remote the local branches are usually + pushed to. This can be overwritten per branch using + ‘branch.NAME.pushRemote’. + + The following variables are used during the creation of a branch and +control whether the various branch-specific variables are automatically +set at this time. + + -- Variable: branch.autoSetupMerge + + This variable specifies under what circumstances creating a branch + NAME should result in the variables ‘branch.NAME.merge’ and + ‘branch.NAME.remote’ being set according to the starting point used + to create the branch. If the starting point isn’t a branch, then + these variables are never set. + + • When ‘always’ then the variables are set regardless of whether + the starting point is a local or a remote branch. + + • When ‘true’ (the default) then the variables are set when the + starting point is a remote branch, but not when it is a local + branch. + + • When ‘false’ then the variables are never set. + + -- Variable: branch.autoSetupRebase + + This variable specifies whether creating a branch NAME should + result in the variable ‘branch.NAME.rebase’ being set to ‘true’. + + • When ‘always’ then the variable is set regardless of whether + the starting point is a local or a remote branch. + + • When ‘local’ then the variable are set when the starting point + is a local branch, but not when it is a remote branch. + + • When ‘remote’ then the variable are set when the starting + point is a remote branch, but not when it is a local branch. + + • When ‘never’ (the default) then the variable is never set. + + Note that the respective commands always change the repository-local +values. If you want to change the global value, which is used when the +local value is undefined, then you have to do so on the command line, +e.g.: + + git config --global remote.autoSetupMerge always + + For more information about these variables you should also see + + *note (gitman)git-config::. Also see *note (gitman)git-branch::. , +*note (gitman)git-checkout::. and *note Pushing::. + + -- User Option: magit-prefer-remote-upstream + + This option controls whether commands that read a branch from the + user and then set it as the upstream branch, offer a local or a + remote branch as default completion candidate, when they have the + choice. + + This affects all commands that use ‘magit-read-upstream-branch’ or + ‘magit-read-starting-point’, which includes all commands that + change the upstream and many which create new branches. + + +File: magit.info, Node: Auxiliary Branch Commands, Prev: Branch Git Variables, Up: Branching + +6.6.4 Auxiliary Branch Commands +------------------------------- + +These commands are not available from the transient ‘magit-branch’ by +default. + + -- Command: magit-branch-shelve + + This command shelves a branch. This is done by deleting the + branch, and creating a new reference "refs/shelved/BRANCH-NAME" + pointing at the same commit as the branch pointed at. If the + deleted branch had a reflog, then that is preserved as the reflog + of the new reference. + + This is useful if you want to move a branch out of sight, but are + not ready to completely discard it yet. + + -- Command: magit-branch-unshelve + + This command unshelves a branch that was previously shelved using + ‘magit-branch-shelve’. This is done by deleting the reference + "refs/shelved/BRANCH-NAME" and creating a branch "BRANCH-NAME" + pointing at the same commit as the deleted reference pointed at. + If the deleted reference had a reflog, then that is restored as the + reflog of the branch. + + +File: magit.info, Node: Merging, Next: Resolving Conflicts, Prev: Branching, Up: Manipulating + +6.7 Merging +=========== + +Also see *note (gitman)git-merge::. For information on how to resolve +merge conflicts see the next section. + +‘m’ (‘magit-merge’) + + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. + + When no merge is in progress, then the transient features the +following suffix commands. + +‘m m’ (‘magit-merge-plain’) + + This command merges another branch or an arbitrary revision into + the current branch. The branch or revision to be merged is read in + the minibuffer and defaults to the branch at point. + + Unless there are conflicts or a prefix argument is used, then the + resulting merge commit uses a generic commit message, and the user + does not get a chance to inspect or change it before the commit is + created. With a prefix argument this does not actually create the + merge commit, which makes it possible to inspect how conflicts were + resolved and to adjust the commit message. + +‘m e’ (‘magit-merge-editmsg’) + + This command merges another branch or an arbitrary revision into + the current branch and opens a commit message buffer, so that the + user can make adjustments. The commit is not actually created + until the user finishes with ‘C-c C-c’. + +‘m n’ (‘magit-merge-nocommit’) + + This command merges another branch or an arbitrary revision into + the current branch, but does not actually create the merge commit. + The user can then further adjust the merge, even when automatic + conflict resolution succeeded and/or adjust the commit message. + +‘m a’ (‘magit-merge-absorb’) + + This command merges another local branch into the current branch + and then removes the former. + + Before the source branch is merged, it is first force pushed to its + push-remote, provided the respective remote branch already exists. + This ensures that the respective pull-request (if any) won’t get + stuck on some obsolete version of the commits that are being + merged. Finally, if ‘magit-branch-pull-request’ was used to create + the merged branch, then the respective remote branch is also + removed. + +‘m i’ (‘magit-merge-into’) + + This command merges the current branch into another local branch + and then removes the former. The latter becomes the new current + branch. + + Before the source branch is merged, it is first force pushed to its + push-remote, provided the respective remote branch already exists. + This ensures that the respective pull-request (if any) won’t get + stuck on some obsolete version of the commits that are being + merged. Finally, if ‘magit-branch-pull-request’ was used to create + the merged branch, then the respective remote branch is also + removed. + +‘m s’ (‘magit-merge-squash’) + + This command squashes the changes introduced by another branch or + an arbitrary revision into the current branch. This only applies + the changes made by the squashed commits. No information is + preserved that would allow creating an actual merge commit. + Instead of this command you should probably use a command from the + apply transient. + +‘m p’ (‘magit-merge-preview’) + + This command shows a preview of merging another branch or an + arbitrary revision into the current branch. + + When a merge is in progress, then the transient instead features the +following suffix commands. + +‘m m’ (‘magit-merge’) + + After the user resolved conflicts, this command proceeds with the + merge. If some conflicts weren’t resolved, then this command + fails. + +‘m a’ (‘magit-merge-abort’) + + This command aborts the current merge operation. + + +File: magit.info, Node: Resolving Conflicts, Next: Rebasing, Prev: Merging, Up: Manipulating + +6.8 Resolving Conflicts +======================= + +When merging branches (or otherwise combining or changing history) +conflicts can occur. If you edited two completely different parts of +the same file in two branches and then merge one of these branches into +the other, then Git can resolve that on its own, but if you edit the +same area of a file, then a human is required to decide how the two +versions, or "sides of the conflict", are to be combined into one. + + Here we can only provide a brief introduction to the subject and +point you toward some tools that can help. If you are new to this, then +please also consult Git’s own documentation as well as other resources. + + If a file has conflicts and Git cannot resolve them by itself, then +it puts both versions into the affected file along with special markers +whose purpose is to denote the boundaries of the unresolved part of the +file and between the different versions. These boundary lines begin +with the strings consisting of six times the same character, one of ‘<’, +‘|’, ‘=’ and ‘>’ and are followed by information about the source of the +respective versions, e.g.: + + <<<<<<< HEAD + Take the blue pill. + ======= + Take the red pill. + >>>>>>> feature + + In this case you have chosen to take the red pill on one branch and +on another you picked the blue pill. Now that you are merging these two +diverging branches, Git cannot possibly know which pill you want to +take. + + To resolve that conflict you have to create a version of the affected +area of the file by keeping only one of the sides, possibly by editing +it in order to bring in the changes from the other side, remove the +other versions as well as the markers, and then stage the result. A +possible resolution might be: + + Take both pills. + + Often it is useful to see not only the two sides of the conflict but +also the "original" version from before the same area of the file was +modified twice on different branches. Instruct Git to insert that +version as well by running this command once: + + git config --global merge.conflictStyle diff3 + + The above conflict might then have looked like this: + + <<<<<<< HEAD + Take the blue pill. + ||||||| merged common ancestors + Take either the blue or the red pill, but not both. + ======= + Take the red pill. + >>>>>>> feature + + If that were the case, then the above conflict resolution would not +have been correct, which demonstrates why seeing the original version +alongside the conflicting versions can be useful. + + You can perform the conflict resolution completely by hand, but Emacs +also provides some packages that help in the process: Smerge, Ediff +(*note (ediff)Top::), and Emerge (*note (emacs)Emerge::). Magit does +not provide its own tools for conflict resolution, but it does make +using Smerge and Ediff more convenient. (Ediff supersedes Emerge, so +you probably don’t want to use the latter anyway.) + + In the Magit status buffer, files with unresolved conflicts are +listed in the "Unstaged changes" and/or "Staged changes" sections. They +are prefixed with the word "unmerged", which in this context essentially +is a synonym for "unresolved". + + Pressing ‘RET’ while point is on such a file section shows a buffer +visiting that file, turns on ‘smerge-mode’ in that buffer, and places +point inside the first area with conflicts. You should then resolve +that conflict using regular edit commands and/or Smerge commands. + + Unfortunately Smerge does not have a manual, but you can get a list +of commands and binding ‘C-c ^ C-h’ and press ‘RET’ while point is on a +command name to read its documentation. + + Normally you would edit one version and then tell Smerge to keep only +that version. Use ‘C-c ^ m’ (‘smerge-keep-mine’) to keep the ‘HEAD’ +version or ‘C-c ^ o’ (‘smerge-keep-other’) to keep the version that +follows "|||||||". Then use ‘C-c ^ n’ to move to the next conflicting +area in the same file. Once you are done resolving conflicts, return to +the Magit status buffer. The file should now be shown as "modified", no +longer as "unmerged", because Smerge automatically stages the file when +you save the buffer after resolving the last conflict. + + Alternatively you could use Ediff, which uses separate buffers for +the different versions of the file. To resolve conflicts in a file +using Ediff press ‘e’ while point is on such a file in the status +buffer. + + Ediff can be used for other purposes as well. For more information +on how to enter Ediff from Magit, see *note Ediffing::. Explaining how +to use Ediff is beyond the scope of this manual, instead see *note +(ediff)Top::. + + If you are unsure whether you should Smerge or Ediff, then use the +former. It is much easier to understand and use, and except for truly +complex conflicts, the latter is usually overkill. + + +File: magit.info, Node: Rebasing, Next: Cherry Picking, Prev: Resolving Conflicts, Up: Manipulating + +6.9 Rebasing +============ + +Also see *note (gitman)git-rebase::. For information on how to resolve +conflicts that occur during rebases see the preceding section. + +‘r’ (‘magit-rebase’) + + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. + + When no rebase is in progress, then the transient features the +following suffix commands. + + Using one of these commands _starts_ a rebase sequence. Git might +then stop somewhere along the way, either because you told it to do so, +or because applying a commit failed due to a conflict. When that +happens, then the status buffer shows information about the rebase +sequence which is in progress in a section similar to a log section. +See *note Information About In-Progress Rebase::. + + For information about the upstream and the push-remote, see *note The +Two Remotes::. + +‘r p’ (‘magit-rebase-onto-pushremote’) + + This command rebases the current branch onto its push-remote. + + When ‘magit-remote-set-if-missing’ is non-nil and the push-remote + is not configured, then configure it before rebasing. With a + prefix argument let the user change the push-remote before rebasing + onto it. + +‘r u’ (‘magit-rebase-onto-upstream’) + + This command rebases the current branch onto its upstream branch. + + When ‘magit-remote-set-if-missing’ is non-nil and the upstream is + not configured, then configure it before rebasing. With a prefix + argument let the user change the upstream before rebasing onto it. + +‘r e’ (‘magit-rebase-branch’) + + This command rebases the current branch onto a branch read in the + minibuffer. All commits that are reachable from head but not from + the selected branch TARGET are being rebased. + +‘r s’ (‘magit-rebase-subset’) + + This command starts a non-interactive rebase sequence to transfer + commits from START to ‘HEAD’ onto NEWBASE. START has to be + selected from a list of recent commits. + + By default Magit uses the ‘--autostash’ argument, which causes +uncommitted changes to be stored in a stash before the rebase begins. +These changes are restored after the rebase completes and if possible +the stash is removed. If the stash does not apply cleanly, then the +stash is not removed. In case something goes wrong when resolving the +conflicts, this allows you to start over. + + Even though one of the actions is dedicated to interactive rebases, +the transient also features the infix argument ‘--interactive’. This +can be used to turn one of the other, non-interactive rebase variants +into an interactive rebase. + + For example if you want to clean up a feature branch and at the same +time rebase it onto ‘master’, then you could use ‘r-iu’. But we +recommend that you instead do that in two steps. First use ‘ri’ to +cleanup the feature branch, and then in a second step ‘ru’ to rebase it +onto ‘master’. That way if things turn out to be more complicated than +you thought and/or you make a mistake and have to start over, then you +only have to redo half the work. + + Explicitly enabling ‘--interactive’ won’t have an effect on the +following commands as they always use that argument anyway, even if it +is not enabled in the transient. + +‘r i’ (‘magit-rebase-interactive’) + + This command starts an interactive rebase sequence. + +‘r f’ (‘magit-rebase-autosquash’) + + This command combines squash and fixup commits with their intended + targets. + +‘r m’ (‘magit-rebase-edit-commit’) + + This command starts an interactive rebase sequence that lets the + user edit a single older commit. + +‘r w’ (‘magit-rebase-reword-commit’) + + This command starts an interactive rebase sequence that lets the + user reword a single older commit. + +‘r k’ (‘magit-rebase-remove-commit’) + + This command removes a single older commit using rebase. + + When a rebase is in progress, then the transient instead features the +following suffix commands. + +‘r r’ (‘magit-rebase-continue’) + + This command restart the current rebasing operation. + + In some cases this pops up a commit message buffer for you do edit. + With a prefix argument the old message is reused as-is. + +‘r s’ (‘magit-rebase-skip’) + + This command skips the current commit and restarts the current + rebase operation. + +‘r e’ (‘magit-rebase-edit’) + + This command lets the user edit the todo list of the current rebase + operation. + +‘r a’ (‘magit-rebase-abort’) + + This command aborts the current rebase operation, restoring the + original branch. + +* Menu: + +* Editing Rebase Sequences:: +* Information About In-Progress Rebase:: + + +File: magit.info, Node: Editing Rebase Sequences, Next: Information About In-Progress Rebase, Up: Rebasing + +6.9.1 Editing Rebase Sequences +------------------------------ + +‘C-c C-c’ (‘with-editor-finish’) + + Finish the current editing session by returning with exit code 0. + Git then uses the rebase instructions it finds in the file. + +‘C-c C-k’ (‘with-editor-cancel’) + + Cancel the current editing session by returning with exit code 1. + Git then forgoes starting the rebase sequence. + +‘RET’ (‘git-rebase-show-commit’) + + Show the commit on the current line in another buffer and select + that buffer. + +‘SPC’ (‘git-rebase-show-or-scroll-up’) + + Show the commit on the current line in another buffer without + selecting that buffer. If the revision buffer is already visible + in another window of the current frame, then instead scroll that + window up. + +‘DEL’ (‘git-rebase-show-or-scroll-down’) + + Show the commit on the current line in another buffer without + selecting that buffer. If the revision buffer is already visible + in another window of the current frame, then instead scroll that + window down. + +‘p’ (‘git-rebase-backward-line’) + + Move to previous line. + +‘n’ (‘forward-line’) + + Move to next line. + +‘M-p’ (‘git-rebase-move-line-up’) + + Move the current commit (or command) up. + +‘M-n’ (‘git-rebase-move-line-down’) + + Move the current commit (or command) down. + +‘r’ (‘git-rebase-reword’) + + Edit message of commit on current line. + +‘e’ (‘git-rebase-edit’) + + Stop at the commit on the current line. + +‘s’ (‘git-rebase-squash’) + + Meld commit on current line into previous commit, and edit message. + +‘f’ (‘git-rebase-fixup’) + + Meld commit on current line into previous commit, discarding the + current commit’s message. + +‘k’ (‘git-rebase-kill-line’) + + Kill the current action line. + +‘c’ (‘git-rebase-pick’) + + Use commit on current line. + +‘x’ (‘git-rebase-exec’) + + Insert a shell command to be run after the proceeding commit. + + If there already is such a command on the current line, then edit + that instead. With a prefix argument insert a new command even + when there already is one on the current line. With empty input + remove the command on the current line, if any. + +‘b’ (‘git-rebase-break’) + + Insert a break action before the current line, instructing Git to + return control to the user. + +‘y’ (‘git-rebase-insert’) + + Read an arbitrary commit and insert it below current line. + +‘C-x u’ (‘git-rebase-undo’) + + Undo some previous changes. Like ‘undo’ but works in read-only + buffers. + + -- User Option: git-rebase-auto-advance + + Whether to move to next line after changing a line. + + -- User Option: git-rebase-show-instructions + + Whether to show usage instructions inside the rebase buffer. + + -- User Option: git-rebase-confirm-cancel + + Whether confirmation is required to cancel. + + When a rebase is performed with the ‘--rebase-merges’ option, the +sequence will include a few other types of actions and the following +commands become relevant. + +‘l’ (‘git-rebase-label’) + + This commands inserts a label action or edits the one at point. + +‘t’ (‘git-rebase-reset’) + + This command inserts a reset action or edits the one at point. The + prompt will offer the labels that are currently present in the + buffer. + +‘MM’ (‘git-rebase-merge’) + + The command inserts a merge action or edits the one at point. The + prompt will offer the labels that are currently present in the + buffer. Specifying a message to reuse via ‘-c’ or ‘-C’ is not + supported; an editor will always be invoked for the merge. + +‘Mt’ (‘git-rebase-merge-toggle-editmsg’) + + This command toggles between the ‘-C’ and ‘-c’ options of the merge + action at point. These options both specify a commit whose message + should be reused. The lower-case variant instructs Git to invoke + the editor when creating the merge, allowing the user to edit the + message. + + +File: magit.info, Node: Information About In-Progress Rebase, Prev: Editing Rebase Sequences, Up: Rebasing + +6.9.2 Information About In-Progress Rebase +------------------------------------------ + +While a rebase sequence is in progress, the status buffer features a +section that lists the commits that have already been applied as well as +the commits that still have to be applied. + + The commits are split in two halves. When rebase stops at a commit, +either because the user has to deal with a conflict or because s/he +explicitly requested that rebase stops at that commit, then point is +placed on the commit that separates the two groups, i.e. on ‘HEAD’. +The commits above it have not been applied yet, while the ‘HEAD’ and the +commits below it have already been applied. In between these two groups +of applied and yet-to-be applied commits, there sometimes is a commit +which has been dropped. + + Each commit is prefixed with a word and these words are additionally +shown in different colors to indicate the status of the commits. + + The following colors are used: + + • Yellow commits have not been applied yet. + + • Gray commits have already been applied. + + • The blue commit is the ‘HEAD’ commit. + + • The green commit is the commit the rebase sequence stopped at. If + this is the same commit as ‘HEAD’ (e.g. because you haven’t done + anything yet after rebase stopped at the commit, then this commit + is shown in blue, not green). There can only be a green *and* a + blue commit at the same time, if you create one or more new commits + after rebase stops at a commit. + + • Red commits have been dropped. They are shown for reference only, + e.g. to make it easier to diff. + + Of course these colors are subject to the color-theme in use. + + The following words are used: + + • Commits prefixed with ‘pick’, ‘reword’, ‘edit’, ‘squash’, and + ‘fixup’ have not been applied yet. These words have the same + meaning here as they do in the buffer used to edit the rebase + sequence. See *note Editing Rebase Sequences::. When the + ‘--rebase-merges’ option was specified, ‘reset’, ‘label’, and + ‘merge’ lines may also be present. + + • Commits prefixed with ‘done’ and ‘onto’ have already been applied. + It is possible for such a commit to be the ‘HEAD’, in which case it + is blue. Otherwise it is grey. + + • The commit prefixed with ‘onto’ is the commit on top of which + all the other commits are being re-applied. This commit + itself did not have to be re-applied, it is the commit rebase + did rewind to before starting to re-apply other commits. + + • Commits prefixed with ‘done’ have already been re-applied. + This includes commits that have been re-applied but also new + commits that you have created during the rebase. + + • All other commits, those not prefixed with any of the above words, + are in some way related to the commit at which rebase stopped. + + To determine whether a commit is related to the stopped-at commit + their hashes, trees and patch-ids (1) are being compared. The + commit message is not used for this purpose. + + Generally speaking commits that are related to the stopped-at + commit can have any of the used colors, though not all color/word + combinations are possible. + + Words used for stopped-at commits are: + + • When a commit is prefixed with ‘void’, then that indicates + that Magit knows for sure that all the changes in that commit + have been applied using several new commits. This commit is + no longer reachable from ‘HEAD’, and it also isn’t one of the + commits that will be applied when resuming the session. + + • When a commit is prefixed with ‘join’, then that indicates + that the rebase sequence stopped at that commit due to a + conflict - you now have to join (merge) the changes with what + has already been applied. In a sense this is the commit + rebase stopped at, but while its effect is already in the + index and in the worktree (with conflict markers), the commit + itself has not actually been applied yet (it isn’t the + ‘HEAD’). So it is shown in yellow, like the other commits + that still have to be applied. + + • When a commit is prefixed with ‘stop’ or a _blue_ or _green_ + ‘same’, then that indicates that rebase stopped at this + commit, that it is still applied or has been applied again, + and that at least its patch-id is unchanged. + + • When a commit is prefixed with ‘stop’, then that + indicates that rebase stopped at that commit because you + requested that earlier, and its patch-id is unchanged. + It might even still be the exact same commit. + + • When a commit is prefixed with a _blue_ or _green_ + ‘same’, then that indicates that while its tree or hash + changed, its patch-id did not. If it is blue, then it is + the ‘HEAD’ commit (as always for blue). When it is + green, then it no longer is ‘HEAD’ because other commit + have been created since (but before continuing the + rebase). + + • When a commit is prefixed with ‘goal’, a _yellow_ ‘same,’ or + ‘work’, then that indicates that rebase applied that commit + but that you then reset ‘HEAD’ to an earlier commit (likely to + split it up into multiple commits), and that there are some + uncommitted changes remaining which likely (but not + necessarily) originate from that commit. + + • When a commit is prefixed with ‘goal’, then that + indicates that it is still possible to create a new + commit with the exact same tree (the "goal") without + manually editing any files, by committing the index, or + by staging all changes and then committing that. This is + the case when the original tree still exists in the index + or worktree in untainted form. + + • When a commit is prefixed with a yellow ‘same’, then that + indicates that it is no longer possible to create a + commit with the exact same tree, but that it is still + possible to create a commit with the same patch-id. This + would be the case if you created a new commit with other + changes, but the changes from the original commit still + exist in the index or working tree in untainted form. + + • When a commit is prefixed with ‘work’, then that + indicates that you reset ‘HEAD’ to an earlier commit, and + that there are some staged and/or unstaged changes + (likely, but not necessarily) originating from that + commit. However it is no longer possible to create a new + commit with the same tree or at least the same patch-id + because you have already made other changes. + + • When a commit is prefixed with ‘poof’ or ‘gone’, then that + indicates that rebase applied that commit but that you then + reset ‘HEAD’ to an earlier commit (likely to split it up into + multiple commits), and that there are no uncommitted changes. + + • When a commit is prefixed with ‘poof’, then that + indicates that it is no longer reachable from ‘HEAD’, but + that it has been replaced with one or more commits, which + together have the exact same effect. + + • When a commit is prefixed with ‘gone’, then that + indicates that it is no longer reachable from ‘HEAD’ and + that we also cannot determine whether its changes are + still in effect in one or more new commits. They might + be, but if so, then there must also be other changes + which makes it impossible to know for sure. + + Do not worry if you do not fully understand the above. That’s okay, +you will acquire a good enough understanding through practice. + + For other sequence operations such as cherry-picking, a similar +section is displayed, but they lack some of the features described +above, due to limitations in the git commands used to implement them. +Most importantly these sequences only support "picking" a commit but not +other actions such as "rewording", and they do not keep track of the +commits which have already been applied. + + ---------- Footnotes ---------- + + (1) The patch-id is a hash of the _changes_ introduced by a commit. +It differs from the hash of the commit itself, which is a hash of the +result of applying that change (i.e. the resulting trees and blobs) as +well as author and committer information, the commit message, and the +hashes of the parents of the commit. The patch-id hash on the other +hand is created only from the added and removed lines, even line numbers +and whitespace changes are ignored when calculating this hash. The +patch-ids of two commits can be used to answer the question "Do these +commits make the same change?". + + +File: magit.info, Node: Cherry Picking, Next: Resetting, Prev: Rebasing, Up: Manipulating + +6.10 Cherry Picking +=================== + +Also see *note (gitman)git-cherry-pick::. + +‘A’ (‘magit-cherry-pick’) + + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. + + When no cherry-pick or revert is in progress, then the transient +features the following suffix commands. + +‘A A’ (‘magit-cherry-copy’) + + This command copies COMMITS from another branch onto the current + branch. If the region selects multiple commits, then those are + copied, without prompting. Otherwise the user is prompted for a + commit or range, defaulting to the commit at point. + +‘A a’ (‘magit-cherry-apply’) + + This command applies the changes in COMMITS from another branch + onto the current branch. If the region selects multiple commits, + then those are used, without prompting. Otherwise the user is + prompted for a commit or range, defaulting to the commit at point. + + This command also has a top-level binding, which can be invoked + without using the transient by typing ‘a’ at the top-level. + + The following commands not only apply some commits to some branch, +but also remove them from some other branch. The removal is performed +using either ‘git-update-ref’ or if necessary ‘git-rebase’. Both +applying commits as well as removing them using ‘git-rebase’ can lead to +conflicts. If that happens, then these commands abort and you not only +have to resolve the conflicts but also finish the process the same way +you would have to if these commands didn’t exist at all. + +‘A h’ (‘magit-cherry-harvest’) + + This command moves the selected COMMITS that must be located on + another BRANCH onto the current branch instead, removing them from + the former. When this command succeeds, then the same branch is + current as before. + + Applying the commits on the current branch or removing them from + the other branch can lead to conflicts. When that happens, then + this command stops and you have to resolve the conflicts and then + finish the process manually. + +‘A d’ (‘magit-cherry-donate’) + + This command moves the selected COMMITS from the current branch + onto another existing BRANCH, removing them from the former. When + this command succeeds, then the same branch is current as before. + + Applying the commits on the other branch or removing them from the + current branch can lead to conflicts. When that happens, then this + command stops and you have to resolve the conflicts and then finish + the process manually. + +‘A n’ (‘magit-cherry-spinout’) + + This command moves the selected COMMITS from the current branch + onto a new branch BRANCH, removing them from the former. When this + command succeeds, then the same branch is current as before. + + Applying the commits on the other branch or removing them from the + current branch can lead to conflicts. When that happens, then this + command stops and you have to resolve the conflicts and then finish + the process manually. + +‘A s’ (‘magit-cherry-spinoff’) + + This command moves the selected COMMITS from the current branch + onto a new branch BRANCH, removing them from the former. When this + command succeeds, then the new branch is checked out. + + Applying the commits on the other branch or removing them from the + current branch can lead to conflicts. When that happens, then this + command stops and you have to resolve the conflicts and then finish + the process manually. + + When a cherry-pick or revert is in progress, then the transient +instead features the following suffix commands. + +‘A A’ (‘magit-sequence-continue’) + + Resume the current cherry-pick or revert sequence. + +‘A s’ (‘magit-sequence-skip’) + + Skip the stopped at commit during a cherry-pick or revert sequence. + +‘A a’ (‘magit-sequence-abort’) + + Abort the current cherry-pick or revert sequence. This discards + all changes made since the sequence started. + +* Menu: + +* Reverting:: + + +File: magit.info, Node: Reverting, Up: Cherry Picking + +6.10.1 Reverting +---------------- + +‘V’ (‘magit-revert’) + + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. + + When no cherry-pick or revert is in progress, then the transient +features the following suffix commands. + +‘V V’ (‘magit-revert-and-commit’) + + Revert a commit by creating a new commit. Prompt for a commit, + defaulting to the commit at point. If the region selects multiple + commits, then revert all of them, without prompting. + +‘V v’ (‘magit-revert-no-commit’) + + Revert a commit by applying it in reverse to the working tree. + Prompt for a commit, defaulting to the commit at point. If the + region selects multiple commits, then revert all of them, without + prompting. + + When a cherry-pick or revert is in progress, then the transient +instead features the following suffix commands. + +‘V A’ (‘magit-sequence-continue’) + + Resume the current cherry-pick or revert sequence. + +‘V s’ (‘magit-sequence-skip’) + + Skip the stopped at commit during a cherry-pick or revert sequence. + +‘V a’ (‘magit-sequence-abort’) + + Abort the current cherry-pick or revert sequence. This discards + all changes made since the sequence started. + + +File: magit.info, Node: Resetting, Next: Stashing, Prev: Cherry Picking, Up: Manipulating + +6.11 Resetting +============== + +Also see *note (gitman)git-reset::. + +‘x’ (‘magit-reset-quickly’) + + Reset the ‘HEAD’ and index to some commit read from the user and + defaulting to the commit at point, and possibly also reset the + working tree. With a prefix argument reset the working tree + otherwise don’t. + +‘X m’ (‘magit-reset-mixed’) + + Reset the ‘HEAD’ and index to some commit read from the user and + defaulting to the commit at point. The working tree is kept as-is. + +‘X s’ (‘magit-reset-soft’) + + Reset the ‘HEAD’ to some commit read from the user and defaulting + to the commit at point. The index and the working tree are kept + as-is. + +‘X h’ (‘magit-reset-hard’) + + Reset the ‘HEAD’, index, and working tree to some commit read from + the user and defaulting to the commit at point. + +‘X i’ (‘magit-reset-index’) + + Reset the index to some commit read from the user and defaulting to + the commit at point. Keep the ‘HEAD’ and working tree as-is, so if + the commit refers to the ‘HEAD’, then this effectively unstages all + changes. + +‘X w’ (‘magit-reset-worktree’) + + Reset the working tree to some commit read from the user and + defaulting to the commit at point. Keep the ‘HEAD’ and index + as-is. + +‘X f’ (‘magit-file-checkout’) + + Update file in the working tree and index to the contents from a + revision. Both the revision and file are read from the user. + + +File: magit.info, Node: Stashing, Prev: Resetting, Up: Manipulating + +6.12 Stashing +============= + +Also see *note (gitman)git-stash::. + +‘z’ (‘magit-stash’) + + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. + +‘z z’ (‘magit-stash-both’) + + Create a stash of the index and working tree. Untracked files are + included according to infix arguments. One prefix argument is + equivalent to ‘--include-untracked’ while two prefix arguments are + equivalent to ‘--all’. + +‘z i’ (‘magit-stash-index’) + + Create a stash of the index only. Unstaged and untracked changes + are not stashed. + +‘z w’ (‘magit-stash-worktree’) + + Create a stash of unstaged changes in the working tree. Untracked + files are included according to infix arguments. One prefix + argument is equivalent to ‘--include-untracked’ while two prefix + arguments are equivalent to ‘--all’. + +‘z x’ (‘magit-stash-keep-index’) + + Create a stash of the index and working tree, keeping index intact. + Untracked files are included according to infix arguments. One + prefix argument is equivalent to ‘--include-untracked’ while two + prefix arguments are equivalent to ‘--all’. + +‘z Z’ (‘magit-snapshot-both’) + + Create a snapshot of the index and working tree. Untracked files + are included according to infix arguments. One prefix argument is + equivalent to ‘--include-untracked’ while two prefix arguments are + equivalent to ‘--all’. + +‘z I’ (‘magit-snapshot-index’) + + Create a snapshot of the index only. Unstaged and untracked + changes are not stashed. + +‘z W’ (‘magit-snapshot-worktree’) + + Create a snapshot of unstaged changes in the working tree. + Untracked files are included according to infix arguments. One + prefix argument is equivalent to ‘--include-untracked’ while two + prefix arguments are equivalent to ‘--all’-. + +‘z a’ (‘magit-stash-apply’) + + Apply a stash to the working tree. Try to preserve the stash + index. If that fails because there are staged changes, apply + without preserving the stash index. + +‘z p’ (‘magit-stash-pop’) + + Apply a stash to the working tree and remove it from stash list. + Try to preserve the stash index. If that fails because there are + staged changes, apply without preserving the stash index and forgo + removing the stash. + +‘z k’ (‘magit-stash-drop’) + + Remove a stash from the stash list. When the region is active, + offer to drop all contained stashes. + +‘z v’ (‘magit-stash-show’) + + Show all diffs of a stash in a buffer. + +‘z b’ (‘magit-stash-branch’) + + Create and checkout a new BRANCH from STASH. The branch starts at + the commit that was current when the stash was created. + +‘z B’ (‘magit-stash-branch-here’) + + Create and checkout a new BRANCH using ‘magit-branch’ with the + current branch or ‘HEAD’ as the starting-point. Then apply STASH, + dropping it if it applies cleanly. + +‘z f’ (‘magit-stash-format-patch’) + + Create a patch from STASH. + +‘k’ (‘magit-stash-clear’) + + Remove all stashes saved in REF’s reflog by deleting REF. + +‘z l’ (‘magit-stash-list’) + + List all stashes in a buffer. + + -- User Option: magit-stashes-margin + + This option specifies whether the margin is initially shown in + stashes buffers and how it is formatted. + + The value has the form ‘(INIT STYLE WIDTH AUTHOR AUTHOR-WIDTH)’. + + • If INIT is non-nil, then the margin is shown initially. + + • STYLE controls how to format the author or committer date. It + can be one of ‘age’ (to show the age of the commit), + ‘age-abbreviated’ (to abbreviate the time unit to a + character), or a string (suitable for ‘format-time-string’) to + show the actual date. Option + ‘magit-log-margin-show-committer-date’ controls which date is + being displayed. + + • WIDTH controls the width of the margin. This exists for + forward compatibility and currently the value should not be + changed. + + • AUTHOR controls whether the name of the author is also shown + by default. + + • AUTHOR-WIDTH has to be an integer. When the name of the + author is shown, then this specifies how much space is used to + do so. + + +File: magit.info, Node: Transferring, Next: Miscellaneous, Prev: Manipulating, Up: Top + +7 Transferring +************** + +* Menu: + +* Remotes:: +* Fetching:: +* Pulling:: +* Pushing:: +* Plain Patches:: +* Maildir Patches:: + + +File: magit.info, Node: Remotes, Next: Fetching, Up: Transferring + +7.1 Remotes +=========== + +* Menu: + +* Remote Commands:: +* Remote Git Variables:: + + +File: magit.info, Node: Remote Commands, Next: Remote Git Variables, Up: Remotes + +7.1.1 Remote Commands +--------------------- + +The transient prefix command ‘magit-remote’ is used to add remotes and +to make changes to existing remotes. This command only deals with +remotes themselves, not with branches or the transfer of commits. Those +features are available from separate transient commands. + + Also see *note (gitman)git-remote::. + +‘M’ (‘magit-remote’) + + This transient prefix command binds the following suffix commands + and displays them in a temporary buffer until a suffix is invoked. + + By default it also binds and displays the values of some + remote-related Git variables and allows changing their values. + + -- User Option: magit-remote-direct-configure + + This option controls whether remote-related Git variables are + accessible directly from the transient ‘magit-remote’. + + If ‘t’ (the default) and a local branch is checked out, then + ‘magit-remote’ features the variables for the upstream remote of + that branch, or if ‘HEAD’ is detached, for ‘origin’, provided that + exists. + + If ‘nil’, then ‘magit-remote-configure’ has to be used to do so. + +‘M C’ (‘magit-remote-configure’) + + This transient prefix command binds commands that set the value of + remote-related variables and displays them in a temporary buffer + until the transient is exited. + + With a prefix argument, this command always prompts for a remote. + + Without a prefix argument this depends on whether it was invoked as + a suffix of ‘magit-remote’ and on the + ‘magit-remote-direct-configure’ option. If ‘magit-remote’ already + displays the variables for the upstream, then it does not make + sense to invoke another transient that displays them for the same + remote. In that case this command prompts for a remote. + + The variables are described in *note Remote Git Variables::. + +‘M a’ (‘magit-remote-add’) + + This command add a remote and fetches it. The remote name and url + are read in the minibuffer. + +‘M r’ (‘magit-remote-rename’) + + This command renames a remote. Both the old and the new names are + read in the minibuffer. + +‘M u’ (‘magit-remote-set-url’) + + This command changes the url of a remote. Both the remote and the + new url are read in the minibuffer. + +‘M k’ (‘magit-remote-remove’) + + This command deletes a remote, read in the minibuffer. + +‘M p’ (‘magit-remote-prune’) + + This command removes stale remote-tracking branches for a remote + read in the minibuffer. + +‘M P’ (‘magit-remote-prune-refspecs’) + + This command removes stale refspecs for a remote read in the + minibuffer. + + A refspec is stale if there no longer exists at least one branch on + the remote that would be fetched due to that refspec. A stale + refspec is problematic because its existence causes Git to refuse + to fetch according to the remaining non-stale refspecs. + + If only stale refspecs remain, then this command offers to either + delete the remote or to replace the stale refspecs with the default + refspec ("+refs/heads/*:refs/remotes/REMOTE/*"). + + This command also removes the remote-tracking branches that were + created due to the now stale refspecs. Other stale branches are + not removed. + + -- User Option: magit-remote-add-set-remote.pushDefault + + This option controls whether the user is asked whether they want to + set ‘remote.pushDefault’ after adding a remote. + + If ‘ask’, then users is always ask. If ‘ask-if-unset’, then the + user is only if the variable isn’t set already. If ‘nil’, then the + user isn’t asked and the variable isn’t set. If the value is a + string, then the variable is set without the user being asked, + provided that the name of the added remote is equal to that string + and the variable isn’t already set. + + +File: magit.info, Node: Remote Git Variables, Prev: Remote Commands, Up: Remotes + +7.1.2 Remote Git Variables +-------------------------- + +These variables can be set from the transient prefix command +‘magit-remote-configure’. By default they can also be set from +‘magit-remote’. See *note Remote Commands::. + + -- Variable: remote.NAME.url + + This variable specifies the url of the remote named NAME. It can + have multiple values. + + -- Variable: remote.NAME.fetch + + The refspec used when fetching from the remote named NAME. It can + have multiple values. + + -- Variable: remote.NAME.pushurl + + This variable specifies the url used for fetching from the remote + named NAME. If it is not specified, then ‘remote.NAME.url’ is used + instead. It can have multiple values. + + -- Variable: remote.NAME.push + + The refspec used when pushing to the remote named NAME. It can + have multiple values. + + -- Variable: remote.NAME.tagOpts + + This variable specifies what tags are fetched by default. If the + value is ‘--no-tags’ then no tags are fetched. If the value is + ‘--tags’, then all tags are fetched. If this variable has no + value, then only tags are fetched that are reachable from fetched + branches. + + -- User Option: magit-remote-set-if-missing + + This option controls whether missing remotes are configured before + fetching, pulling, pushing and rebasing. + + When ‘nil’, then commands such as ‘magit-pull-from-upstream’ and + ‘magit-rebase-onto-uptream’ are not available as suffix commands if + the push-remote or upstream is not configured. + + When ‘non-nil’, then these commands are always available in their + respective transient, but if the required configuration is missing, + then they do appear in a way that indicates that this is the case. + If the user invokes such a command, then it asks for the necessary + configuration, stores the configuration, and only then performs the + action. + + This option also affects whether the argument ‘--set-upstream’ is + available in ‘magit-push’. If the value is ‘non-nil’, then that + argument would be redundant. But note that changing the value of + this option does not take affect immediately, the argument will + only be added or removed after restarting Emacs. + + +File: magit.info, Node: Fetching, Next: Pulling, Prev: Remotes, Up: Transferring + +7.2 Fetching +============ + +Also see *note (gitman)git-fetch::. For information about the upstream +and the push-remote, see *note The Two Remotes::. + +‘f’ (‘magit-fetch’) + + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. + +‘f p’ (‘magit-fetch-from-pushremote’) + + This command fetches from the push-remote of the current branch. + + When ‘magit-remote-set-if-missing’ is non-nil and the push-remote + is not configured, then configure it before fetching. With a + prefix argument let the user change the push-remote before fetching + from it. + +‘f u’ (‘magit-fetch-from-upstream’) + + This command fetch from the upstream of the current branch. + + When ‘magit-remote-set-if-missing’ is non-nil and the upstream is + not configured, then configure it before fetching. With a prefix + argument let the user change the upstream before fetching from it. + +‘f e’ (‘magit-fetch-other’) + + This command fetch from a repository read from the minibuffer. + +‘f o’ (‘magit-fetch-branch’) + + This command fetches a branch from a remote, both of which are read + from the minibuffer. + +‘f r’ (‘magit-fetch-refspec’) + + This command fetches from a remote using an explicit refspec, both + of which are read from the minibuffer. + +‘f a’ (‘magit-fetch-all’) + + This command fetches from all remotes. + +‘f m’ (‘magit-submodule-fetch’) + + This command fetches all submodules. With a prefix argument it + fetches all remotes of all submodules. + + -- User Option: magit-pull-or-fetch + + By default fetch and pull commands are available from separate + transient prefix command. Setting this to ‘t’ adds some (but not + all) of the above suffix commands to the ‘magit-pull’ transient. + + If you do that, then you might also want to change the key binding + for these prefix commands, e.g.: + + (setq magit-pull-or-fetch t) + (define-key magit-mode-map "f" 'magit-pull) ; was magit-fetch + (define-key magit-mode-map "F" nil) ; was magit-pull + + +File: magit.info, Node: Pulling, Next: Pushing, Prev: Fetching, Up: Transferring + +7.3 Pulling +=========== + +Also see *note (gitman)git-pull::. For information about the upstream +and the push-remote, see *note The Two Remotes::. + +‘F’ (‘magit-pull’) + + This transient prefix command binds the following suffix commands + and displays them in a temporary buffer until a suffix is invoked. + +‘F p’ (‘magit-pull-from-pushremote’) + + This command pulls from the push-remote of the current branch. + + When ‘magit-remote-set-if-missing’ is non-nil and the push-remote + is not configured, then configure it before pulling. With a prefix + argument let the user change the push-remote before pulling from + it. + +‘F u’ (‘magit-pull-from-upstream’) + + This command pulls from the upstream of the current branch. + + When ‘magit-remote-set-if-missing’ is non-nil and the upstream is + not configured, then configure it before pulling. With a prefix + argument let the user change the upstream before pulling from it. + +‘F e’ (‘magit-pull-branch’) + + This command pulls from a branch read in the minibuffer. + + +File: magit.info, Node: Pushing, Next: Plain Patches, Prev: Pulling, Up: Transferring + +7.4 Pushing +=========== + +Also see *note (gitman)git-push::. For information about the upstream +and the push-remote, see *note The Two Remotes::. + +‘P’ (‘magit-push’) + + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. + +‘P p’ (‘magit-push-current-to-pushremote’) + + This command pushes the current branch to its push-remote. + + When ‘magit-remote-set-if-missing’ is non-nil and the push-remote + is not configured, then configure it before pushing. With a prefix + argument let the user change the push-remote before pushing to it. + +‘P u’ (‘magit-push-current-to-upstream’) + + This command pushes the current branch to its upstream branch. + + When ‘magit-remote-set-if-missing’ is non-nil and the upstream is + not configured, then configure it before pushing. With a prefix + argument let the user change the upstream before pushing to it. + +‘P e’ (‘magit-push-current’) + + This command pushes the current branch to a branch read in the + minibuffer. + +‘P o’ (‘magit-push-other’) + + This command pushes an arbitrary branch or commit somewhere. Both + the source and the target are read in the minibuffer. + +‘P r’ (‘magit-push-refspecs’) + + This command pushes one or multiple refspecs to a remote, both of + which are read in the minibuffer. + + To use multiple refspecs, separate them with commas. Completion is + only available for the part before the colon, or when no colon is + used. + +‘P m’ (‘magit-push-matching’) + + This command pushes all matching branches to another repository. + + If only one remote exists, then push to that. Otherwise prompt for + a remote, offering the remote configured for the current branch as + default. + +‘P t’ (‘magit-push-tags’) + + This command pushes all tags to another repository. + + If only one remote exists, then push to that. Otherwise prompt for + a remote, offering the remote configured for the current branch as + default. + +‘P T’ (‘magit-push-tag’) + + This command pushes a tag to another repository. + + Two more push commands exist, which by default are not available from +the push transient. See their doc-strings for instructions on how to +add them to the transient. + + -- Command: magit-push-implicitly args + + This command pushes somewhere without using an explicit refspec. + + This command simply runs ‘git push -v [ARGS]’. ARGS are the infix + arguments. No explicit refspec arguments are used. Instead the + behavior depends on at least these Git variables: ‘push.default’, + ‘remote.pushDefault’, ‘branch..pushRemote’, + ‘branch..remote’, ‘branch..merge’, and + ‘remote..push’. + + -- Command: magit-push-to-remote remote args + + This command pushes to the remote REMOTE without using an explicit + refspec. The remote is read in the minibuffer. + + This command simply runs ‘git push -v [ARGS] REMOTE’. ARGS are the + infix arguments. No refspec arguments are used. Instead the + behavior depends on at least these Git variables: ‘push.default’, + ‘remote.pushDefault’, ‘branch..pushRemote’, + ‘branch..remote’, ‘branch..merge’, and + ‘remote..push’. + + +File: magit.info, Node: Plain Patches, Next: Maildir Patches, Prev: Pushing, Up: Transferring + +7.5 Plain Patches +================= + +‘W’ (‘magit-patch’) + + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. + +‘W c’ (‘magit-patch-create’) + + This command creates patches for a set commits. If the region + marks several commits, then it creates patches for all of them. + Otherwise it functions as a transient prefix command, which + features several infix arguments and binds itself as a suffix + command. When this command is invoked as a suffix of itself, then + it creates a patch using the specified infix arguments. + +‘w a’ (‘magit-patch-apply’) + + This command applies a patch. This is a transient prefix command, + which features several infix arguments and binds itself as a suffix + command. When this command is invoked as a suffix of itself, then + it applies a patch using the specified infix arguments. + +‘W s’ (‘magit-patch-save’) + + This command creates a patch from the current diff. + + Inside ‘magit-diff-mode’ or ‘magit-revision-mode’ buffers, ‘C-x + C-w’ is also bound to this command. + + It is also possible to save a plain patch file by using ‘C-x C-w’ +inside a ‘magit-diff-mode’ or ‘magit-revision-mode’ buffer. + + +File: magit.info, Node: Maildir Patches, Prev: Plain Patches, Up: Transferring + +7.6 Maildir Patches +=================== + +Also see *note (gitman)git-am::. and *note (gitman)git-apply::. + +‘w’ (‘magit-am’) + + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. + +‘w w’ (‘magit-am-apply-patches’) + + This command applies one or more patches. If the region marks + files, then those are applied as patches. Otherwise this command + reads a file-name in the minibuffer, defaulting to the file at + point. + +‘w m’ (‘magit-am-apply-maildir’) + + This command applies patches from a maildir. + +‘w a’ (‘magit-patch-apply’) + + This command applies a plain patch. For a longer description see + *note Plain Patches::. This command is only available from the + ‘magit-am’ transient for historic reasons. + + When an "am" operation is in progress, then the transient instead +features the following suffix commands. + +‘w w’ (‘magit-am-continue’) + + This command resumes the current patch applying sequence. + +‘w s’ (‘magit-am-skip’) + + This command skips the stopped at patch during a patch applying + sequence. + +‘w a’ (‘magit-am-abort’) + + This command aborts the current patch applying sequence. This + discards all changes made since the sequence started. + + +File: magit.info, Node: Miscellaneous, Next: Customizing, Prev: Transferring, Up: Top + +8 Miscellaneous +*************** + +* Menu: + +* Tagging:: +* Notes:: +* Submodules:: +* Subtree:: +* Worktree:: +* Common Commands:: +* Wip Modes:: +* Minor Mode for Buffers Visiting Files:: +* Minor Mode for Buffers Visiting Blobs:: + + +File: magit.info, Node: Tagging, Next: Notes, Up: Miscellaneous + +8.1 Tagging +=========== + +Also see *note (gitman)git-tag::. + +‘t’ (‘magit-tag’) + + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. + +‘t t’ (‘magit-tag-create’) + + This command creates a new tag with the given NAME at REV. With a + prefix argument it creates an annotate tag. + +‘t r’ (‘magit-tag-release’) + + This commands creates an annotated release tag. It assumes that + release tags match ‘magit-release-tag-regexp’. + + First it prompts for the name of the new tag using the highest + existing tag as initial input and leaving it to the user to + increment the desired part of the version string. + + Then it prompts for the message of the new tag. The proposed tag + message is based on the message of the highest tag, provided that + that contains the corresponding version string and substituting the + new version string for that. Otherwise it proposes something like + "Foo-Bar 1.2.3", given, for example, a TAG "v1.2.3" and a + repository located at something like "/path/to/foo-bar". + + Then it calls "git tag –annotate –sign -m MSG TAG" to create the + tag, regardless of whether these arguments are enabled in the + transient. Finally it shows the refs buffer to let the user + quickly review the result. + +‘t k’ (‘magit-tag-delete’) + + This command deletes one or more tags. If the region marks + multiple tags (and nothing else), then it offers to delete those. + Otherwise, it prompts for a single tag to be deleted, defaulting to + the tag at point. + +‘t p’ (‘magit-tag-prune’) + + This command offers to delete tags missing locally from REMOTE, and + vice versa. + + +File: magit.info, Node: Notes, Next: Submodules, Prev: Tagging, Up: Miscellaneous + +8.2 Notes +========= + +Also see *note (gitman)git-notes::. + +‘T’ (‘magit-notes’) + + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. + +‘T T’ (‘magit-notes-edit’) + + Edit the note attached to a commit, defaulting to the commit at + point. + + By default use the value of Git variable ‘core.notesRef’ or + "refs/notes/commits" if that is undefined. + +‘T r’ (‘magit-notes-remove’) + + Remove the note attached to a commit, defaulting to the commit at + point. + + By default use the value of Git variable ‘core.notesRef’ or + "refs/notes/commits" if that is undefined. + +‘T p’ (‘magit-notes-prune’) + + Remove notes about unreachable commits. + + It is possible to merge one note ref into another. That may result +in conflicts which have to resolved in the temporary worktree +".git/NOTES_MERGE_WORKTREE". + +‘T m’ (‘magit-notes-merge’) + + Merge the notes of a ref read from the user into the current notes + ref. The current notes ref is the value of Git variable + ‘core.notesRef’ or "refs/notes/commits" if that is undefined. + + When a notes merge is in progress then the transient features the +following suffix commands, instead of those listed above. + +‘T c’ (‘magit-notes-merge-commit’) + + Commit the current notes ref merge, after manually resolving + conflicts. + +‘T a’ (‘magit-notes-merge-abort’) + + Abort the current notes ref merge. + + The following variables control what notes reference ‘magit-notes-*’, +‘git notes’ and ‘git show’ act on and display. Both the local and +global values are displayed and can be modified. + + -- Variable: core.notesRef + + This variable specifies the notes ref that is displayed by default + and which commands act on by default. + + -- Variable: notes.displayRef + + This variable specifies additional notes ref to be displayed in + addition to the ref specified by ‘core.notesRef’. It can have + multiple values and may end with ‘*’ to display all refs in the + ‘refs/notes/’ namespace (or ‘**’ if some names contain slashes). + + +File: magit.info, Node: Submodules, Next: Subtree, Prev: Notes, Up: Miscellaneous + +8.3 Submodules +============== + +Also see *note (gitman)git-submodule::. + +* Menu: + +* Listing Submodules:: +* Submodule Transient:: + + +File: magit.info, Node: Listing Submodules, Next: Submodule Transient, Up: Submodules + +8.3.1 Listing Submodules +------------------------ + +The command ‘magit-list-submodules’ displays a list of the current +repository’s submodules in a separate buffer. It’s also possible to +display information about submodules directly in the status buffer of +the super-repository by adding ‘magit-insert-submodules’ to the hook +‘magit-status-sections-hook’ as described in *note Status Module +Sections::. + + -- Command: magit-list-submodules + + This command displays a list of the current repository’s submodules + in a separate buffer. + + It can be invoked by pressing ‘RET’ on the section titled + "Modules". + + -- User Option: magit-submodule-list-columns + + This option controls what columns are displayed by the command + ‘magit-list-submodules’ and how they are displayed. + + Each element has the form ‘(HEADER WIDTH FORMAT PROPS)’. + + HEADER is the string displayed in the header. WIDTH is the width + of the column. FORMAT is a function that is called with one + argument, the repository identification (usually its basename), and + with ‘default-directory’ bound to the toplevel of its working tree. + It has to return a string to be inserted or nil. PROPS is an alist + that supports the keys ‘:right-align’ and ‘:pad-right’. + + -- Function: magit-insert-submodules + + Insert sections for all submodules. For each section insert the + path, the branch, and the output of ‘git describe --tags’, or, + failing that, the abbreviated HEAD commit hash. + + Press ‘RET’ on such a submodule section to show its own status + buffer. Press ‘RET’ on the "Modules" section to display a list of + submodules in a separate buffer. This shows additional information + not displayed in the super-repository’s status buffer. + + +File: magit.info, Node: Submodule Transient, Prev: Listing Submodules, Up: Submodules + +8.3.2 Submodule Transient +------------------------- + +‘o’ (‘magit-submodule’) + + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. + + Some of the below commands default to act on the modules that are +selected using the region. For brevity their description talk about +"the selected modules", but if no modules are selected, then they act on +the current module instead, or if point isn’t on a module, then the read +a single module to act on. With a prefix argument these commands ignore +the selection and the current module and instead act on all suitable +modules. + +‘o a’ (‘magit-submodule-add’) + + This commands adds the repository at URL as a module. Optional + PATH is the path to the module relative to the root of the + super-project. If it is nil then the path is determined based on + URL. + +‘o r’ (‘magit-submodule-register’) + + This command registers the selected modules by copying their urls + from ".gitmodules" to "$GIT_DIR/config". These values can then be + edited before running ‘magit-submodule-populate’. If you don’t + need to edit any urls, then use the latter directly. + +‘o p’ (‘magit-submodule-populate’) + + This command creates the working directory or directories of the + selected modules, checking out the recorded commits. + +‘o u’ (‘magit-submodule-update’) + + This command updates the selected modules checking out the recorded + commits. + +‘o s’ (‘magit-submodule-synchronize’) + + This command synchronizes the urls of the selected modules, copying + the values from ".gitmodules" to the ".git/config" of the + super-project as well those of the modules. + +‘o d’ (‘magit-submodule-unpopulate’) + + This command removes the working directory of the selected modules. + +‘o l’ (‘magit-list-submodules’) + + This command displays a list of the current repository’s modules. + +‘o f’ (‘magit-fetch-modules’) + + This command fetches all modules. + + Option ‘magit-fetch-modules-jobs’ controls how many submodules are + being fetched in parallel. Also fetch the super-repository, + because ‘git fetch’ does not support not doing that. With a prefix + argument fetch all remotes. + + +File: magit.info, Node: Subtree, Next: Worktree, Prev: Submodules, Up: Miscellaneous + +8.4 Subtree +=========== + +Also see *note (gitman)git-subtree::. + +‘O’ (‘magit-subtree’) + + This transient prefix command binds the two sub-transients; one for + importing a subtree and one for exporting a subtree. + +‘O i’ (‘magit-subtree-import’) + + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. + + The suffixes of this command import subtrees. + + If the ‘--prefix’ argument is set, then the suffix commands use + that prefix without prompting the user. If it is unset, then they + read the prefix in the minibuffer. + +‘O i a’ (‘magit-subtree-add’) + + This command adds COMMIT from REPOSITORY as a new subtree at + PREFIX. + +‘O i c’ (‘magit-subtree-add-commit’) + + This command add COMMIT as a new subtree at PREFIX. + +‘O i m’ (‘magit-subtree-merge’) + + This command merges COMMIT into the PREFIX subtree. + +‘O i f’ (‘magit-subtree-pull’) + + This command pulls COMMIT from REPOSITORY into the PREFIX subtree. + +‘O e’ (‘magit-subtree-export’) + + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. + + The suffixes of this command export subtrees. + + If the ‘--prefix’ argument is set, then the suffix commands use + that prefix without prompting the user. If it is unset, then they + read the prefix in the minibuffer. + +‘O e p’ (‘magit-subtree-push’) + + This command extract the history of the subtree PREFIX and pushes + it to REF on REPOSITORY. + +‘O e s’ (‘magit-subtree-split’) + + This command extracts the history of the subtree PREFIX. + + +File: magit.info, Node: Worktree, Next: Common Commands, Prev: Subtree, Up: Miscellaneous + +8.5 Worktree +============ + +Also see *note (gitman)git-worktree::. + +‘%’ (‘magit-worktree’) + + This transient prefix command binds the following suffix commands + and displays them in a temporary buffer until a suffix is invoked. + +‘% b’ (‘magit-worktree-checkout’) + + Checkout BRANCH in a new worktree at PATH. + +‘% c’ (‘magit-worktree-branch’) + + Create a new BRANCH and check it out in a new worktree at PATH. + +‘% m’ (‘magit-worktree-move’) + + Move an existing worktree to a new PATH. + +‘% k’ (‘magit-worktree-delete’) + + Delete a worktree, defaulting to the worktree at point. The + primary worktree cannot be deleted. + +‘% g’ (‘magit-worktree-status’) + + Show the status for the worktree at point. + + If there is no worktree at point, then read one in the minibuffer. + If the worktree at point is the one whose status is already being + displayed in the current buffer, then show it in Dired instead. + + +File: magit.info, Node: Common Commands, Next: Wip Modes, Prev: Worktree, Up: Miscellaneous + +8.6 Common Commands +=================== + +These are some of the commands that can be used in all buffers whose +major-modes derive from ‘magit-mode’. There are other common commands +beside the ones below, but these didn’t fit well anywhere else. + +‘M-w’ (‘magit-copy-section-value’) + + This command saves the value of the current section to the + ‘kill-ring’, and, provided that the current section is a commit, + branch, or tag section, it also pushes the (referenced) revision to + the ‘magit-revision-stack’. + + When the current section is a branch or a tag, and a prefix + argument is used, then it saves the revision at its tip to the + ‘kill-ring’ instead of the reference name. + + When the region is active, this command saves that to the + ‘kill-ring’, like ‘kill-ring-save’ would, instead of behaving as + described above. If a prefix argument is used and the region is + within a hunk, it strips the outer diff marker column before saving + the text. + +‘C-w’ (‘magit-copy-buffer-revision’) + + This command saves the revision being displayed in the current + buffer to the ‘kill-ring’ and also pushes it to the + ‘magit-revision-stack’. It is mainly intended for use in + ‘magit-revision-mode’ buffers, the only buffers where it is always + unambiguous exactly which revision should be saved. + + Most other Magit buffers usually show more than one revision, in + some way or another, so this command has to select one of them, and + that choice might not always be the one you think would have been + the best pick. + + Outside of Magit ‘M-w’ and ‘C-w’ are usually bound to +‘kill-ring-save’ and ‘kill-region’, and these commands would also be +useful in Magit buffers. Therefore when the region is active, then both +of these commands behave like ‘kill-ring-save’ instead of as described +above. + diff --git a/elpa/magit-20191122.2040/magit.info-2 b/elpa/magit-20191122.2040/magit.info-2 new file mode 100644 index 00000000..cbdd174a --- /dev/null +++ b/elpa/magit-20191122.2040/magit.info-2 @@ -0,0 +1,3497 @@ +This is magit.info, produced by makeinfo version 6.5 from magit.texi. + + Copyright (C) 2015-2019 Jonas Bernoulli + + You can redistribute this document and/or modify it under the terms + of the GNU General Public License as published by the Free Software + Foundation, either version 3 of the License, or (at your option) + any later version. + + This document is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + +INFO-DIR-SECTION Emacs +START-INFO-DIR-ENTRY +* Magit: (magit). Using Git from Emacs with Magit. +END-INFO-DIR-ENTRY + + +File: magit.info, Node: Wip Modes, Next: Minor Mode for Buffers Visiting Files, Prev: Common Commands, Up: Miscellaneous + +8.7 Wip Modes +============= + +Git keeps *committed* changes around long enough for users to recover +changes they have accidentally deleted. It does so by not garbage +collecting any committed but no longer referenced objects for a certain +period of time, by default 30 days. + + But Git does *not* keep track of *uncommitted* changes in the working +tree and not even the index (the staging area). Because Magit makes it +so convenient to modify uncommitted changes, it also makes it easy to +shoot yourself in the foot in the process. + + For that reason Magit provides a global mode that saves *tracked* +files to work-in-progress references after or before certain actions. +(At present untracked files are never saved and for technical reasons +nothing is saved before the first commit has been created). + + Two separate work-in-progress references are used to track the state +of the index and of the working tree: ‘refs/wip/index/’ and +‘refs/wip/wtree/’, where ‘’ is the full ref of the +current branch, e.g. ‘refs/heads/master’. When the ‘HEAD’ is detached +then ‘HEAD’ is used in place of ‘’. + + Checking out another branch (or detaching ‘HEAD’) causes the use of +different wip refs for subsequent changes. + + -- User Option: magit-wip-mode + + When this mode is enabled, then uncommitted changes are committed + to dedicated work-in-progress refs whenever appropriate (i.e. when + dataloss would be a possibility otherwise). + + Setting this variable directly does not take effect; either use the + Custom interface to do so or call the respective mode function. + + For historic reasons this mode is implemented on top of four other + ‘magit-wip-*’ modes, which can also be used individually, if you + want finer control over when the wip refs are updated; but that is + discouraged. See *note Legacy Wip Modes::. + + To view the log for a branch and its wip refs use the commands +‘magit-wip-log’ and ‘magit-wip-log-current’. You should use ‘--graph’ +when using these commands. + + -- Command: magit-wip-log + + This command shows the log for a branch and its wip refs. With a + negative prefix argument only the worktree wip ref is shown. + + The absolute numeric value of the prefix argument controls how many + "branches" of each wip ref are shown. This is only relevant if the + value of ‘magit-wip-merge-branch’ is ‘nil’. + + -- Command: magit-wip-log-current + + This command shows the log for the current branch and its wip refs. + With a negative prefix argument only the worktree wip ref is shown. + + The absolute numeric value of the prefix argument controls how many + "branches" of each wip ref are shown. This is only relevant if the + value of ‘magit-wip-merge-branch’ is ‘nil’. + +‘X w’ (‘magit-reset-worktree’) + + This command resets the working tree to some commit read from the + user and defaulting to the commit at point, while keeping the + ‘HEAD’ and index as-is. + + This can be used to restore files to the state committed to a wip + ref. Note that this will discard any unstaged changes that might + have existed before invoking this command (but of course only after + committing that to the working tree wip ref). + + Note that even if you enable ‘magit-wip-mode’ this won’t give you +perfect protection. The most likely scenario for losing changes despite +the use of ‘magit-wip-mode’ is making a change outside Emacs and then +destroying it also outside Emacs. In some such a scenario, Magit, being +an Emacs package, didn’t get the opportunity to keep you from shooting +yourself in the foot. + + When you are unsure whether Magit did commit a change to the wip +refs, then you can explicitly request that all changes to all tracked +files are being committed. + +‘M-x magit-wip-commit’ (‘magit-wip-commit’) + + This command commits all changes to all tracked files to the index + and working tree work-in-progress refs. Like the modes described + above, it does not commit untracked files, but it does check all + tracked files for changes. Use this command when you suspect that + the modes might have overlooked a change made outside Emacs/Magit. + + -- User Option: magit-wip-namespace + + The namespace used for work-in-progress refs. It has to end with a + slash. The wip refs are named ‘index/’ and + ‘wtree/’. When snapshots are created while + the ‘HEAD’ is detached then ‘HEAD’ is used in place of + ‘’. + + -- User Option: magit-wip-mode-lighter + + Mode-line lighter for ‘magit-wip--mode’. + +* Menu: + +* Wip Graph:: +* Legacy Wip Modes:: + + +File: magit.info, Node: Wip Graph, Next: Legacy Wip Modes, Up: Wip Modes + +8.7.1 Wip Graph +--------------- + + -- User Option: magit-wip-merge-branch + + This option controls whether the current branch is merged into the + wip refs after a new commit was created on the branch. + + If non-nil and the current branch has new commits, then it is + merged into the wip ref before creating a new wip commit. This + makes it easier to inspect wip history and the wip commits are + never garbage collected. + + If nil and the current branch has new commits, then the wip ref is + reset to the tip of the branch before creating a new wip commit. + With this setting wip commits are eventually garbage collected. + + When ‘magit-wip-merge-branch’ is ‘t’, then the history looks like +this: + + *--*--*--*--*--* refs/wip/index/refs/heads/master + / / / + A-----B-----C refs/heads/master + + When ‘magit-wip-merge-branch’ is ‘nil’, then creating a commit on the +real branch and then making a change causes the wip refs to be recreated +to fork from the new commit. But the old commits on the wip refs are +not lost. They are still available from the reflog. To make it easier +to see when the fork point of a wip ref was changed, an additional +commit with the message "restart autosaving" is created on it (‘xxO’ +commits below are such boundary commits). + + Starting with + + BI0---BI1 refs/wip/index/refs/heads/master + / + A---B refs/heads/master + \ + BW0---BW1 refs/wip/wtree/refs/heads/master + + and committing the staged changes and editing and saving a file would +result in + + BI0---BI1 refs/wip/index/refs/heads/master + / + A---B---C refs/heads/master + \ \ + \ CW0---CW1 refs/wip/wtree/refs/heads/master + \ + BW0---BW1 refs/wip/wtree/refs/heads/master@{2} + + The fork-point of the index wip ref is not changed until some change +is being staged. Likewise just checking out a branch or creating a +commit does not change the fork-point of the working tree wip ref. The +fork-points are not adjusted until there actually is a change that +should be committed to the respective wip ref. + + +File: magit.info, Node: Legacy Wip Modes, Prev: Wip Graph, Up: Wip Modes + +8.7.2 Legacy Wip Modes +---------------------- + +It is recommended that you use the mode ‘magit-wip-mode’ (which see) and +ignore the existence of the following modes, which are preserved for +historic reasons. + + Setting the following variables directly does not take effect; either +use the Custom interface to do so or call the respective mode functions. + + -- User Option: magit-wip-after-save-mode + + When this mode is enabled, then saving a buffer that visits a file + tracked in a Git repository causes its current state to be + committed to the working tree wip ref for the current branch. + + -- User Option: magit-wip-after-apply-mode + + When this mode is enabled, then applying (i.e. staging, unstaging, + discarding, reversing, and regularly applying) a change to a file + tracked in a Git repository causes its current state to be + committed to the index and/or working tree wip refs for the current + branch. + + If you only ever edit files using Emacs and only ever interact with +Git using Magit, then the above two modes should be enough to protect +each and every change from accidental loss. In practice nobody does +that. Two additional modes exists that do commit to the wip refs before +making changes that could cause the loss of earlier changes. + + -- User Option: magit-wip-before-change-mode + + When this mode is enabled, then certain commands commit the + existing changes to the files they are about to make changes to. + + -- User Option: magit-wip-initial-backup-mode + + When this mode is enabled, then the current version of a file is + committed to the worktree wip ref before the buffer visiting that + file is saved for the first time since the buffer was created. + + This backs up the same version of the file that ‘backup-buffer’ + would save. While ‘backup-buffer’ uses a backup file, this mode + uses the same worktree wip ref as used by the other Magit Wip + modes. Like ‘backup-buffer’, it only does this once; unless you + kill the buffer and visit the file again only one backup will be + created per Emacs session. + + This mode ignores the variables that affect ‘backup-buffer’ and can + be used along-side that function, which is recommended because it + only backs up files that are tracked in a Git repository. + + -- User Option: magit-wip-after-save-local-mode-lighter + + Mode-line lighter for ‘magit-wip-after-save-local-mode’. + + -- User Option: magit-wip-after-apply-mode-lighter + + Mode-line lighter for ‘magit-wip-after-apply-mode’. + + -- User Option: magit-wip-before-change-mode-lighter + + Mode-line lighter for ‘magit-wip-before-change-mode’. + + -- User Option: magit-wip-initial-backup-mode-lighter + + Mode-line lighter for ‘magit-wip-initial-backup-mode’. + + +File: magit.info, Node: Minor Mode for Buffers Visiting Files, Next: Minor Mode for Buffers Visiting Blobs, Prev: Wip Modes, Up: Miscellaneous + +8.8 Minor Mode for Buffers Visiting Files +========================================= + +The minor-mode ‘magit-file-mode’ enables certain Magit features in +file-visiting buffers belonging to a Git repository. The globalized +variant ‘global-magit-file-mode’ enables the local mode in all such +buffers. It is enabled by default. Currently the local mode only +establishes a few key bindings, but this might be extended in the +future. + + -- User Option: global-magit-file-mode + + Whether to establish certain Magit key bindings in all + file-visiting buffers belonging to any Git repository. This is + enabled by default. This globalized mode turns on the local + minor-mode ‘magit-file-mode’ in all suitable buffers. + + -- Variable: magit-file-mode-map + + This keymap is used by the local minor-mode ‘magit-file-mode’ and + establishes the key bindings described below. + + Note that the default binding for ‘magit-file-dispatch’ is very + cumbersome to use and that we recommend that you add a better + binding. + + Instead of ‘C-c M-g’ I would have preferred to use ‘C-c g’ because + (1) it is similar to ‘C-x g’ (the recommended global binding for + ‘~magit-status’), (2) we cannot use ‘C-c C-g’ because we have been + recommending that that be bound to ‘magit-dispatch’ for a long + time, (3) we cannot use ‘C-x C-g’ because that is a convenient way + of aborting the incomplete key sequence ‘C-x’, and most importantly + (4) it would make it much easier to type the next key (a suffix + binding) because most of those are letters. + + For example ‘C-c g b’ is much easier to type than ‘C-c M-g b’. For + suffix bindings that use uppercase letters, the default is just + horrible—having to use e.g. ‘C-c M-g B’ (‘Control+c Meta+g + Shift+b’) would drive anyone up the walls (or to Vim). + + However ‘C-c LETTER’ bindings are reserved for users (see *note + (elisp)Key Binding Conventions::). Packages are forbidden from + using those. Doing so anyway is considered heresy. Therefore if + you want a better binding, you have to add it yourself: + + (define-key magit-file-mode-map + (kbd "C-c g") 'magit-file-dispatch) + + The key bindings shown below assume that you have not improved the +binding for ‘magit-file-dispatch’. + +‘C-c M-g’ (‘magit-file-dispatch’) + + This transient prefix command binds the following suffix commands + and displays them in a temporary buffer until a suffix is invoked. + +‘C-c M-g s’ (‘magit-stage-file’) + + Stage all changes to the file being visited in the current buffer. + +‘C-c M-g u’ (‘magit-unstage-file’) + + Unstage all changes to the file being visited in the current + buffer. + +‘C-c M-g c’ (‘magit-commit’) + + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. See *note Initiating a + Commit::. + +‘C-c M-g D’ (‘magit-diff’) + + This transient prefix command binds several diff suffix commands + and infix arguments and displays them in a temporary buffer until a + suffix is invoked. See *note Diffing::. + + This is the same command that ‘d’ is bound to in Magit buffers. If + this command is invoked from a file-visiting buffer, then the + initial value of the option (‘--’) that limits the diff to certain + file(s) is set to the visited file. + +‘C-c M-g d’ (‘magit-diff-buffer-file’) + + This command shows the diff for the file of blob that the current + buffer visits. + + -- User Option: magit-diff-buffer-file-locked + + This option controls whether ‘magit-diff-buffer-file’ uses a + dedicated buffer. See *note Modes and Buffers::. + +‘C-c M-g L’ (‘magit-log’) + + This transient prefix command binds several log suffix commands and + infix arguments and displays them in a temporary buffer until a + suffix is invoked. See *note Logging::. + + This is the same command that ‘l’ is bound to in Magit buffers. If + this command is invoked from a file-visiting buffer, then the + initial value of the option (‘--’) that limits the log to certain + file(s) is set to the visited file. + +‘C-c M-g l’ (‘magit-log-buffer-file’) + + This command shows the log for the file of blob that the current + buffer visits. Renames are followed when a prefix argument is used + or when ‘--follow’ is an active log argument. When the region is + active, the log is restricted to the selected line range. + +‘C-c M-g t’ (‘magit-log-trace-definition’) + + This command shows the log for the definition at point. + + -- User Option: magit-log-buffer-file-locked + + This option controls whether ‘magit-log-buffer-file’ uses a + dedicated buffer. See *note Modes and Buffers::. + +‘C-c M-g B’ (‘magit-blame’) + + This transient prefix command binds all blaming suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. + + For more information about this and the following commands also see + *note Blaming::. + + In addition to the ‘magit-blame’ sub-transient, the dispatch +transient also binds several blaming suffix commands directly. See +*note Blaming:: for information about those commands and bindings. + +‘C-c M-g e’ (‘magit-edit-line-commit’) + + This command makes the commit editable that added the current line. + + With a prefix argument it makes the commit editable that removes + the line, if any. The commit is determined using ‘git blame’ and + made editable using ‘git rebase --interactive’ if it is reachable + from ‘HEAD’, or by checking out the commit (or a branch that points + at it) otherwise. + +‘C-c M-g p’ (‘magit-blob-previous’) + + Visit the previous blob which modified the current file. + + There are a few additional commands that operate on a single file but +are not enabled in the file transient command by default: + + -- Command: magit-file-rename + + This command renames a file read from the user. + + -- Command: magit-file-delete + + This command deletes a file read from the user. + + -- Command: magit-file-untrack + + This command untracks a file read from the user. + + -- Command: magit-file-checkout + + This command updates a file in the working tree and index to the + contents from a revision. Both the revision and file are read from + the user. + + To enable them invoke the transient (‘C-c M-g’), enter "edit mode" +(‘C-x l’), set the "transient level" (‘C-x l’ again), enter ‘5’, and +leave edit mode (‘C-g’). Also see *note (transient)Enabling and +Disabling Suffixes::. + + +File: magit.info, Node: Minor Mode for Buffers Visiting Blobs, Prev: Minor Mode for Buffers Visiting Files, Up: Miscellaneous + +8.9 Minor Mode for Buffers Visiting Blobs +========================================= + +The ‘magit-blob-mode’ enables certain Magit features in blob-visiting +buffers. Such buffers can be created using ‘magit-find-file’ and some +of the commands mentioned below, which also take care of turning on this +minor mode. Currently this mode only establishes a few key bindings, +but this might be extended. + +‘p’ (‘magit-blob-previous’) + + Visit the previous blob which modified the current file. + +‘n’ (‘magit-blob-next’) + + Visit the next blob which modified the current file. + +‘q’ (‘magit-kill-this-buffer’) + + Kill the current buffer. + + +File: magit.info, Node: Customizing, Next: Plumbing, Prev: Miscellaneous, Up: Top + +9 Customizing +************* + +Both Git and Emacs are highly customizable. Magit is both a Git +porcelain as well as an Emacs package, so it makes sense to customize it +using both Git variables as well as Emacs options. However this +flexibility doesn’t come without problems, including but not limited to +the following. + + • Some Git variables automatically have an effect in Magit without + requiring any explicit support. Sometimes that is desirable - in + other cases, it breaks Magit. + + When a certain Git setting breaks Magit but you want to keep using + that setting on the command line, then that can be accomplished by + overriding the value for Magit only by appending something like + ‘("-c" "some.variable=compatible-value")’ to + ‘magit-git-global-arguments’. + + • Certain settings like ‘fetch.prune=true’ are respected by Magit + commands (because they simply call the respective Git command) but + their value is not reflected in the respective transient buffers. + In this case the ‘--prune’ argument in ‘magit-fetch’ might be + active or inactive, but that doesn’t keep the Git variable from + being honored by the suffix commands anyway. So pruning might + happen despite the ‘--prune’ arguments being displayed in a way + that seems to indicate that no pruning will happen. + + I intend to address these and similar issues in a future release. + +* Menu: + +* Per-Repository Configuration:: +* Essential Settings:: + + +File: magit.info, Node: Per-Repository Configuration, Next: Essential Settings, Up: Customizing + +9.1 Per-Repository Configuration +================================ + +Magit can be configured on a per-repository level using both Git +variables as well as Emacs options. + + To set a Git variable for one repository only, simply set it in +‘/path/to/repo/.git/config’ instead of ‘$HOME/.gitconfig’ or +‘/etc/gitconfig’. See *note (gitman)git-config::. + + Similarly, Emacs options can be set for one repository only by +editing ‘/path/to/repo/.dir-locals.el’. See *note (emacs)Directory +Variables::. For example to disable automatic refreshes of +file-visiting buffers in just one huge repository use this: + + • ‘/path/to/huge/repo/.dir-locals.el’ + + ((nil . ((magit-refresh-buffers . nil)))) + + If you want to apply the same settings to several, but not all, +repositories then keeping the repository-local config files in sync +would quickly become annoying. To avoid that you can create config +files for certain classes of repositories (e.g. "huge repositories") +and then include those files in the per-repository config files. For +example: + + • ‘/path/to/huge/repo/.git/config’ + + [include] + path = /path/to/huge-gitconfig + + • ‘/path/to/huge-gitconfig’ + + [status] + showUntrackedFiles = no + + • ‘$HOME/.emacs.d/init.el’ + + (dir-locals-set-class-variables 'huge-git-repository + '((nil . ((magit-refresh-buffers . nil))))) + + (dir-locals-set-directory-class + "/path/to/huge/repo/" 'huge-git-repository) + + +File: magit.info, Node: Essential Settings, Prev: Per-Repository Configuration, Up: Customizing + +9.2 Essential Settings +====================== + +The next two sections list and discuss several variables that many users +might want to customize, for safety and/or performance reasons. + +* Menu: + +* Safety:: +* Performance:: + + +File: magit.info, Node: Safety, Next: Performance, Up: Essential Settings + +9.2.1 Safety +------------ + +This section discusses various variables that you might want to change +(or *not* change) for safety reasons. + + Git keeps *committed* changes around long enough for users to recover +changes they have accidentally been deleted. It does not do the same +for *uncommitted* changes in the working tree and not even the index +(the staging area). Because Magit makes it so easy to modify +uncommitted changes, it also makes it easy to shoot yourself in the foot +in the process. For that reason Magit provides three global modes that +save *tracked* files to work-in-progress references after or before +certain actions. See *note Wip Modes::. + + These modes are not enabled by default because of performance +concerns. Instead a lot of potentially destructive commands require +confirmation every time they are used. In many cases this can be +disabled by adding a symbol to ‘magit-no-confirm’ (see *note Completion +and Confirmation::). If you enable the various wip modes then you +should add ‘safe-with-wip’ to this list. + + Similarly it isn’t necessary to require confirmation before moving a +file to the system trash - if you trashed a file by mistake then you can +recover it from the there. Option ‘magit-delete-by-moving-to-trash’ +controls whether the system trash is used, which is the case by default. +Nevertheless, ‘trash’ isn’t a member of ‘magit-no-confirm’ - you might +want to change that. + + By default buffers visiting files are automatically reverted when the +visited file changes on disk. This isn’t as risky as it might seem, but +to make an informed decision you should see *note Risk of Reverting +Automatically::. + + +File: magit.info, Node: Performance, Prev: Safety, Up: Essential Settings + +9.2.2 Performance +----------------- + +After Magit has run ‘git’ for side-effects, it also refreshes the +current Magit buffer and the respective status buffer. This is +necessary because otherwise outdated information might be displayed +without the user noticing. Magit buffers are updated by recreating +their content from scratch, which makes updating simpler and less +error-prone, but also more costly. Keeping it simple and just +re-creating everything from scratch is an old design decision and +departing from that will require major refactoring. + + I plan to do that in time for the next major release. I also intend +to create logs and diffs asynchronously, which should also help a lot +but also requires major refactoring. + + Meanwhile you can tell Magit to only automatically refresh the +current Magit buffer, but not the status buffer. If you do that, then +the status buffer is only refreshed automatically if it is the current +buffer. + + (setq magit-refresh-status-buffer nil) + + You should also check whether any third-party packages have added +anything to ‘magit-refresh-buffer-hook’, ‘magit-status-refresh-hook’, +‘magit-pre-refresh-hook’, and ‘magit-post-refresh-hook’. If so, then +check whether those additions impact performance significantly. Setting +‘magit-refresh-verbose’ and then inspecting the output in the +‘*Messages*’ buffer, should help doing so. + + Magit also reverts buffers for visited files located inside the +current repository when the visited file changes on disk. That is +implemented on top of ‘auto-revert-mode’ from the built-in library +‘autorevert’. To figure out whether that impacts performance, check +whether performance is significantly worse, when many buffers exist +and/or when some buffers visit files using TRAMP. If so, then this +should help. + + (setq auto-revert-buffer-list-filter + 'magit-auto-revert-repository-buffer-p) + + For alternative approaches see *note Automatic Reverting of +File-Visiting Buffers::. + + If you have enabled any features that are disabled by default, then +you should check whether they impact performance significantly. It’s +likely that they were not enabled by default because it is known that +they reduce performance at least in large repositories. + + If performance is only slow inside certain unusually large +repositories, then you might want to disable certain features on a +per-repository or per-repository-class basis only. See *note +Per-Repository Configuration::. + +* Menu: + +* Microsoft Windows Performance:: +* MacOS Performance:: + +Log Performance +............... + +When showing logs, Magit limits the number of commits initially shown in +the hope that this avoids unnecessary work. When using ‘--graph’ is +used, then this unfortunately does not have the desired effect for large +histories. Junio, Git’s maintainer, said on the git mailing list +(): "‘--graph’ wants to +compute the whole history and the max-count only affects the output +phase after ‘--graph’ does its computation". + + In other words, it’s not that Git is slow at outputting the +differences, or that Magit is slow at parsing the output - the problem +is that Git first goes outside and has a smoke. + + We actually work around this issue by limiting the number of commits +not only by using ‘-’ but by also using a range. But unfortunately +that’s not always possible. + + When more than a few thousand commits are shown, then the use of +‘--graph’ can slow things down. + + Using ‘--color --graph’ is even slower. Magit uses code that is part +of Emacs to turn control characters into faces. That code is pretty +slow and this is quite noticeable when showing a log with many branches +and merges. For that reason ‘--color’ is not enabled by default +anymore. Consider leaving it at that. + +Diff Performance +................ + +If diffs are slow, then consider turning off some optional diff features +by setting all or some of the following variables to ‘nil’: +‘magit-diff-highlight-indentation’, ‘magit-diff-highlight-trailing’, +‘magit-diff-paint-whitespace’, ‘magit-diff-highlight-hunk-body’, and +‘magit-diff-refine-hunk’. + + When showing a commit instead of some arbitrary diff, then some +additional information is displayed. Calculating this information can +be quite expensive given certain circumstances. If looking at a commit +using ‘magit-revision-mode’ takes considerably more time than looking at +the same commit in ‘magit-diff-mode’, then consider setting +‘magit-revision-insert-related-refs’ to ‘nil’. + +Refs Buffer Performance +....................... + +When refreshing the "references buffer" is slow, then that’s usually +because several hundred refs are being displayed. The best way to +address that is to display fewer refs, obviously. + + If you are not, or only mildly, interested in seeing the list of +tags, then start by not displaying them: + + (remove-hook 'magit-refs-sections-hook 'magit-insert-tags) + + Then you should also make sure that the listed remote branches +actually all exist. You can do so by pruning branches which no longer +exist using ‘f-pa’. + +Committing Performance +...................... + +When you initiate a commit, then Magit by default automatically shows a +diff of the changes you are about to commit. For large commits this can +take a long time, which is especially distracting when you are +committing large amounts of generated data which you don’t actually +intend to inspect before committing. This behavior can be turned off +using: + + (remove-hook 'server-switch-hook 'magit-commit-diff) + + Then you can type ‘C-c C-d’ to show the diff when you actually want +to see it, but only then. Alternatively you can leave the hook alone +and just type ‘C-g’ in those cases when it takes too long to generate +the diff. If you do that, then you will end up with a broken diff +buffer, but doing it this way has the advantage that you usually get to +see the diff, which is useful because it increases the odds that you +spot potential issues. + +The Built-In VC Package +....................... + +Emacs comes with a version control interface called "VC", see *note +(emacs)Version Control::. It is enabled be default, and if you don’t +use it in addition to Magit, then you should disable it to keep it from +performing unnecessary work: + + (setq vc-handled-backends nil) + + You can also disable its use for Git but keep using it when using +another version control system: + + (setq vc-handled-backends (delq 'Git vc-handled-backends)) + + +File: magit.info, Node: Microsoft Windows Performance, Next: MacOS Performance, Up: Performance + +Microsoft Windows Performance +............................. + +In order to update the status buffer, ‘git’ has to be run a few dozen +times. That is problematic on Microsoft Windows, because that operating +system is exceptionally slow at starting processes. Sadly this is an +issue that can only be fixed by Microsoft itself, and they don’t appear +to be particularly interested in doing so. + + Beside the subprocess issue, there are also other Windows-specific +performance issues. Some of these have workarounds. The maintainers of +"Git for Windows" try to improve performance on Windows. Always use the +latest release in order to benefit from the latest performance tweaks. +Magit too tries to work around some Windows-specific issues. + + According to some sources, setting the following Git variables can +also help. + + git config --global core.preloadindex true # default since v2.1 + git config --global core.fscache true # default since v2.8 + git config --global gc.auto 256 + + You should also check whether an anti-virus program is affecting +performance. + + +File: magit.info, Node: MacOS Performance, Prev: Microsoft Windows Performance, Up: Performance + +MacOS Performance +................. + +Before Emacs 26.1 child processes were created using ‘fork’ on macOS. +That needlessly copied GUI resources, which is expensive. The result +was that forking took about 30 times as long on Darwin than on Linux, +and because Magit starts many ‘git’ processes that made quite a +difference. + + So make sure that you are using at least Emacs 26.1, in which case +the faster ‘vfork’ will be used. (The creation of child processes still +takes about twice as long on Darwin compared to Linux.) See (1) for +more information. + + ---------- Footnotes ---------- + + (1) + + + +File: magit.info, Node: Plumbing, Next: FAQ, Prev: Customizing, Up: Top + +10 Plumbing +*********** + +The following sections describe how to use several of Magit’s core +abstractions to extend Magit itself or implement a separate extension. + + A few of the low-level features used by Magit have been factored out +into separate libraries/packages, so that they can be used by other +packages, without having to depend on Magit. See *note +(with-editor)Top:: for information about ‘with-editor’. ‘transient’ +doesn’t have a manual yet. + + If you are trying to find an unused key that you can bind to a +command provided by your own Magit extension, then checkout +. + +* Menu: + +* Calling Git:: +* Section Plumbing:: +* Refreshing Buffers:: +* Conventions:: + + +File: magit.info, Node: Calling Git, Next: Section Plumbing, Up: Plumbing + +10.1 Calling Git +================ + +Magit provides many specialized functions for calling Git. All of these +functions are defined in either ‘magit-git.el’ or ‘magit-process.el’ and +have one of the prefixes ‘magit-run-’, ‘magit-call-’, ‘magit-start-’, or +‘magit-git-’ (which is also used for other things). + + All of these functions accept an indefinite number of arguments, +which are strings that specify command line arguments for Git (or in +some cases an arbitrary executable). These arguments are flattened +before being passed on to the executable; so instead of strings they can +also be lists of strings and arguments that are ‘nil’ are silently +dropped. Some of these functions also require a single mandatory +argument before these command line arguments. + + Roughly speaking, these functions run Git either to get some value or +for side-effects. The functions that return a value are useful to +collect the information necessary to populate a Magit buffer, while the +others are used to implement Magit commands. + + The functions in the value-only group always run synchronously, and +they never trigger a refresh. The function in the side-effect group can +be further divided into subgroups depending on whether they run Git +synchronously or asynchronously, and depending on whether they trigger a +refresh when the executable has finished. + +* Menu: + +* Getting a Value from Git:: +* Calling Git for Effect:: + + +File: magit.info, Node: Getting a Value from Git, Next: Calling Git for Effect, Up: Calling Git + +10.1.1 Getting a Value from Git +------------------------------- + +These functions run Git in order to get a value, an exit status, or +output. Of course you could also use them to run Git commands that have +side-effects, but that should be avoided. + + -- Function: magit-git-exit-code &rest args + + Executes git with ARGS and returns its exit code. + + -- Function: magit-git-success &rest args + + Executes git with ARGS and returns ‘t’ if the exit code is ‘0’, + ‘nil’ otherwise. + + -- Function: magit-git-failure &rest args + + Executes git with ARGS and returns ‘t’ if the exit code is ‘1’, + ‘nil’ otherwise. + + -- Function: magit-git-true &rest args + + Executes git with ARGS and returns ‘t’ if the first line printed by + git is the string "true", ‘nil’ otherwise. + + -- Function: magit-git-false &rest args + + Executes git with ARGS and returns ‘t’ if the first line printed by + git is the string "false", ‘nil’ otherwise. + + -- Function: magit-git-insert &rest args + + Executes git with ARGS and inserts its output at point. + + -- Function: magit-git-string &rest args + + Executes git with ARGS and returns the first line of its output. + If there is no output or if it begins with a newline character, + then this returns ‘nil’. + + -- Function: magit-git-lines &rest args + + Executes git with ARGS and returns its output as a list of lines. + Empty lines anywhere in the output are omitted. + + -- Function: magit-git-items &rest args + + Executes git with ARGS and returns its null-separated output as a + list. Empty items anywhere in the output are omitted. + + If the value of option ‘magit-git-debug’ is non-nil and git exits + with a non-zero exit status, then warn about that in the echo area + and add a section containing git’s standard error in the current + repository’s process buffer. + + If an error occurs when using one of the above functions, then that +is usually due to a bug, i.e. using an argument which is not actually +supported. Such errors are usually not reported, but when they occur we +need to be able to debug them. + + -- User Option: magit-git-debug + + Whether to report errors that occur when using ‘magit-git-insert’, + ‘magit-git-string’, ‘magit-git-lines’, or ‘magit-git-items’. This + does not actually raise an error. Instead a message is shown in + the echo area, and git’s standard error is insert into a new + section in the current repository’s process buffer. + + -- Function: magit-git-str &rest args + + This is a variant of ‘magit-git-string’ that ignores the option + ‘magit-git-debug’. It is mainly intended to be used while handling + errors in functions that do respect that option. Using such a + function while handing an error could cause yet another error and + therefore lead to an infinite recursion. You probably won’t ever + need to use this function. + + +File: magit.info, Node: Calling Git for Effect, Prev: Getting a Value from Git, Up: Calling Git + +10.1.2 Calling Git for Effect +----------------------------- + +These functions are used to run git to produce some effect. Most Magit +commands that actually run git do so by using such a function. + + Because we do not need to consume git’s output when using these +functions, their output is instead logged into a per-repository buffer, +which can be shown using ‘$’ from a Magit buffer or ‘M-x magit-process’ +elsewhere. + + These functions can have an effect in two distinct ways. Firstly, +running git may change something, i.e. create or push a new commit. +Secondly, that change may require that Magit buffers are refreshed to +reflect the changed state of the repository. But refreshing isn’t +always desirable, so only some of these functions do perform such a +refresh after git has returned. + + Sometimes it is useful to run git asynchronously. For example, when +the user has just initiated a push, then there is no reason to make her +wait until that has completed. In other cases it makes sense to wait +for git to complete before letting the user do something else. For +example after staging a change it is useful to wait until after the +refresh because that also automatically moves to the next change. + + -- Function: magit-call-git &rest args + + Calls git synchronously with ARGS. + + -- Function: magit-call-process program &rest args + + Calls PROGRAM synchronously with ARGS. + + -- Function: magit-run-git &rest args + + Calls git synchronously with ARGS and then refreshes. + + -- Function: magit-run-git-with-input input &rest args + + Calls git synchronously with ARGS and sends it INPUT on standard + input. + + INPUT should be a buffer or the name of an existing buffer. The + content of that buffer is used as the process’ standard input. + After the process returns a refresh is performed. + + As a special case, INPUT may also be nil. In that case the content + of the current buffer is used as standard input and *no* refresh is + performed. + + This function actually runs git asynchronously. But then it waits + for the process to return, so the function itself is synchronous. + + -- Function: magit-run-git-with-logfile file &rest args + + Calls git synchronously with ARGS. The process’ output is saved in + FILE. This is rarely useful and so this function might be removed + in the future. + + This function actually runs git asynchronously. But then it waits + for the process to return, so the function itself is synchronous. + + -- Function: magit-git &rest args + + Calls git synchronously with ARGS for side-effects only. This + function does not refresh the buffer. + + -- Function: magit-git-wash washer &rest args + + Execute Git with ARGS, inserting washed output at point. Actually + first insert the raw output at point. If there is no output call + ‘magit-cancel-section’. Otherwise temporarily narrow the buffer to + the inserted text, move to its beginning, and then call function + WASHER with ARGS as its sole argument. + + And now for the asynchronous variants. + + -- Function: magit-run-git-async &rest args + + Start Git, prepare for refresh, and return the process object. + ARGS is flattened and then used as arguments to Git. + + Display the command line arguments in the echo area. + + After Git returns some buffers are refreshed: the buffer that was + current when this function was called (if it is a Magit buffer and + still alive), as well as the respective Magit status buffer. + Unmodified buffers visiting files that are tracked in the current + repository are reverted if ‘magit-revert-buffers’ is non-nil. + + -- Function: magit-run-git-with-editor &rest args + + Export GIT_EDITOR and start Git. Also prepare for refresh and + return the process object. ARGS is flattened and then used as + arguments to Git. + + Display the command line arguments in the echo area. + + After Git returns some buffers are refreshed: the buffer that was + current when this function was called (if it is a Magit buffer and + still alive), as well as the respective Magit status buffer. + + -- Function: magit-start-git &rest args + + Start Git, prepare for refresh, and return the process object. + + If INPUT is non-nil, it has to be a buffer or the name of an + existing buffer. The buffer content becomes the processes standard + input. + + Option ‘magit-git-executable’ specifies the Git executable and + option ‘magit-git-global-arguments’ specifies constant arguments. + The remaining arguments ARGS specify arguments to Git. They are + flattened before use. + + After Git returns, some buffers are refreshed: the buffer that was + current when this function was called (if it is a Magit buffer and + still alive), as well as the respective Magit status buffer. + Unmodified buffers visiting files that are tracked in the current + repository are reverted if ‘magit-revert-buffers’ is non-nil. + + -- Function: magit-start-process &rest args + + Start PROGRAM, prepare for refresh, and return the process object. + + If optional argument INPUT is non-nil, it has to be a buffer or the + name of an existing buffer. The buffer content becomes the + processes standard input. + + The process is started using ‘start-file-process’ and then setup to + use the sentinel ‘magit-process-sentinel’ and the filter + ‘magit-process-filter’. Information required by these functions is + stored in the process object. When this function returns the + process has not started to run yet so it is possible to override + the sentinel and filter. + + After the process returns, ‘magit-process-sentinel’ refreshes the + buffer that was current when ‘magit-start-process’ was called (if + it is a Magit buffer and still alive), as well as the respective + Magit status buffer. Unmodified buffers visiting files that are + tracked in the current repository are reverted if + ‘magit-revert-buffers’ is non-nil. + + -- Variable: magit-this-process + + The child process which is about to start. This can be used to + change the filter and sentinel. + + -- Variable: magit-process-raise-error + + When this is non-nil, then ‘magit-process-sentinel’ raises an error + if git exits with a non-zero exit status. For debugging purposes. + + +File: magit.info, Node: Section Plumbing, Next: Refreshing Buffers, Prev: Calling Git, Up: Plumbing + +10.2 Section Plumbing +===================== + +* Menu: + +* Creating Sections:: +* Section Selection:: +* Matching Sections:: + + +File: magit.info, Node: Creating Sections, Next: Section Selection, Up: Section Plumbing + +10.2.1 Creating Sections +------------------------ + + -- Macro: magit-insert-section &rest args + + Insert a section at point. + + TYPE is the section type, a symbol. Many commands that act on the + current section behave differently depending on that type. Also if + a variable ‘magit-TYPE-section-map’ exists, then use that as the + text-property ‘keymap’ of all text belonging to the section (but + this may be overwritten in subsections). TYPE can also have the + form ‘(eval FORM)’ in which case FORM is evaluated at runtime. + + Optional VALUE is the value of the section, usually a string that + is required when acting on the section. + + When optional HIDE is non-nil collapse the section body by default, + i.e. when first creating the section, but not when refreshing the + buffer. Otherwise, expand it by default. This can be overwritten + using ‘magit-section-set-visibility-hook’. When a section is + recreated during a refresh, then the visibility of predecessor is + inherited and HIDE is ignored (but the hook is still honored). + + BODY is any number of forms that actually insert the section’s + heading and body. Optional NAME, if specified, has to be a symbol, + which is then bound to the struct of the section being inserted. + + Before BODY is evaluated the ‘start’ of the section object is set + to the value of ‘point’ and after BODY was evaluated its ‘end’ is + set to the new value of ‘point’; BODY is responsible for moving + ‘point’ forward. + + If it turns out inside BODY that the section is empty, then + ‘magit-cancel-section’ can be used to abort and remove all traces + of the partially inserted section. This can happen when creating a + section by washing Git’s output and Git didn’t actually output + anything this time around. + + -- Function: magit-insert-heading &rest args + + Insert the heading for the section currently being inserted. + + This function should only be used inside ‘magit-insert-section’. + + When called without any arguments, then just set the ‘content’ slot + of the object representing the section being inserted to a marker + at ‘point’. The section should only contain a single line when + this function is used like this. + + When called with arguments ARGS, which have to be strings, then + insert those strings at point. The section should not contain any + text before this happens and afterwards it should again only + contain a single line. If the ‘face’ property is set anywhere + inside any of these strings, then insert all of them unchanged. + Otherwise use the ‘magit-section-heading’ face for all inserted + text. + + The ‘content’ property of the section struct is the end of the + heading (which lasts from ‘start’ to ‘content’) and the beginning + of the body (which lasts from ‘content’ to ‘end’). If the value of + ‘content’ is nil, then the section has no heading and its body + cannot be collapsed. If a section does have a heading then its + height must be exactly one line, including a trailing newline + character. This isn’t enforced; you are responsible for getting it + right. The only exception is that this function does insert a + newline character if necessary. + + -- Function: magit-cancel-section + + Cancel the section currently being inserted. This exits the + innermost call to ‘magit-insert-section’ and removes all traces of + what has already happened inside that call. + + -- Function: magit-define-section-jumper sym title &optional value + + Define an interactive function to go to section SYM. TITLE is the + displayed title of the section. + + +File: magit.info, Node: Section Selection, Next: Matching Sections, Prev: Creating Sections, Up: Section Plumbing + +10.2.2 Section Selection +------------------------ + + -- Function: magit-current-section + + Return the section at point. + + -- Function: magit-region-sections &optional condition multiple + + Return a list of the selected sections. + + When the region is active and constitutes a valid section + selection, then return a list of all selected sections. This is + the case when the region begins in the heading of a section and + ends in the heading of the same section or in that of a sibling + section. If optional MULTIPLE is non-nil, then the region cannot + begin and end in the same section. + + When the selection is not valid, then return nil. In this case, + most commands that can act on the selected sections will instead + act on the section at point. + + When the region looks like it would in any other buffer then the + selection is invalid. When the selection is valid then the region + uses the ‘magit-section-highlight’ face. This does not apply to + diffs where things get a bit more complicated, but even here if the + region looks like it usually does, then that’s not a valid + selection as far as this function is concerned. + + If optional CONDITION is non-nil, then the selection not only has + to be valid; all selected sections additionally have to match + CONDITION, or nil is returned. See ‘magit-section-match’ for the + forms CONDITION can take. + + -- Function: magit-region-values &optional condition multiple + + Return a list of the values of the selected sections. + + Return the values that themselves would be returned by + ‘magit-region-sections’ (which see). + + +File: magit.info, Node: Matching Sections, Prev: Section Selection, Up: Section Plumbing + +10.2.3 Matching Sections +------------------------ + +‘M-x magit-describe-section-briefly’ (‘magit-describe-section-briefly’) + + Show information about the section at point. This command is + intended for debugging purposes. + + -- Function: magit-section-ident section + + Return an unique identifier for SECTION. The return value has the + form ‘((TYPE . VALUE)...)’. + + -- Function: magit-get-section ident &optional root + + Return the section identified by IDENT. IDENT has to be a list as + returned by ‘magit-section-ident’. + + -- Function: magit-section-match condition &optional section + + Return ‘t’ if SECTION matches CONDITION. SECTION defaults to the + section at point. If SECTION is not specified and there also is no + section at point, then return ‘nil’. + + CONDITION can take the following forms: + • ‘(CONDITION...)’ + + matches if any of the CONDITIONs matches. + + • ‘[CLASS...]’ + + matches if the section’s class is the same as the first CLASS + or a subclass of that; the section’s parent class matches the + second CLASS; and so on. + + • ‘[* CLASS...]’ + + matches sections that match ‘[CLASS...]’ and also recursively + all their child sections. + + • ‘CLASS’ + + matches if the section’s class is the same as CLASS or a + subclass of that; regardless of the classes of the parent + sections. + + Each CLASS should be a class symbol, identifying a class that + derives from ‘magit-section’. For backward compatibility CLASS can + also be a "type symbol". A section matches such a symbol if the + value of its ‘type’ slot is ‘eq’. If a type symbol has an entry in + ‘magit--section-type-alist’, then a section also matches that type + if its class is a subclass of the class that corresponds to the + type as per that alist. + + Note that it is not necessary to specify the complete section + lineage as printed by ‘magit-describe-section-briefly’, unless of + course you want to be that precise. + + -- Function: magit-section-value-if condition &optional section + + If the section at point matches CONDITION, then return its value. + + If optional SECTION is non-nil then test whether that matches + instead. If there is no section at point and SECTION is nil, then + return nil. If the section does not match, then return nil. + + See ‘magit-section-match’ for the forms CONDITION can take. + + -- Function: magit-section-case &rest clauses + + Choose among clauses on the type of the section at point. + + Each clause looks like (CONDITION BODY...). The type of the + section is compared against each CONDITION; the BODY forms of the + first match are evaluated sequentially and the value of the last + form is returned. Inside BODY the symbol ‘it’ is bound to the + section at point. If no clause succeeds or if there is no section + at point return nil. + + See ‘magit-section-match’ for the forms CONDITION can take. + Additionally a CONDITION of t is allowed in the final clause and + matches if no other CONDITION match, even if there is no section at + point. + + -- Variable: magit-root-section + + The root section in the current buffer. All other sections are + descendants of this section. The value of this variable is set by + ‘magit-insert-section’ and you should never modify it. + + For diff related sections a few additional tools exist. + + -- Function: magit-diff-type &optional section + + Return the diff type of SECTION. + + The returned type is one of the symbols ‘staged’, ‘unstaged’, + ‘committed’, or ‘undefined’. This type serves a similar purpose as + the general type common to all sections (which is stored in the + ‘type’ slot of the corresponding ‘magit-section’ struct) but takes + additional information into account. When the SECTION isn’t + related to diffs and the buffer containing it also isn’t a + diff-only buffer, then return nil. + + Currently the type can also be one of ‘tracked’ and ‘untracked’, + but these values are not handled explicitly in every place they + should be. A possible fix could be to just return nil here. + + The section has to be a ‘diff’ or ‘hunk’ section, or a section + whose children are of type ‘diff’. If optional SECTION is nil, + return the diff type for the current section. In buffers whose + major mode is ‘magit-diff-mode’ SECTION is ignored and the type is + determined using other means. In ‘magit-revision-mode’ buffers the + type is always ‘committed’. + + -- Function: magit-diff-scope &optional section strict + + Return the diff scope of SECTION or the selected section(s). + + A diff’s "scope" describes what part of a diff is selected, it is a + symbol, one of ‘region’, ‘hunk’, ‘hunks’, ‘file’, ‘files’, or + ‘list’. Do not confuse this with the diff "type", as returned by + ‘magit-diff-type’. + + If optional SECTION is non-nil, then return the scope of that, + ignoring the sections selected by the region. Otherwise return the + scope of the current section, or if the region is active and + selects a valid group of diff related sections, the type of these + sections, i.e. ‘hunks’ or ‘files’. If SECTION (or if the current + section that is nil) is a ‘hunk’ section and the region starts and + ends inside the body of a that section, then the type is ‘region’. + + If optional STRICT is non-nil then return nil if the diff type of + the section at point is ‘untracked’ or the section at point is not + actually a ‘diff’ but a ‘diffstat’ section. + + +File: magit.info, Node: Refreshing Buffers, Next: Conventions, Prev: Section Plumbing, Up: Plumbing + +10.3 Refreshing Buffers +======================= + +All commands that create a new Magit buffer or change what is being +displayed in an existing buffer do so by calling ‘magit-mode-setup’. +Among other things, that function sets the buffer local values of +‘default-directory’ (to the top-level of the repository), +‘magit-refresh-function’, and ‘magit-refresh-args’. + + Buffers are refreshed by calling the function that is the local value +of ‘magit-refresh-function’ (a function named ‘magit-*-refresh-buffer’, +where ‘*’ may be something like ‘diff’) with the value of +‘magit-refresh-args’ as arguments. + + -- Macro: magit-mode-setup buffer switch-func mode refresh-func + &optional refresh-args + + This function displays and selects BUFFER, turns on MODE, and + refreshes a first time. + + This function displays and optionally selects BUFFER by calling + ‘magit-mode-display-buffer’ with BUFFER, MODE and SWITCH-FUNC as + arguments. Then it sets the local value of + ‘magit-refresh-function’ to REFRESH-FUNC and that of + ‘magit-refresh-args’ to REFRESH-ARGS. Finally it creates the + buffer content by calling REFRESH-FUNC with REFRESH-ARGS as + arguments. + + All arguments are evaluated before switching to BUFFER. + + -- Function: magit-mode-display-buffer buffer mode &optional + switch-function + + This function display BUFFER in some window and select it. BUFFER + may be a buffer or a string, the name of a buffer. The buffer is + returned. + + Unless BUFFER is already displayed in the selected frame, store the + previous window configuration as a buffer local value, so that it + can later be restored by ‘magit-mode-bury-buffer’. + + The buffer is displayed and selected using SWITCH-FUNCTION. If + that is ‘nil’ then ‘pop-to-buffer’ is used if the current buffer’s + major mode derives from ‘magit-mode’. Otherwise ‘switch-to-buffer’ + is used. + + -- Variable: magit-refresh-function + + The value of this buffer-local variable is the function used to + refresh the current buffer. It is called with ‘magit-refresh-args’ + as arguments. + + -- Variable: magit-refresh-args + + The list of arguments used by ‘magit-refresh-function’ to refresh + the current buffer. ‘magit-refresh-function’ is called with these + arguments. + + The value is usually set using ‘magit-mode-setup’, but in some + cases it’s also useful to provide commands that can change the + value. For example, the ‘magit-diff-refresh’ transient can be used + to change any of the arguments used to display the diff, without + having to specify again which differences should be shown, but + ‘magit-diff-more-context’, ‘magit-diff-less-context’ and + ‘magit-diff-default-context’ change just the ‘-U’ argument. In + both case this is done by changing the value of this variable and + then calling this ‘magit-refresh-function’. + + +File: magit.info, Node: Conventions, Prev: Refreshing Buffers, Up: Plumbing + +10.4 Conventions +================ + +Also see *note Completion and Confirmation::. + +* Menu: + +* Theming Faces:: + + +File: magit.info, Node: Theming Faces, Up: Conventions + +10.4.1 Theming Faces +-------------------- + +The default theme uses blue for local branches, green for remote +branches, and goldenrod (brownish yellow) for tags. When creating a new +theme, you should probably follow that example. If your theme already +uses other colors, then stick to that. + + In older releases these reference faces used to have a background +color and a box around them. The basic default faces no longer do so, +to make Magit buffers much less noisy, and you should follow that +example at least with regards to boxes. (Boxes were used in the past to +work around a conflict between the highlighting overlay and text +property backgrounds. That’s no longer necessary because highlighting +no longer causes other background colors to disappear.) Alternatively +you can keep the background color and/or box, but then have to take +special care to adjust ‘magit-branch-current’ accordingly. By default +it looks mostly like ‘magit-branch-local’, but with a box (by default +the former is the only face that uses a box, exactly so that it sticks +out). If the former also uses a box, then you have to make sure that it +differs in some other way from the latter. + + The most difficult faces to theme are those related to diffs, +headings, highlighting, and the region. There are faces that fall into +all four groups - expect to spend some time getting this right. + + The ‘region’ face in the default theme, in both the light and dark +variants, as well as in many other themes, distributed with Emacs or by +third-parties, is very ugly. It is common to use a background color +that really sticks out, which is ugly but if that were the only problem +then it would be acceptable. Unfortunately many themes also set the +foreground color, which ensures that all text within the region is +readable. Without doing that there might be cases where some foreground +color is too close to the region background color to still be readable. +But it also means that text within the region loses all syntax +highlighting. + + I consider the work that went into getting the ‘region’ face right to +be a good indicator for the general quality of a theme. My +recommendation for the ‘region’ face is this: use a background color +slightly different from the background color of the ‘default’ face, and +do not set the foreground color at all. So for a light theme you might +use a light (possibly tinted) gray as the background color of ‘default’ +and a somewhat darker gray for the background of ‘region’. That should +usually be enough to not collide with the foreground color of any other +face. But if some other faces also set a light gray as background +color, then you should also make sure it doesn’t collide with those (in +some cases it might be acceptable though). + + Magit only uses the ‘region’ face when the region is "invalid" by its +own definition. In a Magit buffer the region is used to either select +multiple sibling sections, so that commands which support it act on all +of these sections instead of just the current section, or to select +lines within a single hunk section. In all other cases, the section is +considered invalid and Magit won’t act on it. But such invalid sections +happen, either because the user has not moved point enough yet to make +it valid or because she wants to use a non-magit command to act on the +region, e.g. ‘kill-region’. + + So using the regular ‘region’ face for invalid sections is a feature. +It tells the user that Magit won’t be able to act on it. It’s +acceptable if that face looks a bit odd and even (but less so) if it +collides with the background colors of section headings and other things +that have a background color. + + Magit highlights the current section. If a section has subsections, +then all of them are highlighted. This is done using faces that have +"highlight" in their names. For most sections, +‘magit-section-highlight’ is used for both the body and the heading. +Like the ‘region’ face, it should only set the background color to +something similar to that of ‘default’. The highlight background color +must be different from both the ‘region’ background color and the +‘default’ background color. + + For diff related sections Magit uses various faces to highlight +different parts of the selected section(s). Note that hunk headings, +unlike all other section headings, by default have a background color, +because it is useful to have very visible separators between hunks. +That face ‘magit-diff-hunk-heading’, should be different from both +‘magit-diff-hunk-heading-highlight’ and ‘magit-section-highlight’, as +well as from ‘magit-diff-context’ and ‘magit-diff-context-highlight’. +By default we do that by changing the foreground color. Changing the +background color would lead to complications, and there are already +enough we cannot get around. (Also note that it is generally a good +idea for section headings to always be bold, but only for sections that +have subsections). + + When there is a valid region selecting diff-related sibling sections, +i.e. multiple files or hunks, then the bodies of all these sections use +the respective highlight faces, but additionally the headings instead +use one of the faces ‘magit-diff-file-heading-selection’ or +‘magit-diff-hunk-heading-selection’. These faces have to be different +from the regular highlight variants to provide explicit visual +indication that the region is active. + + When theming diff related faces, start by setting the option +‘magit-diff-refine-hunk’ to ‘all’. You might personally prefer to only +refine the current hunk or not use hunk refinement at all, but some of +the users of your theme want all hunks to be refined, so you have to +cater to that. + + (Also turn on ‘magit-diff-highlight-indentation’, +‘magit-diff-highlight-trailing’, and ‘magit-diff-paint-whitespace’; and +insert some whitespace errors into the code you use for testing.) + + For e.g. "added lines" you have to adjust three faces: +‘magit-diff-added’, ‘magit-diff-added-highlight’, and +‘smerge-refined-added’. Make sure that the latter works well with both +of the former, as well as ‘smerge-other’ and ‘diff-added’. Then do the +same for the removed lines, context lines, lines added by us, and lines +added by them. Also make sure the respective added, removed, and +context faces use approximately the same saturation for both the +highlighted and unhighlighted variants. Also make sure the file and +diff headings work nicely with context lines (e.g. make them look +different). Line faces should set both the foreground and the +background color. For example, for added lines use two different +greens. + + It’s best if the foreground color of both the highlighted and the +unhighlighted variants are the same, so you will need to have to find a +color that works well on the highlight and unhighlighted background, the +refine background, and the highlight context background. When there is +an hunk internal region, then the added- and removed-lines background +color is used only within that region. Outside the region the +highlighted context background color is used. This makes it easier to +see what is being staged. With an hunk internal region the hunk heading +is shown using ‘magit-diff-hunk-heading-selection’, and so are the thin +lines that are added around the lines that fall within the region. The +background color of that has to be distinct enough from the various +other involved background colors. + + Nobody said this would be easy. If your theme restricts itself to a +certain set of colors, then you should make an exception here. +Otherwise it would be impossible to make the diffs look good in each and +every variation. Actually you might want to just stick to the default +definitions for these faces. You have been warned. Also please note +that if you do not get this right, this will in some cases look to users +like bugs in Magit - so please do it right or not at all. + + +File: magit.info, Node: FAQ, Next: Debugging Tools, Prev: Plumbing, Up: Top + +Appendix A FAQ +************** + +The next two nodes lists frequently asked questions. For a list of +frequently *and recently* asked questions, i.e. questions that haven’t +made it into the manual yet, see +. + + Please also use the *note Debugging Tools::. + +* Menu: + +* FAQ - How to ...?:: +* FAQ - Issues and Errors:: + + +File: magit.info, Node: FAQ - How to ...?, Next: FAQ - Issues and Errors, Up: FAQ + +A.1 FAQ - How to ...? +===================== + +* Menu: + +* How to show git's output?:: +* How to install the gitman info manual?:: +* How to show diffs for gpg-encrypted files?:: +* How does branching and pushing work?:: +* Can Magit be used as ediff-version-control-package?:: + + +File: magit.info, Node: How to show git's output?, Next: How to install the gitman info manual?, Up: FAQ - How to ...? + +A.1.1 How to show git’s output? +------------------------------- + +To show the output of recently run git commands, press ‘$’ (or, if that +isn’t available, ‘M-x magit-process-buffer’). This will show a buffer +containing a section per git invocation; as always press ‘TAB’ to expand +or collapse them. + + By default, git’s output is only inserted into the process buffer if +it is run for side-effects. When the output is consumed in some way, +also inserting it into the process buffer would be too expensive. For +debugging purposes, it’s possible to do so anyway by setting +‘magit-git-debug’ to ‘t’. + + +File: magit.info, Node: How to install the gitman info manual?, Next: How to show diffs for gpg-encrypted files?, Prev: How to show git's output?, Up: FAQ - How to ...? + +A.1.2 How to install the gitman info manual? +-------------------------------------------- + +Git’s manpages can be exported as an info manual called ‘gitman’. +Magit’s own info manual links to nodes in that manual instead of the +actual manpages because Info doesn’t support linking to manpages. + + Unfortunately some distributions do not install the ‘gitman’ manual +by default and you will have to install a separate documentation package +to get it. + + Magit patches Info adding the ability to visit links to the ‘gitman’ +Info manual by instead viewing the respective manpage. If you prefer +that approach, then set the value of ‘magit-view-git-manual-method’ to +one of the supported packages ‘man’ or ‘woman’, e.g.: + + (setq magit-view-git-manual-method 'man) + + +File: magit.info, Node: How to show diffs for gpg-encrypted files?, Next: How does branching and pushing work?, Prev: How to install the gitman info manual?, Up: FAQ - How to ...? + +A.1.3 How to show diffs for gpg-encrypted files? +------------------------------------------------ + +Git supports showing diffs for encrypted files, but has to be told to do +so. Since Magit just uses Git to get the diffs, configuring Git also +affects the diffs displayed inside Magit. + + git config --global diff.gpg.textconv "gpg --no-tty --decrypt" + echo "*.gpg filter=gpg diff=gpg" > .gitattributes + + +File: magit.info, Node: How does branching and pushing work?, Next: Can Magit be used as ediff-version-control-package?, Prev: How to show diffs for gpg-encrypted files?, Up: FAQ - How to ...? + +A.1.4 How does branching and pushing work? +------------------------------------------ + +Please see *note Branching:: and + + + +File: magit.info, Node: Can Magit be used as ediff-version-control-package?, Prev: How does branching and pushing work?, Up: FAQ - How to ...? + +A.1.5 Can Magit be used as ‘ediff-version-control-package’? +----------------------------------------------------------- + +No, it cannot. For that to work the functions ‘ediff-magit-internal’ +and ‘ediff-magit-merge-internal’ would have to be implemented, and they +are not. These two functions are only used by the three commands +‘ediff-revision’, ‘ediff-merge-revisions-with-ancestor’, and +‘ediff-merge-revisions’. + + These commands only delegate the task of populating buffers with +certain revisions to the "internal" functions. The equally important +task of determining which revisions are to be compared/merged is not +delegated. Instead this is done without any support whatsoever from the +version control package/system - meaning that the user has to enter the +revisions explicitly. Instead of implementing ‘ediff-magit-internal’ we +provide ‘magit-ediff-compare’, which handles both tasks like it is 2005. + + The other commands ‘ediff-merge-revisions’ and +‘ediff-merge-revisions-with-ancestor’ are normally not what you want +when using a modern version control system like Git. Instead of letting +the user resolve only those conflicts which Git could not resolve on its +own, they throw away all work done by Git and then expect the user to +manually merge all conflicts, including those that had already been +resolved. That made sense back in the days when version control systems +couldn’t merge (or so I have been told), but not anymore. Once in a +blue moon you might actually want to see all conflicts, in which case +you *can* use these commands, which then use ‘ediff-vc-merge-internal’. +So we don’t actually have to implement ‘ediff-magit-merge-internal’. +Instead we provide the more useful command ‘magit-ediff-resolve’ which +only shows yet-to-be resolved conflicts. + + +File: magit.info, Node: FAQ - Issues and Errors, Prev: FAQ - How to ...?, Up: FAQ + +A.2 FAQ - Issues and Errors +=========================== + +* Menu: + +* Magit is slow:: +* I changed several thousand files at once and now Magit is unusable:: +* I am having problems committing:: +* I am using MS Windows and cannot push with Magit:: +* I am using OS X and SOMETHING works in shell, but not in Magit: I am using OS X and SOMETHING works in shell but not in Magit. +* Diffs contain control sequences:: +* Expanding a file to show the diff causes it to disappear:: +* Point is wrong in the COMMIT_EDITMSG buffer:: +* The mode-line information isn't always up-to-date:: +* A branch and tag sharing the same name breaks SOMETHING:: +* My Git hooks work on the command-line but not inside Magit:: +* git-commit-mode isn't used when committing from the command-line:: +* Point ends up inside invisible text when jumping to a file-visiting buffer:: + + +File: magit.info, Node: Magit is slow, Next: I changed several thousand files at once and now Magit is unusable, Up: FAQ - Issues and Errors + +A.2.1 Magit is slow +------------------- + +See *note Performance::. + + +File: magit.info, Node: I changed several thousand files at once and now Magit is unusable, Next: I am having problems committing, Prev: Magit is slow, Up: FAQ - Issues and Errors + +A.2.2 I changed several thousand files at once and now Magit is unusable +------------------------------------------------------------------------ + +Magit is *currently* not expected to work under such conditions. It +sure would be nice if it did, and v2.5 will hopefully be a big step into +that direction. But it might take until v3.1 to accomplish fully +satisfactory performance, because that requires some heavy refactoring. + + But for now we recommend you use the command line to complete this +one commit. Also see *note Performance::. + + +File: magit.info, Node: I am having problems committing, Next: I am using MS Windows and cannot push with Magit, Prev: I changed several thousand files at once and now Magit is unusable, Up: FAQ - Issues and Errors + +A.2.3 I am having problems committing +------------------------------------- + +That likely means that Magit is having problems finding an appropriate +emacsclient executable. See *note (with-editor)Configuring +With-Editor:: and *note (with-editor)Debugging::. + + +File: magit.info, Node: I am using MS Windows and cannot push with Magit, Next: I am using OS X and SOMETHING works in shell but not in Magit, Prev: I am having problems committing, Up: FAQ - Issues and Errors + +A.2.4 I am using MS Windows and cannot push with Magit +------------------------------------------------------ + +It’s almost certain that Magit is only incidental to this issue. It is +much more likely that this is a configuration issue, even if you can +push on the command line. + + Detailed setup instructions can be found at +. + + +File: magit.info, Node: I am using OS X and SOMETHING works in shell but not in Magit, Next: Diffs contain control sequences, Prev: I am using MS Windows and cannot push with Magit, Up: FAQ - Issues and Errors + +A.2.5 I am using OS X and SOMETHING works in shell, but not in Magit +-------------------------------------------------------------------- + +This usually occurs because Emacs doesn’t have the same environment +variables as your shell. Try installing and configuring +. By default it +synchronizes ‘$PATH’, which helps Magit find the same ‘git’ as the one +you are using on the shell. + + If SOMETHING is "passphrase caching with gpg-agent for commit and/or +tag signing", then you’ll also need to synchronize ‘$GPG_AGENT_INFO’. + + +File: magit.info, Node: Diffs contain control sequences, Next: Expanding a file to show the diff causes it to disappear, Prev: I am using OS X and SOMETHING works in shell but not in Magit, Up: FAQ - Issues and Errors + +A.2.6 Diffs contain control sequences +------------------------------------- + +This happens when you configure Git to always color diffs and/or all of +its output. The valid values for relevant Git variables ‘color.ui’ and +‘color.diff’ are ‘false’, ‘true’ and ‘always’, and the default is +‘true’. You should leave it that way because then you get colorful +output in terminals by default but when git’s output is consumed by +something else, then no color control sequences are used. + + If you actually use some other tool that requires setting ‘color.ui’ +and/or ‘color.diff’ to ‘always’ (which is highly unlikely), then you can +override these settings just for Magit by using: + + (setq magit-git-global-arguments + (nconc magit-git-global-arguments + '("-c" "color.ui=false" + "-c" "color.diff=false"))) + + +File: magit.info, Node: Expanding a file to show the diff causes it to disappear, Next: Point is wrong in the COMMIT_EDITMSG buffer, Prev: Diffs contain control sequences, Up: FAQ - Issues and Errors + +A.2.7 Expanding a file to show the diff causes it to disappear +-------------------------------------------------------------- + +This is probably caused by a change of a ‘diff.*’ Git variable. You +probably set that variable for a reason, and should therefore only undo +that setting in Magit by customizing ‘magit-git-global-arguments’. + + +File: magit.info, Node: Point is wrong in the COMMIT_EDITMSG buffer, Next: The mode-line information isn't always up-to-date, Prev: Expanding a file to show the diff causes it to disappear, Up: FAQ - Issues and Errors + +A.2.8 Point is wrong in the ‘COMMIT_EDITMSG’ buffer +--------------------------------------------------- + +Neither Magit nor ‘git-commit‘ fiddle with point in the buffer used to +write commit messages, so something else must be doing it. + + You have probably globally enabled a mode which does restore point in +file-visiting buffers. It might be a bit surprising, but when you write +a commit message, then you are actually editing a file. + + So you have to figure out which package is doing. ‘saveplace’, +‘pointback’, and ‘session’ are likely candidates. These snippets might +help: + + (setq session-name-disable-regexp "\\(?:\\`'\\.git/[A-Z_]+\\'\\)") + + (with-eval-after-load 'pointback + (lambda () + (when (or git-commit-mode git-rebase-mode) + (pointback-mode -1)))) + + +File: magit.info, Node: The mode-line information isn't always up-to-date, Next: A branch and tag sharing the same name breaks SOMETHING, Prev: Point is wrong in the COMMIT_EDITMSG buffer, Up: FAQ - Issues and Errors + +A.2.9 The mode-line information isn’t always up-to-date +------------------------------------------------------- + +Magit is not responsible for the version control information that is +being displayed in the mode-line and looks something like ‘Git-master’. +The built-in "Version Control" package, also known as "VC", updates that +information, and can be told to do so more often: + + (setq auto-revert-check-vc-info t) + + But doing so isn’t good for performance. For more (overly +optimistic) information see *note (emacs)VC Mode Line::. + + If you don’t really care about seeing that information in the +mode-line, but just don’t want to see _incorrect_ information, then +consider disabling VC when using Git: + + (setq vc-handled-backends (delq 'Git vc-handled-backends)) + + Or to disable it completely: + + (setq vc-handled-backends nil) + + +File: magit.info, Node: A branch and tag sharing the same name breaks SOMETHING, Next: My Git hooks work on the command-line but not inside Magit, Prev: The mode-line information isn't always up-to-date, Up: FAQ - Issues and Errors + +A.2.10 A branch and tag sharing the same name breaks SOMETHING +-------------------------------------------------------------- + +Or more generally, ambiguous refnames break SOMETHING. + + Magit assumes that refs are named non-ambiguously across the +"refs/heads/", "refs/tags/", and "refs/remotes/" namespaces (i.e., all +the names remain unique when those prefixes are stripped). We consider +ambiguous refnames unsupported and recommend that you use a +non-ambiguous naming scheme. However, if you do work with a repository +that has ambiguous refnames, please report any issues you encounter so +that we can investigate whether there is a simple fix. + + +File: magit.info, Node: My Git hooks work on the command-line but not inside Magit, Next: git-commit-mode isn't used when committing from the command-line, Prev: A branch and tag sharing the same name breaks SOMETHING, Up: FAQ - Issues and Errors + +A.2.11 My Git hooks work on the command-line but not inside Magit +----------------------------------------------------------------- + +When Magit calls ‘git’ it adds a few global arguments including +‘--literal-pathspecs’ and the ‘git’ process started by Magit then passes +that setting on to other ‘git’ process it starts itself. It does so by +setting the environment variable ‘GIT_LITERAL_PATHSPECS’, not by calling +subprocesses with the ‘--literal-pathspecs’ argument. You can therefore +override this setting in hook scripts using ‘unset +GIT_LITERAL_PATHSPECS’. + + +File: magit.info, Node: git-commit-mode isn't used when committing from the command-line, Next: Point ends up inside invisible text when jumping to a file-visiting buffer, Prev: My Git hooks work on the command-line but not inside Magit, Up: FAQ - Issues and Errors + +A.2.12 ‘git-commit-mode’ isn’t used when committing from the command-line +------------------------------------------------------------------------- + +The reason for this is that ‘git-commit.el’ has not been loaded yet +and/or that the server has not been started yet. These things have +always already been taken care of when you commit from Magit because in +order to do so, Magit has to be loaded and doing that involves loading +‘git-commit’ and starting the server. + + If you want to commit from the command-line, then you have to take +care of these things yourself. Your ‘init.el’ file should contain: + + (require 'git-commit) + (server-mode) + + Instead of ‘(require ’git-commit)‘ you may also use: + + (load "/path/to/magit-autoloads.el") + + You might want to do that because loading ‘git-commit’ causes large +parts of Magit to be loaded. + + There are also some variations of ‘(server-mode)’ that you might want +to try. Personally I use: + + (use-package server + :config (or (server-running-p) (server-mode))) + + Now you can use: + + $ emacs& + $ EDITOR=emacsclient git commit + + However you cannot use: + + $ killall emacs + $ EDITOR="emacsclient --alternate-editor emacs" git commit + + This will actually end up using ‘emacs’, not ‘emacsclient’. If you +do this, then can still edit the commit message but ‘git-commit-mode’ +won’t be used and you have to exit ‘emacs’ to finish the process. + + Tautology ahead. If you want to be able to use ‘emacsclient’ to +connect to a running ‘emacs’ instance, even though no ‘emacs’ instance +is running, then you cannot use ‘emacsclient’ directly. + + Instead you have to create a script that does something like this: + + Try to use ‘emacsclient’ (without using ‘--alternate-editor’). If +that succeeds, do nothing else. Otherwise start ‘emacs &’ (and +‘init.el’ must call ‘server-start’) and try to use ‘emacsclient’ again. + + +File: magit.info, Node: Point ends up inside invisible text when jumping to a file-visiting buffer, Prev: git-commit-mode isn't used when committing from the command-line, Up: FAQ - Issues and Errors + +A.2.13 Point ends up inside invisible text when jumping to a file-visiting buffer +--------------------------------------------------------------------------------- + +This can happen when you type ‘RET’ on a hunk to visit the respective +file at the respective position. One solution to this problem is to use +‘global-reveal-mode’. It makes sure that text around point is always +visible. If that is too drastic for your taste, then you may instead +use ‘magit-diff-visit-file-hook’ to reveal the text, possibly using +‘reveal-post-command’ or for Org buffers ‘org-reveal’. + + +File: magit.info, Node: Debugging Tools, Next: Keystroke Index, Prev: FAQ, Up: Top + +B Debugging Tools +***************** + +Magit and its dependencies provide a few debugging tools, and we +appreciate it very much if you use those tools before reporting an +issue. Please include all relevant output when reporting an issue. + +‘M-x magit-version’ (‘magit-version’) + + This command shows the currently used versions of Magit, Git, and + Emacs in the echo area. Non-interactively this just returns the + Magit version. + +‘M-x magit-emacs-Q-command’ (‘magit-emacs-Q-command’) + + This command shows a debugging shell command in the echo area and + adds it to the kill ring. Paste that command into a shell and run + it. + + This shell command starts ‘emacs’ with only ‘magit’ and its + dependencies loaded. Neither your configuration nor other + installed packages are loaded. This makes it easier to determine + whether some issue lays with Magit or something else. + + If you run Magit from its Git repository, then you should be able + to use ‘make emacs-Q’ instead of the output of this command. + +‘M-x magit-debug-git-executable’ (‘magit-debug-git-executable’) + + This command displays a buffer containing information about the + available and used ‘git’ executable(s), and can be useful when + investigating ‘exec-path’ issues. + + Also see *note Git Executable::. + +‘M-x with-editor-debug’ (‘with-editor-debug’) + + This command displays a buffer containing information about the + available and used ‘~emacsclient’ executable(s), and can be useful + when investigating why Magit (or rather ‘with-editor’) cannot find + an appropriate ‘emacsclient’ executable. + + Also see *note (with-editor)Debugging::. + + Please also see the *note FAQ::. + + +File: magit.info, Node: Keystroke Index, Next: Command Index, Prev: Debugging Tools, Up: Top + +Appendix C Keystroke Index +************************** + +[index] +* Menu: + +* !: Running Git Manually. + (line 12) +* ! !: Running Git Manually. + (line 17) +* ! a: Running Git Manually. + (line 58) +* ! b: Running Git Manually. + (line 62) +* ! g: Running Git Manually. + (line 66) +* ! k: Running Git Manually. + (line 54) +* ! p: Running Git Manually. + (line 25) +* ! s: Running Git Manually. + (line 35) +* ! S: Running Git Manually. + (line 40) +* $: Viewing Git Output. (line 16) +* %: Worktree. (line 8) +* % b: Worktree. (line 13) +* % c: Worktree. (line 17) +* % g: Worktree. (line 30) +* % k: Worktree. (line 25) +* % m: Worktree. (line 21) +* +: Log Buffer. (line 61) +* + <1>: Refreshing Diffs. (line 69) +* -: Log Buffer. (line 65) +* - <1>: Refreshing Diffs. (line 65) +* 0: Refreshing Diffs. (line 73) +* 1: Section Visibility. (line 26) +* 2: Section Visibility. (line 27) +* 3: Section Visibility. (line 28) +* 4: Section Visibility. (line 29) +* =: Log Buffer. (line 55) +* ^: Section Movement. (line 31) +* a: Applying. (line 33) +* A: Cherry Picking. (line 8) +* A A: Cherry Picking. (line 17) +* A a: Cherry Picking. (line 24) +* A A <1>: Cherry Picking. (line 90) +* A a <1>: Cherry Picking. (line 98) +* A d: Cherry Picking. (line 54) +* A h: Cherry Picking. (line 42) +* A n: Cherry Picking. (line 65) +* A s: Cherry Picking. (line 76) +* A s <1>: Cherry Picking. (line 94) +* B: Bisecting. (line 8) +* b: Blaming. (line 105) +* b <1>: Branch Commands. (line 12) +* b <2>: Editing Rebase Sequences. + (line 85) +* B B: Bisecting. (line 16) +* B b: Bisecting. (line 31) +* b b: Branch Commands. (line 49) +* b C: Branch Commands. (line 29) +* b c: Branch Commands. (line 67) +* B g: Bisecting. (line 36) +* B k: Bisecting. (line 41) +* b k: Branch Commands. (line 147) +* b l: Branch Commands. (line 74) +* b n: Branch Commands. (line 57) +* B r: Bisecting. (line 47) +* b r: Branch Commands. (line 153) +* B s: Bisecting. (line 24) +* b s: Branch Commands. (line 97) +* b S: Branch Commands. (line 125) +* b x: Branch Commands. (line 131) +* c: Blaming. (line 138) +* C: Cloning Repository. (line 20) +* c <1>: Initiating a Commit. (line 8) +* c <2>: Editing Rebase Sequences. + (line 72) +* c a: Initiating a Commit. (line 19) +* c A: Initiating a Commit. (line 67) +* C b: Cloning Repository. (line 41) +* C C: Cloning Repository. (line 29) +* c c: Initiating a Commit. (line 14) +* C d: Cloning Repository. (line 54) +* C e: Cloning Repository. (line 61) +* c e: Initiating a Commit. (line 23) +* c f: Initiating a Commit. (line 43) +* c F: Initiating a Commit. (line 51) +* C m: Cloning Repository. (line 46) +* C s: Cloning Repository. (line 34) +* c s: Initiating a Commit. (line 55) +* c S: Initiating a Commit. (line 63) +* c w: Initiating a Commit. (line 33) +* C-: Visiting Files and Blobs from a Diff. + (line 51) +* C-: Section Visibility. (line 13) +* C-c C-a: Editing Commit Messages. + (line 128) +* C-c C-b: Log Buffer. (line 21) +* C-c C-b <1>: Refreshing Diffs. (line 91) +* C-c C-c: Transient Commands. (line 18) +* C-c C-c <1>: Select from Log. (line 20) +* C-c C-c <2>: Editing Commit Messages. + (line 19) +* C-c C-c <3>: Editing Rebase Sequences. + (line 6) +* C-c C-d: Refreshing Diffs. (line 81) +* C-c C-d <1>: Editing Commit Messages. + (line 57) +* C-c C-e: Commands Available in Diffs. + (line 25) +* C-c C-f: Log Buffer. (line 25) +* C-c C-f <1>: Refreshing Diffs. (line 95) +* C-c C-i: Editing Commit Messages. + (line 153) +* C-c C-k: Select from Log. (line 26) +* C-c C-k <1>: Editing Commit Messages. + (line 24) +* C-c C-k <2>: Editing Rebase Sequences. + (line 11) +* C-c C-n: Log Buffer. (line 29) +* C-c C-o: Editing Commit Messages. + (line 144) +* C-c C-p: Editing Commit Messages. + (line 148) +* C-c C-r: Editing Commit Messages. + (line 132) +* C-c C-s: Editing Commit Messages. + (line 136) +* C-c C-t: Commands Available in Diffs. + (line 14) +* C-c C-t <1>: Editing Commit Messages. + (line 140) +* C-c C-w: Editing Commit Messages. + (line 63) +* C-c M-g: Minor Mode for Buffers Visiting Files. + (line 54) +* C-c M-g B: Blaming. (line 21) +* C-c M-g b: Blaming. (line 32) +* C-c M-g B <1>: Minor Mode for Buffers Visiting Files. + (line 123) +* C-c M-g B b: Blaming. (line 33) +* C-c M-g B e: Blaming. (line 67) +* C-c M-g B f: Blaming. (line 58) +* C-c M-g B r: Blaming. (line 49) +* C-c M-g c: Minor Mode for Buffers Visiting Files. + (line 68) +* C-c M-g D: Minor Mode for Buffers Visiting Files. + (line 75) +* C-c M-g d: Minor Mode for Buffers Visiting Files. + (line 86) +* C-c M-g e: Blaming. (line 66) +* C-c M-g e <1>: Minor Mode for Buffers Visiting Files. + (line 136) +* C-c M-g f: Blaming. (line 57) +* C-c M-g L: Minor Mode for Buffers Visiting Files. + (line 96) +* C-c M-g l: Minor Mode for Buffers Visiting Files. + (line 107) +* C-c M-g p: Minor Mode for Buffers Visiting Files. + (line 146) +* C-c M-g r: Blaming. (line 48) +* C-c M-g s: Minor Mode for Buffers Visiting Files. + (line 59) +* C-c M-g t: Minor Mode for Buffers Visiting Files. + (line 114) +* C-c M-g u: Minor Mode for Buffers Visiting Files. + (line 63) +* C-c M-s: Editing Commit Messages. + (line 35) +* C-w: Common Commands. (line 27) +* C-x g: Status Buffer. (line 22) +* C-x u: Editing Rebase Sequences. + (line 94) +* d: Diffing. (line 21) +* D: Refreshing Diffs. (line 11) +* d c: Diffing. (line 69) +* d d: Diffing. (line 27) +* D f: Refreshing Diffs. (line 46) +* D F: Refreshing Diffs. (line 51) +* D g: Refreshing Diffs. (line 17) +* d p: Diffing. (line 61) +* d r: Diffing. (line 31) +* D r: Refreshing Diffs. (line 41) +* d s: Diffing. (line 51) +* D s: Refreshing Diffs. (line 22) +* d t: Diffing. (line 74) +* D t: Refreshing Diffs. (line 37) +* d u: Diffing. (line 57) +* d w: Diffing. (line 45) +* D w: Refreshing Diffs. (line 29) +* DEL: Log Buffer. (line 45) +* DEL <1>: Commands Available in Diffs. + (line 60) +* DEL <2>: Blaming. (line 92) +* DEL <3>: Editing Rebase Sequences. + (line 28) +* e: Ediffing. (line 9) +* E: Ediffing. (line 21) +* e <1>: Editing Rebase Sequences. + (line 55) +* E c: Ediffing. (line 65) +* E i: Ediffing. (line 57) +* E m: Ediffing. (line 35) +* E r: Ediffing. (line 26) +* E s: Ediffing. (line 48) +* E u: Ediffing. (line 53) +* E w: Ediffing. (line 61) +* E z: Ediffing. (line 69) +* f: Editing Rebase Sequences. + (line 63) +* f <1>: Fetching. (line 9) +* F: Pulling. (line 9) +* f a: Fetching. (line 46) +* f C: Branch Commands. (line 30) +* F C: Branch Commands. (line 31) +* f e: Fetching. (line 32) +* F e: Pulling. (line 31) +* f m: Fetching. (line 50) +* f o: Fetching. (line 36) +* f p: Fetching. (line 15) +* F p: Pulling. (line 14) +* f r: Fetching. (line 41) +* f u: Fetching. (line 24) +* F u: Pulling. (line 23) +* g: Automatic Refreshing of Magit Buffers. + (line 24) +* G: Automatic Refreshing of Magit Buffers. + (line 33) +* j: Commands Available in Diffs. + (line 45) +* k: Viewing Git Output. (line 24) +* k <1>: Applying. (line 40) +* k <2>: Editing Rebase Sequences. + (line 68) +* k <3>: Stashing. (line 96) +* l: Logging. (line 29) +* L: Refreshing Logs. (line 11) +* L <1>: Log Buffer. (line 6) +* L <2>: Log Margin. (line 57) +* l <1>: Editing Rebase Sequences. + (line 115) +* l a: Logging. (line 60) +* l b: Logging. (line 56) +* L d: Log Margin. (line 74) +* L g: Refreshing Logs. (line 17) +* l h: Logging. (line 48) +* l H: Reflog. (line 19) +* l l: Logging. (line 35) +* l L: Logging. (line 52) +* L L: Log Margin. (line 66) +* L l: Log Margin. (line 70) +* l o: Logging. (line 41) +* l O: Reflog. (line 15) +* l r: Reflog. (line 11) +* L s: Refreshing Logs. (line 22) +* L t: Refreshing Logs. (line 37) +* L w: Refreshing Logs. (line 29) +* m: Merging. (line 9) +* M: Remote Commands. (line 13) +* m a: Merging. (line 45) +* m a <1>: Merging. (line 95) +* M a: Remote Commands. (line 50) +* M C: Remote Commands. (line 33) +* m e: Merging. (line 31) +* m i: Merging. (line 58) +* M k: Remote Commands. (line 65) +* m m: Merging. (line 18) +* m m <1>: Merging. (line 89) +* m n: Merging. (line 38) +* m p: Merging. (line 81) +* M p: Remote Commands. (line 69) +* M P: Remote Commands. (line 74) +* M r: Remote Commands. (line 55) +* m s: Merging. (line 72) +* M u: Remote Commands. (line 60) +* M-1: Section Visibility. (line 33) +* M-2: Section Visibility. (line 34) +* M-3: Section Visibility. (line 35) +* M-4: Section Visibility. (line 36) +* M-: Section Visibility. (line 17) +* M-n: Section Movement. (line 26) +* M-n <1>: Editing Commit Messages. + (line 45) +* M-n <2>: Editing Rebase Sequences. + (line 47) +* M-p: Section Movement. (line 20) +* M-p <1>: Editing Commit Messages. + (line 39) +* M-p <2>: Editing Rebase Sequences. + (line 43) +* M-w: Blaming. (line 130) +* M-w <1>: Common Commands. (line 10) +* M-x magit-debug-git-executable: Git Executable. (line 45) +* M-x magit-debug-git-executable <1>: Debugging Tools. (line 30) +* M-x magit-describe-section-briefly: Section Types and Values. + (line 13) +* M-x magit-describe-section-briefly <1>: Matching Sections. (line 6) +* M-x magit-emacs-Q-command: Debugging Tools. (line 16) +* M-x magit-init: Creating Repository. (line 6) +* M-x magit-reset-index: Staging and Unstaging. + (line 87) +* M-x magit-reverse-in-index: Staging and Unstaging. + (line 62) +* M-x magit-stage-file: Staging from File-Visiting Buffers. + (line 10) +* M-x magit-toggle-buffer-lock: Modes and Buffers. (line 17) +* M-x magit-unstage-file: Staging from File-Visiting Buffers. + (line 18) +* M-x magit-version: Git Executable. (line 17) +* M-x magit-version <1>: Debugging Tools. (line 10) +* M-x magit-wip-commit: Wip Modes. (line 88) +* M-x with-editor-debug: Debugging Tools. (line 38) +* MM: Editing Rebase Sequences. + (line 125) +* Mt: Editing Rebase Sequences. + (line 132) +* n: Section Movement. (line 16) +* n <1>: Blaming. (line 109) +* N: Blaming. (line 113) +* n <2>: Editing Rebase Sequences. + (line 39) +* n <3>: Minor Mode for Buffers Visiting Blobs. + (line 16) +* o: Submodule Transient. (line 6) +* O: Subtree. (line 8) +* o a: Submodule Transient. (line 20) +* o d: Submodule Transient. (line 50) +* O e: Subtree. (line 42) +* O e p: Subtree. (line 54) +* O e s: Subtree. (line 59) +* o f: Submodule Transient. (line 58) +* O i: Subtree. (line 13) +* O i a: Subtree. (line 25) +* O i c: Subtree. (line 30) +* O i f: Subtree. (line 38) +* O i m: Subtree. (line 34) +* o l: Submodule Transient. (line 54) +* o p: Submodule Transient. (line 34) +* o r: Submodule Transient. (line 27) +* o s: Submodule Transient. (line 44) +* o u: Submodule Transient. (line 39) +* p: Section Movement. (line 10) +* p <1>: Blaming. (line 117) +* P: Blaming. (line 121) +* p <2>: Editing Rebase Sequences. + (line 35) +* P <1>: Pushing. (line 9) +* p <3>: Minor Mode for Buffers Visiting Blobs. + (line 12) +* P C: Branch Commands. (line 32) +* P e: Pushing. (line 31) +* P m: Pushing. (line 50) +* P o: Pushing. (line 36) +* P p: Pushing. (line 15) +* P r: Pushing. (line 41) +* P t: Pushing. (line 58) +* P T: Pushing. (line 66) +* P u: Pushing. (line 23) +* q: Quitting Windows. (line 6) +* q <1>: Log Buffer. (line 14) +* q <2>: Blaming. (line 125) +* q <3>: Minor Mode for Buffers Visiting Blobs. + (line 20) +* r: Rebasing. (line 9) +* r <1>: Editing Rebase Sequences. + (line 51) +* r a: Rebasing. (line 124) +* r e: Rebasing. (line 45) +* r e <1>: Rebasing. (line 119) +* r f: Rebasing. (line 85) +* r i: Rebasing. (line 81) +* r k: Rebasing. (line 100) +* r m: Rebasing. (line 90) +* r p: Rebasing. (line 28) +* r r: Rebasing. (line 107) +* r s: Rebasing. (line 51) +* r s <1>: Rebasing. (line 114) +* r u: Rebasing. (line 37) +* r w: Rebasing. (line 95) +* RET: References Buffer. (line 181) +* RET <1>: Visiting Files and Blobs from a Diff. + (line 8) +* RET <2>: Blaming. (line 78) +* RET <3>: Editing Rebase Sequences. + (line 16) +* s: Staging and Unstaging. + (line 28) +* S: Staging and Unstaging. + (line 36) +* s <1>: Editing Rebase Sequences. + (line 59) +* S-: Section Visibility. (line 22) +* SPC: Log Buffer. (line 35) +* SPC <1>: Commands Available in Diffs. + (line 56) +* SPC <2>: Blaming. (line 82) +* SPC <3>: Editing Rebase Sequences. + (line 21) +* t: Editing Rebase Sequences. + (line 119) +* t <1>: Tagging. (line 8) +* T: Notes. (line 8) +* T a: Notes. (line 52) +* T c: Notes. (line 47) +* t k: Tagging. (line 40) +* T m: Notes. (line 38) +* t p: Tagging. (line 47) +* T p: Notes. (line 30) +* t r: Tagging. (line 19) +* T r: Notes. (line 22) +* t t: Tagging. (line 14) +* T T: Notes. (line 14) +* TAB: Section Visibility. (line 9) +* u: Staging and Unstaging. + (line 43) +* U: Staging and Unstaging. + (line 52) +* v: Applying. (line 44) +* V: Reverting. (line 6) +* V A: Reverting. (line 31) +* V a: Reverting. (line 39) +* V s: Reverting. (line 35) +* V V: Reverting. (line 15) +* V v: Reverting. (line 21) +* W: Plain Patches. (line 6) +* w: Maildir Patches. (line 8) +* w a: Plain Patches. (line 21) +* w a <1>: Maildir Patches. (line 25) +* w a <2>: Maildir Patches. (line 43) +* W c: Plain Patches. (line 12) +* w m: Maildir Patches. (line 21) +* W s: Plain Patches. (line 28) +* w s: Maildir Patches. (line 38) +* w w: Maildir Patches. (line 14) +* w w <1>: Maildir Patches. (line 34) +* x: Editing Rebase Sequences. + (line 76) +* x <1>: Resetting. (line 8) +* X f: Resetting. (line 44) +* X h: Resetting. (line 26) +* X i: Resetting. (line 31) +* X m: Resetting. (line 15) +* X s: Resetting. (line 20) +* X w: Resetting. (line 38) +* X w <1>: Wip Modes. (line 66) +* Y: Cherries. (line 17) +* y: References Buffer. (line 6) +* y <1>: Editing Rebase Sequences. + (line 90) +* y c: References Buffer. (line 26) +* y o: References Buffer. (line 32) +* y y: References Buffer. (line 21) +* z: Stashing. (line 8) +* z a: Stashing. (line 59) +* z b: Stashing. (line 81) +* z B: Stashing. (line 86) +* z f: Stashing. (line 92) +* z i: Stashing. (line 21) +* z I: Stashing. (line 47) +* z k: Stashing. (line 72) +* z l: Stashing. (line 100) +* z p: Stashing. (line 65) +* z v: Stashing. (line 77) +* z w: Stashing. (line 26) +* z W: Stashing. (line 52) +* z x: Stashing. (line 33) +* z z: Stashing. (line 14) +* z Z: Stashing. (line 40) + + +File: magit.info, Node: Command Index, Next: Function Index, Prev: Keystroke Index, Up: Top + +Appendix D Command Index +************************ + +[index] +* Menu: + +* forward-line: Editing Rebase Sequences. + (line 39) +* git-commit-ack: Editing Commit Messages. + (line 128) +* git-commit-cc: Editing Commit Messages. + (line 144) +* git-commit-next-message: Editing Commit Messages. + (line 45) +* git-commit-prev-message: Editing Commit Messages. + (line 39) +* git-commit-reported: Editing Commit Messages. + (line 148) +* git-commit-review: Editing Commit Messages. + (line 132) +* git-commit-save-message: Editing Commit Messages. + (line 35) +* git-commit-signoff: Editing Commit Messages. + (line 136) +* git-commit-suggested: Editing Commit Messages. + (line 153) +* git-commit-test: Editing Commit Messages. + (line 140) +* git-rebase-backward-line: Editing Rebase Sequences. + (line 35) +* git-rebase-break: Editing Rebase Sequences. + (line 85) +* git-rebase-edit: Editing Rebase Sequences. + (line 55) +* git-rebase-exec: Editing Rebase Sequences. + (line 76) +* git-rebase-fixup: Editing Rebase Sequences. + (line 63) +* git-rebase-insert: Editing Rebase Sequences. + (line 90) +* git-rebase-kill-line: Editing Rebase Sequences. + (line 68) +* git-rebase-label: Editing Rebase Sequences. + (line 115) +* git-rebase-merge: Editing Rebase Sequences. + (line 125) +* git-rebase-merge-toggle-editmsg: Editing Rebase Sequences. + (line 132) +* git-rebase-move-line-down: Editing Rebase Sequences. + (line 47) +* git-rebase-move-line-up: Editing Rebase Sequences. + (line 43) +* git-rebase-pick: Editing Rebase Sequences. + (line 72) +* git-rebase-reset: Editing Rebase Sequences. + (line 119) +* git-rebase-reword: Editing Rebase Sequences. + (line 51) +* git-rebase-show-commit: Editing Rebase Sequences. + (line 16) +* git-rebase-show-or-scroll-down: Editing Rebase Sequences. + (line 28) +* git-rebase-show-or-scroll-up: Editing Rebase Sequences. + (line 21) +* git-rebase-squash: Editing Rebase Sequences. + (line 59) +* git-rebase-undo: Editing Rebase Sequences. + (line 94) +* ido-enter-magit-status: Status Buffer. (line 72) +* magit-am: Maildir Patches. (line 8) +* magit-am-abort: Maildir Patches. (line 43) +* magit-am-apply-maildir: Maildir Patches. (line 21) +* magit-am-apply-patches: Maildir Patches. (line 14) +* magit-am-continue: Maildir Patches. (line 34) +* magit-am-skip: Maildir Patches. (line 38) +* magit-apply: Applying. (line 33) +* magit-bisect: Bisecting. (line 8) +* magit-bisect-bad: Bisecting. (line 31) +* magit-bisect-good: Bisecting. (line 36) +* magit-bisect-reset: Bisecting. (line 47) +* magit-bisect-run: Bisecting. (line 24) +* magit-bisect-skip: Bisecting. (line 41) +* magit-bisect-start: Bisecting. (line 16) +* magit-blame: Blaming. (line 21) +* magit-blame <1>: Blaming. (line 105) +* magit-blame <2>: Minor Mode for Buffers Visiting Files. + (line 123) +* magit-blame-addition: Blaming. (line 32) +* magit-blame-addition <1>: Blaming. (line 33) +* magit-blame-copy-hash: Blaming. (line 130) +* magit-blame-cycle-style: Blaming. (line 138) +* magit-blame-echo: Blaming. (line 66) +* magit-blame-echo <1>: Blaming. (line 67) +* magit-blame-next-chunk: Blaming. (line 109) +* magit-blame-next-chunk-same-commit: Blaming. (line 113) +* magit-blame-previous-chunk: Blaming. (line 117) +* magit-blame-previous-chunk-same-commit: Blaming. (line 121) +* magit-blame-quit: Blaming. (line 125) +* magit-blame-removal: Blaming. (line 48) +* magit-blame-removal <1>: Blaming. (line 49) +* magit-blame-reverse: Blaming. (line 57) +* magit-blame-reverse <1>: Blaming. (line 58) +* magit-blob-next: Minor Mode for Buffers Visiting Blobs. + (line 16) +* magit-blob-previous: Minor Mode for Buffers Visiting Files. + (line 146) +* magit-blob-previous <1>: Minor Mode for Buffers Visiting Blobs. + (line 12) +* magit-branch: Branch Commands. (line 12) +* magit-branch-and-checkout: Branch Commands. (line 67) +* magit-branch-checkout: Branch Commands. (line 74) +* magit-branch-configure: Branch Commands. (line 29) +* magit-branch-configure <1>: Branch Commands. (line 30) +* magit-branch-configure <2>: Branch Commands. (line 31) +* magit-branch-configure <3>: Branch Commands. (line 32) +* magit-branch-create: Branch Commands. (line 57) +* magit-branch-delete: Branch Commands. (line 147) +* magit-branch-or-checkout: Branch Commands. (line 257) +* magit-branch-orphan: Branch Commands. (line 252) +* magit-branch-rename: Branch Commands. (line 153) +* magit-branch-reset: Branch Commands. (line 131) +* magit-branch-shelve: Auxiliary Branch Commands. + (line 9) +* magit-branch-spinoff: Branch Commands. (line 97) +* magit-branch-spinout: Branch Commands. (line 125) +* magit-branch-unshelve: Auxiliary Branch Commands. + (line 20) +* magit-checkout: Branch Commands. (line 49) +* magit-cherry: Cherries. (line 17) +* magit-cherry-apply: Cherry Picking. (line 24) +* magit-cherry-copy: Cherry Picking. (line 17) +* magit-cherry-donate: Cherry Picking. (line 54) +* magit-cherry-harvest: Cherry Picking. (line 42) +* magit-cherry-pick: Cherry Picking. (line 8) +* magit-cherry-spinoff: Cherry Picking. (line 76) +* magit-cherry-spinout: Cherry Picking. (line 65) +* magit-clone: Cloning Repository. (line 20) +* magit-clone-bare: Cloning Repository. (line 41) +* magit-clone-mirror: Cloning Repository. (line 46) +* magit-clone-regular: Cloning Repository. (line 29) +* magit-clone-shallow: Cloning Repository. (line 34) +* magit-clone-shallow-exclude: Cloning Repository. (line 61) +* magit-clone-shallow-since: Cloning Repository. (line 54) +* magit-commit: Initiating a Commit. (line 8) +* magit-commit <1>: Minor Mode for Buffers Visiting Files. + (line 68) +* magit-commit-amend: Initiating a Commit. (line 19) +* magit-commit-augment: Initiating a Commit. (line 67) +* magit-commit-create: Initiating a Commit. (line 14) +* magit-commit-extend: Initiating a Commit. (line 23) +* magit-commit-fixup: Initiating a Commit. (line 43) +* magit-commit-instant-fixup: Initiating a Commit. (line 51) +* magit-commit-instant-squash: Initiating a Commit. (line 63) +* magit-commit-reword: Initiating a Commit. (line 33) +* magit-commit-squash: Initiating a Commit. (line 55) +* magit-copy-buffer-revision: Common Commands. (line 27) +* magit-copy-section-value: Common Commands. (line 10) +* magit-cycle-margin-style: Log Margin. (line 70) +* magit-debug-git-executable: Git Executable. (line 45) +* magit-debug-git-executable <1>: Debugging Tools. (line 30) +* magit-describe-section-briefly: Section Types and Values. + (line 13) +* magit-describe-section-briefly <1>: Matching Sections. (line 6) +* magit-diff: Diffing. (line 21) +* magit-diff <1>: Minor Mode for Buffers Visiting Files. + (line 75) +* magit-diff-buffer-file: Minor Mode for Buffers Visiting Files. + (line 86) +* magit-diff-default-context: Refreshing Diffs. (line 73) +* magit-diff-dwim: Diffing. (line 27) +* magit-diff-edit-hunk-commit: Commands Available in Diffs. + (line 25) +* magit-diff-flip-revs: Refreshing Diffs. (line 46) +* magit-diff-less-context: Refreshing Diffs. (line 65) +* magit-diff-more-context: Refreshing Diffs. (line 69) +* magit-diff-paths: Diffing. (line 61) +* magit-diff-range: Diffing. (line 31) +* magit-diff-refresh: Refreshing Diffs. (line 11) +* magit-diff-refresh <1>: Refreshing Diffs. (line 17) +* magit-diff-save-default-arguments: Refreshing Diffs. (line 29) +* magit-diff-set-default-arguments: Refreshing Diffs. (line 22) +* magit-diff-show-or-scroll-down: Log Buffer. (line 45) +* magit-diff-show-or-scroll-down <1>: Blaming. (line 92) +* magit-diff-show-or-scroll-up: Log Buffer. (line 35) +* magit-diff-show-or-scroll-up <1>: Blaming. (line 82) +* magit-diff-staged: Diffing. (line 51) +* magit-diff-switch-range-type: Refreshing Diffs. (line 41) +* magit-diff-toggle-file-filter: Refreshing Diffs. (line 51) +* magit-diff-toggle-refine-hunk: Refreshing Diffs. (line 37) +* magit-diff-trace-definition: Commands Available in Diffs. + (line 14) +* magit-diff-unstaged: Diffing. (line 57) +* magit-diff-visit-file: Visiting Files and Blobs from a Diff. + (line 8) +* magit-diff-visit-file-other-frame: Visiting Files and Blobs from a Diff. + (line 74) +* magit-diff-visit-file-other-window: Visiting Files and Blobs from a Diff. + (line 73) +* magit-diff-visit-file-worktree: Visiting Files and Blobs from a Diff. + (line 51) +* magit-diff-visit-worktree-file-other-frame: Visiting Files and Blobs from a Diff. + (line 76) +* magit-diff-visit-worktree-file-other-window: Visiting Files and Blobs from a Diff. + (line 75) +* magit-diff-while-committing: Refreshing Diffs. (line 81) +* magit-diff-while-committing <1>: Editing Commit Messages. + (line 57) +* magit-diff-working-tree: Diffing. (line 45) +* magit-discard: Applying. (line 40) +* magit-dispatch: Transient Commands. (line 18) +* magit-ediff: Ediffing. (line 21) +* magit-ediff-compare: Ediffing. (line 26) +* magit-ediff-dwim: Ediffing. (line 9) +* magit-ediff-resolve: Ediffing. (line 35) +* magit-ediff-show-commit: Ediffing. (line 65) +* magit-ediff-show-staged: Ediffing. (line 57) +* magit-ediff-show-stash: Ediffing. (line 69) +* magit-ediff-show-unstaged: Ediffing. (line 53) +* magit-ediff-show-working-tree: Ediffing. (line 61) +* magit-ediff-stage: Ediffing. (line 48) +* magit-edit-line-commit: Minor Mode for Buffers Visiting Files. + (line 136) +* magit-emacs-Q-command: Debugging Tools. (line 16) +* magit-fetch: Fetching. (line 9) +* magit-fetch-all: Fetching. (line 46) +* magit-fetch-branch: Fetching. (line 36) +* magit-fetch-from-pushremote: Fetching. (line 15) +* magit-fetch-from-upstream: Fetching. (line 24) +* magit-fetch-modules: Submodule Transient. (line 58) +* magit-fetch-other: Fetching. (line 32) +* magit-fetch-refspec: Fetching. (line 41) +* magit-file-checkout: Resetting. (line 44) +* magit-file-checkout <1>: Minor Mode for Buffers Visiting Files. + (line 165) +* magit-file-delete: Minor Mode for Buffers Visiting Files. + (line 157) +* magit-file-dispatch: Minor Mode for Buffers Visiting Files. + (line 54) +* magit-file-rename: Minor Mode for Buffers Visiting Files. + (line 153) +* magit-file-untrack: Minor Mode for Buffers Visiting Files. + (line 161) +* magit-find-file: General-Purpose Visit Commands. + (line 9) +* magit-find-file-other-frame: General-Purpose Visit Commands. + (line 21) +* magit-find-file-other-window: General-Purpose Visit Commands. + (line 15) +* magit-git-command: Running Git Manually. + (line 25) +* magit-git-command-topdir: Running Git Manually. + (line 17) +* magit-go-backward: Log Buffer. (line 21) +* magit-go-backward <1>: Refreshing Diffs. (line 91) +* magit-go-forward: Log Buffer. (line 25) +* magit-go-forward <1>: Refreshing Diffs. (line 95) +* magit-init: Creating Repository. (line 6) +* magit-jump-to-diffstat-or-diff: Commands Available in Diffs. + (line 45) +* magit-kill-this-buffer: Minor Mode for Buffers Visiting Blobs. + (line 20) +* magit-list-repositories: Repository List. (line 6) +* magit-list-submodules: Listing Submodules. (line 13) +* magit-list-submodules <1>: Submodule Transient. (line 54) +* magit-log: Logging. (line 29) +* magit-log <1>: Minor Mode for Buffers Visiting Files. + (line 96) +* magit-log-all: Logging. (line 60) +* magit-log-all-branches: Logging. (line 56) +* magit-log-branches: Logging. (line 52) +* magit-log-buffer-file: Minor Mode for Buffers Visiting Files. + (line 107) +* magit-log-bury-buffer: Log Buffer. (line 14) +* magit-log-current: Logging. (line 35) +* magit-log-double-commit-limit: Log Buffer. (line 61) +* magit-log-half-commit-limit: Log Buffer. (line 65) +* magit-log-head: Logging. (line 48) +* magit-log-move-to-parent: Log Buffer. (line 29) +* magit-log-other: Logging. (line 41) +* magit-log-refresh: Refreshing Logs. (line 11) +* magit-log-refresh <1>: Refreshing Logs. (line 17) +* magit-log-refresh <2>: Log Buffer. (line 6) +* magit-log-save-default-arguments: Refreshing Logs. (line 29) +* magit-log-select-pick: Select from Log. (line 20) +* magit-log-select-quit: Select from Log. (line 26) +* magit-log-set-default-arguments: Refreshing Logs. (line 22) +* magit-log-toggle-commit-limit: Log Buffer. (line 55) +* magit-log-trace-definition: Minor Mode for Buffers Visiting Files. + (line 114) +* magit-margin-settings: Log Margin. (line 57) +* magit-merge: Merging. (line 9) +* magit-merge <1>: Merging. (line 89) +* magit-merge-abort: Merging. (line 95) +* magit-merge-absorb: Merging. (line 45) +* magit-merge-editmsg: Merging. (line 31) +* magit-merge-into: Merging. (line 58) +* magit-merge-nocommit: Merging. (line 38) +* magit-merge-plain: Merging. (line 18) +* magit-merge-preview: Merging. (line 81) +* magit-merge-squash: Merging. (line 72) +* magit-mode-bury-buffer: Quitting Windows. (line 6) +* magit-notes: Notes. (line 8) +* magit-notes-edit: Notes. (line 14) +* magit-notes-merge: Notes. (line 38) +* magit-notes-merge-abort: Notes. (line 52) +* magit-notes-merge-commit: Notes. (line 47) +* magit-notes-prune: Notes. (line 30) +* magit-notes-remove: Notes. (line 22) +* magit-patch: Plain Patches. (line 6) +* magit-patch-apply: Plain Patches. (line 21) +* magit-patch-apply <1>: Maildir Patches. (line 25) +* magit-patch-create: Plain Patches. (line 12) +* magit-patch-save: Plain Patches. (line 28) +* magit-pop-revision-stack: Editing Commit Messages. + (line 63) +* magit-process: Viewing Git Output. (line 16) +* magit-process-kill: Viewing Git Output. (line 24) +* magit-pull: Pulling. (line 9) +* magit-pull-branch: Pulling. (line 31) +* magit-pull-from-pushremote: Pulling. (line 14) +* magit-pull-from-upstream: Pulling. (line 23) +* magit-push: Pushing. (line 9) +* magit-push-current: Pushing. (line 31) +* magit-push-current-to-pushremote: Pushing. (line 15) +* magit-push-current-to-upstream: Pushing. (line 23) +* magit-push-implicitly args: Pushing. (line 74) +* magit-push-matching: Pushing. (line 50) +* magit-push-other: Pushing. (line 36) +* magit-push-refspecs: Pushing. (line 41) +* magit-push-tag: Pushing. (line 66) +* magit-push-tags: Pushing. (line 58) +* magit-push-to-remote remote args: Pushing. (line 85) +* magit-rebase: Rebasing. (line 9) +* magit-rebase-abort: Rebasing. (line 124) +* magit-rebase-autosquash: Rebasing. (line 85) +* magit-rebase-branch: Rebasing. (line 45) +* magit-rebase-continue: Rebasing. (line 107) +* magit-rebase-edit: Rebasing. (line 119) +* magit-rebase-edit-commit: Rebasing. (line 90) +* magit-rebase-interactive: Rebasing. (line 81) +* magit-rebase-onto-pushremote: Rebasing. (line 28) +* magit-rebase-onto-upstream: Rebasing. (line 37) +* magit-rebase-remove-commit: Rebasing. (line 100) +* magit-rebase-reword-commit: Rebasing. (line 95) +* magit-rebase-skip: Rebasing. (line 114) +* magit-rebase-subset: Rebasing. (line 51) +* magit-reflog-current: Reflog. (line 11) +* magit-reflog-head: Reflog. (line 19) +* magit-reflog-other: Reflog. (line 15) +* magit-refresh: Automatic Refreshing of Magit Buffers. + (line 24) +* magit-refresh-all: Automatic Refreshing of Magit Buffers. + (line 33) +* magit-remote: Remote Commands. (line 13) +* magit-remote-add: Remote Commands. (line 50) +* magit-remote-configure: Remote Commands. (line 33) +* magit-remote-prune: Remote Commands. (line 69) +* magit-remote-prune-refspecs: Remote Commands. (line 74) +* magit-remote-remove: Remote Commands. (line 65) +* magit-remote-rename: Remote Commands. (line 55) +* magit-remote-set-url: Remote Commands. (line 60) +* magit-reset-hard: Resetting. (line 26) +* magit-reset-index: Staging and Unstaging. + (line 87) +* magit-reset-index <1>: Resetting. (line 31) +* magit-reset-mixed: Resetting. (line 15) +* magit-reset-quickly: Resetting. (line 8) +* magit-reset-soft: Resetting. (line 20) +* magit-reset-worktree: Resetting. (line 38) +* magit-reset-worktree <1>: Wip Modes. (line 66) +* magit-reverse: Applying. (line 44) +* magit-reverse-in-index: Staging and Unstaging. + (line 62) +* magit-revert: Reverting. (line 6) +* magit-revert-and-commit: Reverting. (line 15) +* magit-revert-no-commit: Reverting. (line 21) +* magit-run: Running Git Manually. + (line 12) +* magit-run-git-gui: Running Git Manually. + (line 66) +* magit-run-gitk: Running Git Manually. + (line 54) +* magit-run-gitk-all: Running Git Manually. + (line 58) +* magit-run-gitk-branches: Running Git Manually. + (line 62) +* magit-section-backward: Section Movement. (line 10) +* magit-section-backward-siblings: Section Movement. (line 20) +* magit-section-cycle: Section Visibility. (line 13) +* magit-section-cycle-diffs: Section Visibility. (line 17) +* magit-section-cycle-global: Section Visibility. (line 22) +* magit-section-forward: Section Movement. (line 16) +* magit-section-forward-siblings: Section Movement. (line 26) +* magit-section-hide: Section Visibility. (line 49) +* magit-section-hide-children: Section Visibility. (line 64) +* magit-section-show: Section Visibility. (line 45) +* magit-section-show-children: Section Visibility. (line 58) +* magit-section-show-headings: Section Visibility. (line 53) +* magit-section-show-level-1: Section Visibility. (line 26) +* magit-section-show-level-1-all: Section Visibility. (line 33) +* magit-section-show-level-2: Section Visibility. (line 27) +* magit-section-show-level-2-all: Section Visibility. (line 34) +* magit-section-show-level-3: Section Visibility. (line 28) +* magit-section-show-level-3-all: Section Visibility. (line 35) +* magit-section-show-level-4: Section Visibility. (line 29) +* magit-section-show-level-4-all: Section Visibility. (line 36) +* magit-section-toggle: Section Visibility. (line 9) +* magit-section-toggle-children: Section Visibility. (line 68) +* magit-section-up: Section Movement. (line 31) +* magit-sequence-abort: Cherry Picking. (line 98) +* magit-sequence-abort <1>: Reverting. (line 39) +* magit-sequence-continue: Cherry Picking. (line 90) +* magit-sequence-continue <1>: Reverting. (line 31) +* magit-sequence-skip: Cherry Picking. (line 94) +* magit-sequence-skip <1>: Reverting. (line 35) +* magit-shell-command: Running Git Manually. + (line 40) +* magit-shell-command-topdir: Running Git Manually. + (line 35) +* magit-show-commit: Diffing. (line 69) +* magit-show-commit <1>: Blaming. (line 78) +* magit-show-refs: References Buffer. (line 6) +* magit-show-refs-current: References Buffer. (line 26) +* magit-show-refs-head: References Buffer. (line 21) +* magit-show-refs-other: References Buffer. (line 32) +* magit-snapshot-both: Stashing. (line 40) +* magit-snapshot-index: Stashing. (line 47) +* magit-snapshot-worktree: Stashing. (line 52) +* magit-stage: Staging and Unstaging. + (line 28) +* magit-stage-file: Staging from File-Visiting Buffers. + (line 10) +* magit-stage-file <1>: Minor Mode for Buffers Visiting Files. + (line 59) +* magit-stage-modified: Staging and Unstaging. + (line 36) +* magit-stash: Stashing. (line 8) +* magit-stash-apply: Stashing. (line 59) +* magit-stash-both: Stashing. (line 14) +* magit-stash-branch: Stashing. (line 81) +* magit-stash-branch-here: Stashing. (line 86) +* magit-stash-clear: Stashing. (line 96) +* magit-stash-drop: Stashing. (line 72) +* magit-stash-format-patch: Stashing. (line 92) +* magit-stash-index: Stashing. (line 21) +* magit-stash-keep-index: Stashing. (line 33) +* magit-stash-list: Stashing. (line 100) +* magit-stash-pop: Stashing. (line 65) +* magit-stash-show: Diffing. (line 74) +* magit-stash-show <1>: Stashing. (line 77) +* magit-stash-worktree: Stashing. (line 26) +* magit-status: Status Buffer. (line 22) +* magit-submodule: Submodule Transient. (line 6) +* magit-submodule-add: Submodule Transient. (line 20) +* magit-submodule-fetch: Fetching. (line 50) +* magit-submodule-populate: Submodule Transient. (line 34) +* magit-submodule-register: Submodule Transient. (line 27) +* magit-submodule-synchronize: Submodule Transient. (line 44) +* magit-submodule-unpopulate: Submodule Transient. (line 50) +* magit-submodule-update: Submodule Transient. (line 39) +* magit-subtree: Subtree. (line 8) +* magit-subtree-add: Subtree. (line 25) +* magit-subtree-add-commit: Subtree. (line 30) +* magit-subtree-export: Subtree. (line 42) +* magit-subtree-import: Subtree. (line 13) +* magit-subtree-merge: Subtree. (line 34) +* magit-subtree-pull: Subtree. (line 38) +* magit-subtree-push: Subtree. (line 54) +* magit-subtree-split: Subtree. (line 59) +* magit-tag: Tagging. (line 8) +* magit-tag-create: Tagging. (line 14) +* magit-tag-delete: Tagging. (line 40) +* magit-tag-prune: Tagging. (line 47) +* magit-tag-release: Tagging. (line 19) +* magit-toggle-buffer-lock: Modes and Buffers. (line 17) +* magit-toggle-margin: Refreshing Logs. (line 37) +* magit-toggle-margin <1>: Log Margin. (line 66) +* magit-toggle-margin-details: Log Margin. (line 74) +* magit-unstage: Staging and Unstaging. + (line 43) +* magit-unstage-all: Staging and Unstaging. + (line 52) +* magit-unstage-file: Staging from File-Visiting Buffers. + (line 18) +* magit-unstage-file <1>: Minor Mode for Buffers Visiting Files. + (line 63) +* magit-version: Git Executable. (line 17) +* magit-version <1>: Debugging Tools. (line 10) +* magit-visit-ref: References Buffer. (line 181) +* magit-wip-commit: Wip Modes. (line 88) +* magit-wip-log: Wip Modes. (line 48) +* magit-wip-log-current: Wip Modes. (line 57) +* magit-worktree: Worktree. (line 8) +* magit-worktree-branch: Worktree. (line 17) +* magit-worktree-checkout: Worktree. (line 13) +* magit-worktree-delete: Worktree. (line 25) +* magit-worktree-move: Worktree. (line 21) +* magit-worktree-status: Worktree. (line 30) +* scroll-down: Commands Available in Diffs. + (line 60) +* scroll-up: Commands Available in Diffs. + (line 56) +* with-editor-cancel: Editing Commit Messages. + (line 24) +* with-editor-cancel <1>: Editing Rebase Sequences. + (line 11) +* with-editor-debug: Debugging Tools. (line 38) +* with-editor-finish: Editing Commit Messages. + (line 19) +* with-editor-finish <1>: Editing Rebase Sequences. + (line 6) + + +File: magit.info, Node: Function Index, Next: Variable Index, Prev: Command Index, Up: Top + +Appendix E Function Index +************************* + +[index] +* Menu: + +* git-commit-check-style-conventions: Editing Commit Messages. + (line 247) +* git-commit-propertize-diff: Editing Commit Messages. + (line 206) +* git-commit-save-message: Editing Commit Messages. + (line 187) +* git-commit-setup-changelog-support: Editing Commit Messages. + (line 191) +* git-commit-turn-on-auto-fill: Editing Commit Messages. + (line 196) +* git-commit-turn-on-flyspell: Editing Commit Messages. + (line 201) +* ido-enter-magit-status: Status Buffer. (line 72) +* magit-add-section-hook: Section Hooks. (line 20) +* magit-after-save-refresh-status: Automatic Refreshing of Magit Buffers. + (line 58) +* magit-branch-or-checkout: Branch Commands. (line 257) +* magit-branch-orphan: Branch Commands. (line 252) +* magit-branch-shelve: Auxiliary Branch Commands. + (line 9) +* magit-branch-unshelve: Auxiliary Branch Commands. + (line 20) +* magit-builtin-completing-read: Support for Completion Frameworks. + (line 42) +* magit-call-git: Calling Git for Effect. + (line 28) +* magit-call-process: Calling Git for Effect. + (line 32) +* magit-cancel-section: Creating Sections. (line 71) +* magit-completing-read: Support for Completion Frameworks. + (line 60) +* magit-current-section: Section Selection. (line 6) +* magit-define-section-jumper: Creating Sections. (line 77) +* magit-diff-scope: Matching Sections. (line 118) +* magit-diff-type: Matching Sections. (line 95) +* magit-diff-visit-file-other-frame: Visiting Files and Blobs from a Diff. + (line 74) +* magit-diff-visit-file-other-window: Visiting Files and Blobs from a Diff. + (line 73) +* magit-diff-visit-worktree-file-other-frame: Visiting Files and Blobs from a Diff. + (line 76) +* magit-diff-visit-worktree-file-other-window: Visiting Files and Blobs from a Diff. + (line 75) +* magit-display-buffer: Switching Buffers. (line 6) +* magit-display-buffer-fullcolumn-most-v1: Switching Buffers. (line 76) +* magit-display-buffer-fullframe-status-topleft-v1: Switching Buffers. + (line 66) +* magit-display-buffer-fullframe-status-v1: Switching Buffers. + (line 60) +* magit-display-buffer-same-window-except-diff-v1: Switching Buffers. + (line 54) +* magit-display-buffer-traditional: Switching Buffers. (line 46) +* magit-file-checkout: Minor Mode for Buffers Visiting Files. + (line 165) +* magit-file-delete: Minor Mode for Buffers Visiting Files. + (line 157) +* magit-file-rename: Minor Mode for Buffers Visiting Files. + (line 153) +* magit-file-untrack: Minor Mode for Buffers Visiting Files. + (line 161) +* magit-find-file: General-Purpose Visit Commands. + (line 9) +* magit-find-file-other-frame: General-Purpose Visit Commands. + (line 21) +* magit-find-file-other-window: General-Purpose Visit Commands. + (line 15) +* magit-generate-buffer-name-default-function: Naming Buffers. + (line 17) +* magit-get-section: Matching Sections. (line 16) +* magit-git: Calling Git for Effect. + (line 65) +* magit-git-exit-code: Getting a Value from Git. + (line 10) +* magit-git-failure: Getting a Value from Git. + (line 19) +* magit-git-false: Getting a Value from Git. + (line 29) +* magit-git-insert: Getting a Value from Git. + (line 34) +* magit-git-items: Getting a Value from Git. + (line 49) +* magit-git-lines: Getting a Value from Git. + (line 44) +* magit-git-str: Getting a Value from Git. + (line 72) +* magit-git-string: Getting a Value from Git. + (line 38) +* magit-git-success: Getting a Value from Git. + (line 14) +* magit-git-true: Getting a Value from Git. + (line 24) +* magit-git-wash: Calling Git for Effect. + (line 70) +* magit-hunk-set-window-start: Section Movement. (line 43) +* magit-ido-completing-read: Support for Completion Frameworks. + (line 48) +* magit-insert-am-sequence: Status Sections. (line 28) +* magit-insert-assumed-unchanged-files: Status Sections. (line 117) +* magit-insert-bisect-log: Status Sections. (line 46) +* magit-insert-bisect-output: Status Sections. (line 38) +* magit-insert-bisect-rest: Status Sections. (line 42) +* magit-insert-diff-filter-header: Status Header Sections. + (line 38) +* magit-insert-error-header: Status Header Sections. + (line 28) +* magit-insert-head-branch-header: Status Header Sections. + (line 42) +* magit-insert-heading: Creating Sections. (line 42) +* magit-insert-ignored-files: Status Sections. (line 100) +* magit-insert-local-branches: References Sections. (line 17) +* magit-insert-merge-log: Status Sections. (line 18) +* magit-insert-modules: Status Module Sections. + (line 12) +* magit-insert-modules-overview: Status Module Sections. + (line 33) +* magit-insert-modules-unpulled-from-pushremote: Status Module Sections. + (line 50) +* magit-insert-modules-unpulled-from-upstream: Status Module Sections. + (line 44) +* magit-insert-modules-unpushed-to-pushremote: Status Module Sections. + (line 62) +* magit-insert-modules-unpushed-to-upstream: Status Module Sections. + (line 56) +* magit-insert-push-branch-header: Status Header Sections. + (line 51) +* magit-insert-rebase-sequence: Status Sections. (line 23) +* magit-insert-recent-commits: Status Sections. (line 131) +* magit-insert-remote-branches: References Sections. (line 21) +* magit-insert-remote-header: Status Header Sections. + (line 67) +* magit-insert-repo-header: Status Header Sections. + (line 63) +* magit-insert-section: Creating Sections. (line 6) +* magit-insert-sequencer-sequence: Status Sections. (line 33) +* magit-insert-skip-worktree-files: Status Sections. (line 110) +* magit-insert-staged-changes: Status Sections. (line 63) +* magit-insert-stashes: Status Sections. (line 67) +* magit-insert-status-headers: Status Header Sections. + (line 12) +* magit-insert-submodules: Listing Submodules. (line 35) +* magit-insert-tags: References Sections. (line 25) +* magit-insert-tags-header: Status Header Sections. + (line 56) +* magit-insert-tracked-files: Status Sections. (line 96) +* magit-insert-unpulled-cherries: Status Sections. (line 142) +* magit-insert-unpulled-from-pushremote: Status Sections. (line 79) +* magit-insert-unpulled-from-upstream: Status Sections. (line 74) +* magit-insert-unpulled-or-recent-commits: Status Sections. (line 124) +* magit-insert-unpushed-cherries: Status Sections. (line 149) +* magit-insert-unpushed-to-pushremote: Status Sections. (line 89) +* magit-insert-unpushed-to-upstream: Status Sections. (line 84) +* magit-insert-unstaged-changes: Status Sections. (line 59) +* magit-insert-untracked-files: Status Sections. (line 50) +* magit-insert-upstream-branch-header: Status Header Sections. + (line 46) +* magit-insert-user-header: Status Header Sections. + (line 75) +* magit-list-repositories: Repository List. (line 6) +* magit-list-submodules: Listing Submodules. (line 13) +* magit-log-maybe-show-more-commits: Section Movement. (line 57) +* magit-log-maybe-update-blob-buffer: Section Movement. (line 71) +* magit-log-maybe-update-revision-buffer: Section Movement. (line 64) +* magit-maybe-set-dedicated: Switching Buffers. (line 101) +* magit-mode-display-buffer: Refreshing Buffers. (line 33) +* magit-mode-quit-window: Quitting Windows. (line 34) +* magit-mode-setup: Refreshing Buffers. (line 17) +* magit-push-implicitly: Pushing. (line 74) +* magit-push-to-remote: Pushing. (line 85) +* magit-region-sections: Section Selection. (line 10) +* magit-region-values: Section Selection. (line 37) +* magit-repolist-column-branch: Repository List. (line 44) +* magit-repolist-column-branches: Repository List. (line 53) +* magit-repolist-column-flag: Repository List. (line 61) +* magit-repolist-column-ident: Repository List. (line 30) +* magit-repolist-column-path: Repository List. (line 35) +* magit-repolist-column-stashes: Repository List. (line 57) +* magit-repolist-column-unpulled-from-pushremote: Repository List. + (line 81) +* magit-repolist-column-unpulled-from-upstream: Repository List. + (line 76) +* magit-repolist-column-unpushed-to-pushremote: Repository List. + (line 91) +* magit-repolist-column-unpushed-to-upstream: Repository List. + (line 86) +* magit-repolist-column-upstream: Repository List. (line 48) +* magit-repolist-column-version: Repository List. (line 39) +* magit-restore-window-configuration: Quitting Windows. (line 23) +* magit-revert-buffers: Editing Commit Messages. + (line 178) +* magit-run-git: Calling Git for Effect. + (line 36) +* magit-run-git-async: Calling Git for Effect. + (line 80) +* magit-run-git-with-editor: Calling Git for Effect. + (line 93) +* magit-run-git-with-input: Calling Git for Effect. + (line 40) +* magit-run-git-with-logfile: Calling Git for Effect. + (line 56) +* magit-save-window-configuration: Switching Buffers. (line 90) +* magit-section-case: Matching Sections. (line 71) +* magit-section-hide: Section Visibility. (line 49) +* magit-section-hide-children: Section Visibility. (line 64) +* magit-section-ident: Matching Sections. (line 11) +* magit-section-match: Matching Sections. (line 21) +* magit-section-set-window-start: Section Movement. (line 50) +* magit-section-show: Section Visibility. (line 45) +* magit-section-show-children: Section Visibility. (line 58) +* magit-section-show-headings: Section Visibility. (line 53) +* magit-section-toggle-children: Section Visibility. (line 68) +* magit-section-value-if: Matching Sections. (line 61) +* magit-start-git: Calling Git for Effect. + (line 105) +* magit-start-process: Calling Git for Effect. + (line 124) +* magit-stashes-maybe-update-stash-buffer: Section Movement. (line 95) +* magit-status-maybe-update-blob-buffer: Section Movement. (line 89) +* magit-status-maybe-update-revision-buffer: Section Movement. + (line 77) +* magit-status-maybe-update-stash-buffer: Section Movement. (line 83) +* magit-wip-log: Wip Modes. (line 48) +* magit-wip-log-current: Wip Modes. (line 57) +* with-editor-usage-message: Editing Commit Messages. + (line 215) + + +File: magit.info, Node: Variable Index, Prev: Function Index, Up: Top + +Appendix F Variable Index +************************* + +[index] +* Menu: + +* auto-revert-buffer-list-filter: Automatic Reverting of File-Visiting Buffers. + (line 81) +* auto-revert-interval: Automatic Reverting of File-Visiting Buffers. + (line 76) +* auto-revert-mode: Automatic Reverting of File-Visiting Buffers. + (line 62) +* auto-revert-stop-on-user-input: Automatic Reverting of File-Visiting Buffers. + (line 71) +* auto-revert-use-notify: Automatic Reverting of File-Visiting Buffers. + (line 49) +* auto-revert-verbose: Automatic Reverting of File-Visiting Buffers. + (line 103) +* branch.autoSetupMerge: Branch Git Variables. + (line 81) +* branch.autoSetupRebase: Branch Git Variables. + (line 98) +* branch.NAME.description: Branch Git Variables. + (line 48) +* branch.NAME.merge: Branch Git Variables. + (line 10) +* branch.NAME.pushRemote: Branch Git Variables. + (line 34) +* branch.NAME.rebase: Branch Git Variables. + (line 22) +* branch.NAME.remote: Branch Git Variables. + (line 16) +* core.notesRef: Notes. (line 60) +* git-commit-fill-column: Editing Commit Messages. + (line 228) +* git-commit-finish-query-functions: Editing Commit Messages. + (line 233) +* git-commit-known-pseudo-headers: Editing Commit Messages. + (line 124) +* git-commit-major-mode: Editing Commit Messages. + (line 163) +* git-commit-setup-hook: Editing Commit Messages. + (line 174) +* git-commit-summary-max-length: Editing Commit Messages. + (line 222) +* git-rebase-auto-advance: Editing Rebase Sequences. + (line 99) +* git-rebase-confirm-cancel: Editing Rebase Sequences. + (line 107) +* git-rebase-show-instructions: Editing Rebase Sequences. + (line 103) +* global-auto-revert-mode: Automatic Reverting of File-Visiting Buffers. + (line 22) +* global-magit-file-mode: Minor Mode for Buffers Visiting Files. + (line 13) +* magit-auto-revert-immediately: Automatic Reverting of File-Visiting Buffers. + (line 32) +* magit-auto-revert-mode: Automatic Reverting of File-Visiting Buffers. + (line 17) +* magit-auto-revert-tracked-only: Automatic Reverting of File-Visiting Buffers. + (line 55) +* magit-bisect-show-graph: Bisecting. (line 55) +* magit-blame-disable-modes: Blaming. (line 168) +* magit-blame-echo-style: Blaming. (line 151) +* magit-blame-goto-chunk-hook: Blaming. (line 174) +* magit-blame-read-only: Blaming. (line 163) +* magit-blame-styles: Blaming. (line 146) +* magit-blame-time-format: Blaming. (line 158) +* magit-branch-adjust-remote-upstream-alist: Branch Commands. (line 210) +* magit-branch-direct-configure: Branch Commands. (line 20) +* magit-branch-prefer-remote-upstream: Branch Commands. (line 165) +* magit-branch-read-upstream-first: Branch Commands. (line 159) +* magit-buffer-name-format: Naming Buffers. (line 27) +* magit-bury-buffer-function: Quitting Windows. (line 14) +* magit-cherry-margin: Cherries. (line 22) +* magit-clone-always-transient: Cloning Repository. (line 12) +* magit-clone-default-directory: Cloning Repository. (line 90) +* magit-clone-name-alist: Cloning Repository. (line 103) +* magit-clone-set-remote-head: Cloning Repository. (line 68) +* magit-clone-set-remote.pushDefault: Cloning Repository. (line 78) +* magit-clone-url-format: Cloning Repository. (line 124) +* magit-commit-ask-to-stage: Initiating a Commit. (line 75) +* magit-commit-extend-override-date: Initiating a Commit. (line 80) +* magit-commit-reword-override-date: Initiating a Commit. (line 84) +* magit-commit-squash-confirm: Initiating a Commit. (line 88) +* magit-completing-read-function: Support for Completion Frameworks. + (line 27) +* magit-diff-adjust-tab-width: Diff Options. (line 21) +* magit-diff-buffer-file-locked: Minor Mode for Buffers Visiting Files. + (line 91) +* magit-diff-hide-trailing-cr-characters: Diff Options. (line 90) +* magit-diff-highlight-hunk-region-functions: Diff Options. (line 94) +* magit-diff-highlight-indentation: Diff Options. (line 75) +* magit-diff-highlight-trailing: Diff Options. (line 70) +* magit-diff-paint-whitespace: Diff Options. (line 43) +* magit-diff-paint-whitespace-lines: Diff Options. (line 60) +* magit-diff-refine-hunk: Diff Options. (line 6) +* magit-diff-refine-ignore-whitespace: Diff Options. (line 16) +* magit-diff-unmarked-lines-keep-foreground: Diff Options. (line 120) +* magit-diff-visit-previous-blob: Visiting Files and Blobs from a Diff. + (line 39) +* magit-direct-use-buffer-arguments: Transient Arguments and Buffer Variables. + (line 73) +* magit-display-buffer-function: Switching Buffers. (line 27) +* magit-display-buffer-noselect: Switching Buffers. (line 18) +* magit-dwim-selection: Completion and Confirmation. + (line 42) +* magit-ediff-dwim-show-on-hunks: Ediffing. (line 73) +* magit-ediff-quit-hook: Ediffing. (line 88) +* magit-ediff-show-stash-with-index: Ediffing. (line 81) +* magit-file-mode-map: Minor Mode for Buffers Visiting Files. + (line 20) +* magit-generate-buffer-name-function: Naming Buffers. (line 6) +* magit-git-debug: Viewing Git Output. (line 28) +* magit-git-debug <1>: Getting a Value from Git. + (line 64) +* magit-git-executable: Git Executable. (line 39) +* magit-git-global-arguments: Global Git Arguments. + (line 6) +* magit-keep-region-overlay: The Selection. (line 52) +* magit-list-refs-sortby: Additional Completion Options. + (line 6) +* magit-log-auto-more: Log Buffer. (line 69) +* magit-log-buffer-file-locked: Minor Mode for Buffers Visiting Files. + (line 118) +* magit-log-margin: Log Margin. (line 12) +* magit-log-margin-show-committer-date: Log Margin. (line 49) +* magit-log-section-args: Status Options. (line 38) +* magit-log-section-commit-count: Status Sections. (line 136) +* magit-log-select-margin: Select from Log. (line 30) +* magit-log-show-refname-after-summary: Log Buffer. (line 75) +* magit-log-trace-definition-function: Commands Available in Diffs. + (line 18) +* magit-module-sections-hook: Status Module Sections. + (line 20) +* magit-module-sections-nested: Status Module Sections. + (line 24) +* magit-no-confirm: Action Confirmation. (line 18) +* magit-pop-revision-stack-format: Editing Commit Messages. + (line 92) +* magit-post-display-buffer-hook: Switching Buffers. (line 96) +* magit-pre-display-buffer-hook: Switching Buffers. (line 85) +* magit-prefer-remote-upstream: Branch Git Variables. + (line 126) +* magit-prefix-use-buffer-arguments: Transient Arguments and Buffer Variables. + (line 64) +* magit-process-raise-error: Calling Git for Effect. + (line 151) +* magit-pull-or-fetch: Fetching. (line 55) +* magit-reflog-margin: Reflog. (line 23) +* magit-refresh-args: Refreshing Buffers. (line 55) +* magit-refresh-buffer-hook: Automatic Refreshing of Magit Buffers. + (line 42) +* magit-refresh-function: Refreshing Buffers. (line 49) +* magit-refresh-status-buffer: Automatic Refreshing of Magit Buffers. + (line 48) +* magit-refs-filter-alist: References Buffer. (line 159) +* magit-refs-focus-column-width: References Buffer. (line 82) +* magit-refs-margin: References Buffer. (line 97) +* magit-refs-margin-for-tags: References Buffer. (line 125) +* magit-refs-pad-commit-counts: References Buffer. (line 49) +* magit-refs-primary-column-width: References Buffer. (line 69) +* magit-refs-sections-hook: References Sections. (line 13) +* magit-refs-show-commit-count: References Buffer. (line 37) +* magit-refs-show-remote-prefix: References Buffer. (line 62) +* magit-remote-add-set-remote.pushDefault: Remote Commands. (line 92) +* magit-remote-direct-configure: Remote Commands. (line 21) +* magit-remote-set-if-missing: Remote Git Variables. + (line 39) +* magit-repolist-columns: Repository List. (line 14) +* magit-repository-directories: Status Buffer. (line 58) +* magit-revision-filter-files-on-follow: Revision Buffer. (line 64) +* magit-revision-insert-related-refs: Revision Buffer. (line 6) +* magit-revision-show-gravatars: Revision Buffer. (line 19) +* magit-revision-use-hash-sections: Revision Buffer. (line 36) +* magit-root-section: Matching Sections. (line 87) +* magit-save-repository-buffers: Automatic Saving of File-Visiting Buffers. + (line 13) +* magit-section-cache-visibility: Section Visibility. (line 95) +* magit-section-initial-visibility-alist: Section Visibility. (line 78) +* magit-section-movement-hook: Section Movement. (line 38) +* magit-section-set-visibility-hook: Section Visibility. (line 106) +* magit-section-show-child-count: Section Options. (line 9) +* magit-section-visibility-indicator: Section Visibility. (line 124) +* magit-shell-command-verbose-prompt: Running Git Manually. + (line 47) +* magit-stashes-margin: Stashing. (line 104) +* magit-status-headers-hook: Status Header Sections. + (line 18) +* magit-status-margin: Status Options. (line 10) +* magit-status-refresh-hook: Status Options. (line 6) +* magit-status-sections-hook: Status Sections. (line 10) +* magit-submodule-list-columns: Listing Submodules. (line 21) +* magit-this-process: Calling Git for Effect. + (line 146) +* magit-uniquify-buffer-names: Naming Buffers. (line 74) +* magit-unstage-committed: Staging and Unstaging. + (line 56) +* magit-update-other-window-delay: Section Movement. (line 101) +* magit-visit-ref-behavior: References Buffer. (line 192) +* magit-wip-after-apply-mode: Legacy Wip Modes. (line 19) +* magit-wip-after-apply-mode-lighter: Legacy Wip Modes. (line 59) +* magit-wip-after-save-local-mode-lighter: Legacy Wip Modes. (line 55) +* magit-wip-after-save-mode: Legacy Wip Modes. (line 13) +* magit-wip-before-change-mode: Legacy Wip Modes. (line 33) +* magit-wip-before-change-mode-lighter: Legacy Wip Modes. (line 63) +* magit-wip-initial-backup-mode: Legacy Wip Modes. (line 38) +* magit-wip-initial-backup-mode-lighter: Legacy Wip Modes. (line 67) +* magit-wip-merge-branch: Wip Graph. (line 6) +* magit-wip-mode: Wip Modes. (line 30) +* magit-wip-mode-lighter: Wip Modes. (line 104) +* magit-wip-namespace: Wip Modes. (line 96) +* notes.displayRef: Notes. (line 65) +* pull.rebase: Branch Git Variables. + (line 57) +* remote.NAME.fetch: Remote Git Variables. + (line 15) +* remote.NAME.push: Remote Git Variables. + (line 26) +* remote.NAME.pushurl: Remote Git Variables. + (line 20) +* remote.NAME.tagOpts: Remote Git Variables. + (line 31) +* remote.NAME.url: Remote Git Variables. + (line 10) +* remote.pushDefault: Branch Git Variables. + (line 71) + diff --git a/elpa/org-clock-csv-20190418.1505/org-clock-csv-autoloads.el b/elpa/org-clock-csv-20190418.1505/org-clock-csv-autoloads.el new file mode 100644 index 00000000..618e21bb --- /dev/null +++ b/elpa/org-clock-csv-20190418.1505/org-clock-csv-autoloads.el @@ -0,0 +1,55 @@ +;;; org-clock-csv-autoloads.el --- automatically extracted autoloads +;; +;;; Code: + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + + +;;;### (autoloads nil "org-clock-csv" "org-clock-csv.el" (0 0 0 0)) +;;; Generated autoloads from org-clock-csv.el + +(autoload 'org-clock-csv "org-clock-csv" "\ +Export clock entries from INFILE to CSV format. + +When INFILE is a filename or list of filenames, export clock +entries from these files. Otherwise, use `org-agenda-files'. + +When NO-SWITCH is non-nil, do not call `switch-to-buffer' on the +rendered CSV output, simply return the buffer. + +USE-CURRENT takes the value of the prefix argument. When non-nil, +use the current buffer for INFILE. + +See also `org-clock-csv-batch' for a function more appropriate +for use in batch mode. + +\(fn &optional INFILE NO-SWITCH USE-CURRENT)" t nil) + +(autoload 'org-clock-csv-to-file "org-clock-csv" "\ +Write clock entries from INFILE to OUTFILE in CSV format. + +See `org-clock-csv' for additional details. + +\(fn OUTFILE &optional INFILE USE-CURRENT)" t nil) + +(autoload 'org-clock-csv-batch-and-exit "org-clock-csv" "\ +Export clock entries in CSV format to standard output. + +This function is identical in function to `org-clock-csv' except +that it directs output to `standard-output'. It is intended for +use in batch mode. + +\(fn)" nil nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-clock-csv" '("org-clock-csv-"))) + +;;;*** + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; coding: utf-8 +;; End: +;;; org-clock-csv-autoloads.el ends here diff --git a/elpa/org-clock-csv-20190418.1505/org-clock-csv-pkg.el b/elpa/org-clock-csv-20190418.1505/org-clock-csv-pkg.el new file mode 100644 index 00000000..38e09a3a --- /dev/null +++ b/elpa/org-clock-csv-20190418.1505/org-clock-csv-pkg.el @@ -0,0 +1,2 @@ +;;; -*- no-byte-compile: t -*- +(define-package "org-clock-csv" "20190418.1505" "Export `org-mode' clock entries to CSV format." '((org "8.3") (s "1.0")) :commit "e2fbaa1ad1a1be40fceecde603a600b292b76acc" :keywords '("calendar" "data" "org") :authors '(("Aaron Jacobs" . "atheriel@gmail.com")) :maintainer '("Aaron Jacobs" . "atheriel@gmail.com") :url "https://github.com/atheriel/org-clock-csv") diff --git a/elpa/org-clock-csv-20190418.1505/org-clock-csv.el b/elpa/org-clock-csv-20190418.1505/org-clock-csv.el new file mode 100644 index 00000000..b0b0d0b1 --- /dev/null +++ b/elpa/org-clock-csv-20190418.1505/org-clock-csv.el @@ -0,0 +1,305 @@ +;;; org-clock-csv.el --- Export `org-mode' clock entries to CSV format. + +;; Copyright (C) 2016 Aaron Jacobs + +;; Author: Aaron Jacobs +;; URL: https://github.com/atheriel/org-clock-csv +;; Package-Version: 20190418.1505 +;; Keywords: calendar, data, org +;; Version: 1.2 +;; Package-Requires: ((org "8.3") (s "1.0")) + +;; This file is NOT part of GNU Emacs. + +;; This file is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + +;; This file is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: + +;; This package makes use of the `org-element' API to extract clock +;; entries from org files and convert them into CSV format. It is +;; intended to facilitate clocked time analysis in external programs. + +;; In interactive mode, calling `org-clock-csv' will open a buffer +;; with the parsed entries from the files in `org-agenda-files', while +;; `org-clock-csv-to-file' will write this output to a file. Both +;; functions take a prefix argument to read entries from the current +;; buffer instead. + +;; There is also an `org-clock-csv-batch-and-exit' that will output +;; the CSV content to standard output (for use in batch mode). + +;;; Code: + +(require 's) +(require 'org) +(require 'org-agenda) +(require 'org-element) + +(eval-when-compile + (require 'cl-lib)) + +;; This is a simplified shim for `org-element-lineage', as needed for this +;; package, for very old versions of `org': +(when (version< (org-version) "8.3") + (defun org-element-lineage (blob &optional types) + (let ((up (org-element-property :parent blob))) + (while (and up (not (memq (org-element-type up) types))) + (setq up (org-element-property :parent up))) + up))) + +;;;; Configuration options: + +(defgroup org-clock-csv nil + "Export `org-mode' clock entries to CSV format." + :group 'external) + +(defcustom org-clock-csv-header "task,parents,category,start,end,effort,ishabit,tags" + "Header for the CSV output. + +Be sure to keep this in sync with changes to +`org-clock-csv-row-fmt'." + :group 'org-clock-csv) + +(defcustom org-clock-csv-headline-separator "/" + "Character that separates each headline level within the \"task\" column." + :group 'org-clock-csv) + +(defcustom org-clock-csv-row-fmt #'org-clock-csv-default-row-fmt + "Function to parse a plist of properties for each clock entry +and produce a comma-separated CSV row. + +Be sure to keep this in sync with changes to +`org-clock-csv-header'. + +See `org-clock-csv-default-row-fmt' for an example." + :group 'org-clock-csv) + +(defun org-clock-csv-default-row-fmt (plist) + "Default row formatting function." + (mapconcat #'identity + (list (org-clock-csv--escape (plist-get plist ':task)) + (org-clock-csv--escape (s-join org-clock-csv-headline-separator (plist-get plist ':parents))) + (org-clock-csv--escape (plist-get plist ':category)) + (plist-get plist ':start) + (plist-get plist ':end) + (plist-get plist ':effort) + (plist-get plist ':ishabit) + (plist-get plist ':tags)) + ",")) + +;;;; Utility functions: + +(defsubst org-clock-csv--pad (num) + "Add a leading zero when NUM is less than 10." + (if (> num 10) num (format "%02d" num))) + +(defun org-clock-csv--escape (str) + "Escapes STR so that it is suitable for a .csv file. + +Since we don't expect newlines in any of these strings, it is +sufficient to escape commas and double quote characters." + (if (s-contains? "\"" str) + (concat "\"" (s-replace-all '(("\"" . "\"\"")) str) "\"") + (if (s-contains? "," str) (concat "\"" str "\"") str))) + +;;;; Internal API: + +(defun org-clock-csv--find-category (element) + "Find the category of a headline ELEMENT, optionally recursing +upwards until one is found. + +Returns an empty string if no category is found." + (let ((category (org-element-property :CATEGORY element)) + (current element) + (curlvl (org-element-property :level element))) + ;; If the headline does not have a category, recurse upwards + ;; through the parent headlines, checking if there is a category + ;; property in any of them. + (while (not category) + (setq current (if (equal curlvl 1) + (org-element-lineage current) + (org-element-lineage current '(headline))) + curlvl (- curlvl 1)) + (setq category (org-element-property :CATEGORY current)) + ;; If we get to the root of the org file with no category, just + ;; set it to the empty string. + ;; + ;; TODO: File-level categories are stored not as properties, but + ;; as keyword elements in the `org-data' structure. In order to + ;; extract them, it will probaby require a call to + ;; `org-element-map'. Since this could be an expensive operation + ;; on an org file with no headline-level categories, but a + ;; single file-level category, it would need to be cached. + (unless (equal 'headline (org-element-type current)) + (setq category ""))) + category)) + +(defun org-clock-csv--find-headlines (element) + "Returns a list of headline ancestors from closest parent to the farthest" + (let ((ph (org-element-lineage element '(headline)))) + (if ph + (cons ph (org-clock-csv--find-headlines ph))))) + +(defun org-clock-csv--parse-element (element) + "Ingest clock ELEMENT and produces a plist of its relevant +properties." + (when (and (equal (org-element-type element) 'clock) + ;; Only ingest closed, inactive clock elements. + (equal (org-element-property :status element) 'closed) + (equal (org-element-property + :type (org-element-property :value element)) + 'inactive-range)) + (let* ((timestamp (org-element-property :value element)) + (headlines (org-clock-csv--find-headlines element)) ;; Finds the headlines ancestor lineage containing the clock element. + (headlines-values (mapcar (lambda (h) (org-element-property :raw-value h)) headlines )) + (task-headline (car headlines)) ;; The first headline containing this clock element. + (task (car headlines-values)) + (parents (reverse (cdr headlines-values))) + (effort (org-element-property :EFFORT task-headline)) + ;; TODO: Handle tag inheritance, respecting the value of + ;; `org-tags-exclude-from-inheritance'. + (tags (mapconcat #'identity + (org-element-property :tags task-headline) ":")) + (ishabit (when (equal "habit" (org-element-property + :STYLE task-headline)) + "t")) + (category (org-clock-csv--find-category task-headline)) + (start (format "%d-%s-%s %s:%s" + (org-element-property :year-start timestamp) + (org-clock-csv--pad + (org-element-property :month-start timestamp)) + (org-clock-csv--pad + (org-element-property :day-start timestamp)) + (org-clock-csv--pad + (org-element-property :hour-start timestamp)) + (org-clock-csv--pad + (org-element-property :minute-start timestamp)))) + (end (format "%d-%s-%s %s:%s" + (org-element-property :year-end timestamp) + (org-clock-csv--pad + (org-element-property :month-end timestamp)) + (org-clock-csv--pad + (org-element-property :day-end timestamp)) + (org-clock-csv--pad + (org-element-property :hour-end timestamp)) + (org-clock-csv--pad + (org-element-property :minute-end timestamp)))) + (duration (org-element-property :duration element))) + (list :task task + :headline task-headline + :parents parents + :category category + :start start + :end end + :duration duration + :effort effort + :ishabit ishabit + :tags tags)))) + +(defun org-clock-csv--get-entries (filelist &optional no-check) + "Retrieves clock entries from files in FILELIST. + +When NO-CHECK is non-nil, skip checking if all files exist." + (when (not no-check) + ;; For the sake of better debug messages, check whether all of the + ;; files exists first. + (mapc (lambda (file) (cl-assert (file-exists-p file))) filelist)) + (cl-loop for file in filelist append + (with-current-buffer (find-file-noselect file) + (org-element-map (org-element-parse-buffer) 'clock + #'org-clock-csv--parse-element nil nil)))) + +;;;; Public API: + +;;;###autoload +(defun org-clock-csv (&optional infile no-switch use-current) + "Export clock entries from INFILE to CSV format. + +When INFILE is a filename or list of filenames, export clock +entries from these files. Otherwise, use `org-agenda-files'. + +When NO-SWITCH is non-nil, do not call `switch-to-buffer' on the +rendered CSV output, simply return the buffer. + +USE-CURRENT takes the value of the prefix argument. When non-nil, +use the current buffer for INFILE. + +See also `org-clock-csv-batch' for a function more appropriate +for use in batch mode." + (interactive "i\ni\nP") + (when use-current + (unless (equal major-mode 'org-mode) + (user-error "Not in an org buffer"))) + (let* ((infile (if (and use-current buffer-file-name) + (list buffer-file-name) + infile)) + (filelist (if (null infile) (org-agenda-files) + (if (listp infile) infile (list infile)))) + (buffer (get-buffer-create "*clock-entries-csv*")) + (entries (org-clock-csv--get-entries filelist))) + (with-current-buffer buffer + (goto-char 0) + (erase-buffer) + (insert org-clock-csv-header "\n") + (mapc (lambda (entry) + (insert (concat (funcall org-clock-csv-row-fmt entry) "\n"))) + entries)) + (if no-switch buffer + (switch-to-buffer buffer)))) + +;;;###autoload +(defun org-clock-csv-to-file (outfile &optional infile use-current) + "Write clock entries from INFILE to OUTFILE in CSV format. + +See `org-clock-csv' for additional details." + (interactive "FFile: \ni\nP") + (let ((buffer (org-clock-csv infile 'no-switch use-current))) + (with-current-buffer buffer + (write-region nil nil outfile nil nil)) + (kill-buffer buffer))) + +;;;###autoload +(defun org-clock-csv-batch-and-exit () + "Export clock entries in CSV format to standard output. + +This function is identical in function to `org-clock-csv' except +that it directs output to `standard-output'. It is intended for +use in batch mode." + (or noninteractive + (error "`org-clock-csv-batch' is designed for use in batch mode.")) + (let* ((filelist (if (= (length command-line-args-left) 0) + (org-agenda-files) + command-line-args-left)) + entries) + (unwind-protect + (progn + (setq entries (org-clock-csv--get-entries filelist t)) + (princ (concat org-clock-csv-header "\n")) + (mapc (lambda (entry) + (princ (concat (funcall org-clock-csv-row-fmt entry) "\n"))) + entries) + (kill-emacs 0)) + (backtrace) + (message "Error converting clock entries to CSV format.") + (kill-emacs 2)))) + +(defalias 'org-clock-csv-batch 'org-clock-csv-batch-and-exit) + +(provide 'org-clock-csv) + +;; Local Variables: +;; coding: utf-8 +;; End: + +;;; org-clock-csv.el ends here diff --git a/elpa/org-clock-csv-20190418.1505/org-clock-csv.elc b/elpa/org-clock-csv-20190418.1505/org-clock-csv.elc new file mode 100644 index 0000000000000000000000000000000000000000..72da6e7d701076bf8e1e941a722eae3184a2a5b0 GIT binary patch literal 9306 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 literal 0 HcmV?d00001 diff --git a/elpa/org-clock-today-20190915.701/org-clock-today-autoloads.el b/elpa/org-clock-today-20190915.701/org-clock-today-autoloads.el new file mode 100644 index 00000000..f061f641 --- /dev/null +++ b/elpa/org-clock-today-20190915.701/org-clock-today-autoloads.el @@ -0,0 +1,38 @@ +;;; org-clock-today-autoloads.el --- automatically extracted autoloads +;; +;;; Code: + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + + +;;;### (autoloads nil "org-clock-today" "org-clock-today.el" (0 0 +;;;;;; 0 0)) +;;; Generated autoloads from org-clock-today.el + +(defvar org-clock-today-mode nil "\ +Non-nil if Org-Clock-Today mode is enabled. +See the `org-clock-today-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `org-clock-today-mode'.") + +(custom-autoload 'org-clock-today-mode "org-clock-today" nil) + +(autoload 'org-clock-today-mode "org-clock-today" "\ +Minor mode to show the total clocked time of the current day in the mode line. + +\(fn &optional ARG)" t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "org-clock-today" '("org-clock-today-"))) + +;;;*** + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; coding: utf-8 +;; End: +;;; org-clock-today-autoloads.el ends here diff --git a/elpa/org-clock-today-20190915.701/org-clock-today-pkg.el b/elpa/org-clock-today-20190915.701/org-clock-today-pkg.el new file mode 100644 index 00000000..753416eb --- /dev/null +++ b/elpa/org-clock-today-20190915.701/org-clock-today-pkg.el @@ -0,0 +1,2 @@ +;;; -*- no-byte-compile: t -*- +(define-package "org-clock-today" "20190915.701" "Show total clocked time of the current day in the mode line" '((emacs "25")) :commit "18af3fede1aa0ccab83ce9195f94f9097f51c548" :authors '(("Tijs Mallaerts" . "tijs.mallaerts@gmail.com")) :maintainer '("Tijs Mallaerts" . "tijs.mallaerts@gmail.com") :url "https://github.com/mallt/org-clock-today-mode") diff --git a/elpa/org-clock-today-20190915.701/org-clock-today.el b/elpa/org-clock-today-20190915.701/org-clock-today.el new file mode 100644 index 00000000..0ba63fc9 --- /dev/null +++ b/elpa/org-clock-today-20190915.701/org-clock-today.el @@ -0,0 +1,140 @@ +;;; org-clock-today.el --- Show total clocked time of the current day in the mode line -*- lexical-binding: t -*- + +;; Copyright © 2016-2019 Tijs Mallaerts +;; +;; Author: Tijs Mallaerts + +;; Package-Requires: ((emacs "25")) +;; Package-Version: 20190915.701 +;; Version: 0.0.2 +;; URL: https://github.com/mallt/org-clock-today-mode + +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;; This file is not part of GNU Emacs. + +;;; Commentary: + +;; Show the total clocked time of the current day in the mode line + +;;; Code: + +(require 'org-clock) + +(defgroup org-clock-today nil + "Org clock today customizations." + :group 'org-clock) + +(defcustom org-clock-today-hide-default-org-clock-mode-line nil + "Controls the visibility of the default org clock mode line string." + :type 'boolean + :group 'org-clock-today) + +(defcustom org-clock-today-count-subtree nil + "If non-nil, count total minutes of the current subtree as well." + :type 'boolean + :group 'org-clock-today) + +(defvar org-clock-today-string "" "The lighter.") +(defvar org-clock-today-subtree-time nil "Clock count extracted from subtree.") +(defvar org-clock-today-buffer-time nil "Clock count extracted from buffer.") +(defvar org-clock-today--timer nil) + +(defun org-clock-today--total-minutes () + "Return the total minutes." + (let* ((current-sum (org-clock-sum-today)) + (open-time-difference (time-subtract + (float-time) + (float-time org-clock-start-time))) + (open-seconds (time-to-seconds open-time-difference)) + (open-minutes (/ open-seconds 60)) + (total-minutes (+ current-sum + open-minutes))) + (org-duration-from-minutes total-minutes))) + +(defun org-clock-today--display-default () + "Default function to return string for displaying clocks." + (concat + " " + (when org-clock-today-count-subtree + (concat org-clock-today-subtree-time " ")) + org-clock-today-buffer-time)) + +(defcustom org-clock-today-display-format #'org-clock-today--display-default + "Function to call when building string for mode-line." + :type '(choice + (const :tag "Do nothing" ignore) + (function :tag "Custom function"))) + +(defun org-clock-today--update-mode-line () + "Calculate the total clocked time of today and update the mode line." + (setq org-clock-today-string + (if (org-clock-is-active) + (with-current-buffer (org-clock-is-active) + (when org-clock-today-count-subtree + (save-excursion + (save-restriction + (goto-char org-clock-marker) + (org-narrow-to-subtree) + (setq org-clock-today-subtree-time + (org-clock-today--total-minutes))))) + (setq org-clock-today-buffer-time + (org-clock-today--total-minutes)) + (funcall org-clock-today-display-format)) + "")) + (force-mode-line-update)) + +(defun org-clock-today--start-timer () + "Start the timer that will update the mode line every 60 seconds." + (setq org-clock-today--timer + (run-at-time 0 60 'org-clock-today--update-mode-line))) + +(defun org-clock-today--stop-timer () + "Stop the timer." + (org-clock-today--update-mode-line) + (cancel-timer org-clock-today--timer)) + +(defun org-clock-today--maybe-clear-org-mode-line-string () + "Clear the org mode line string depending on the defcustom setting." + (when org-clock-today-hide-default-org-clock-mode-line + (setq org-mode-line-string "") + (force-mode-line-update))) + +(defun org-clock-today-toggle-count-subtree () + "Toggle count total minutes in subtree or buffer." + (interactive) + (setq org-clock-today-count-subtree (not org-clock-today-count-subtree)) + (unless org-clock-today-count-subtree + (setq org-clock-today-subtree-time nil)) + (org-clock-today--update-mode-line)) + +;;;###autoload +(define-minor-mode org-clock-today-mode + "Minor mode to show the total clocked time of the current day in the mode line." + :lighter org-clock-today-string + :global t + (if org-clock-today-mode + (progn + (add-hook 'org-clock-in-hook 'org-clock-today--start-timer) + (add-hook 'org-clock-out-hook 'org-clock-today--stop-timer) + (advice-add 'org-clock-update-mode-line :after + 'org-clock-today--maybe-clear-org-mode-line-string)) + (remove-hook 'org-clock-in-hook 'org-clock-today--start-timer) + (remove-hook 'org-clock-out-hook 'org-clock-today--stop-timer) + (advice-remove 'org-clock-update-mode-line + 'org-clock-today--maybe-clear-org-mode-line-string))) + +(provide 'org-clock-today) + +;;; org-clock-today.el ends here diff --git a/elpa/org-clock-today-20190915.701/org-clock-today.elc b/elpa/org-clock-today-20190915.701/org-clock-today.elc new file mode 100644 index 0000000000000000000000000000000000000000..4b68fea11d1cd4246d090c30310b36ed9da7b2c6 GIT binary patch literal 5722 zcmbtY`)}LG5%x7L>bSr3TJ#F^mrmqMY!#u(haPr}J`PUWrjOk967-kIKvv{RT7)7M za%rFLukSazOH$S&%Ha%9CigkB^UXIid-dYq*S|eFIy$+!x}xiRu~ex{%!kV8#X`g- z-O8d=c}C%|7nz17+mS8cY&77`|9=e%a;_-MImAh5ucjv zMV3&RQ!Fx?NJ?{YZxg3VNm3N4k_G8G28NN{7f0};{#bw?`*(73az0sU>BV^>sWXmz zA5ZXT90vRn;)(F|@eJ?`@dS@u=V%=9pdi45fkE{AIesxTz|eq)@)JGz`Pz7%Ill?X{f?oSK)aOwzQ zTi=~$XtaS?Hx%4Z=Nix|^0WjPB;Be~O;oD%it?#xahtFNP6OVA%qAAnJxH%tOG%SF zPbC1=%43v;Evrm>Wi`=-l=}sFIW@qBU{8T}Od*|XkZLB{Mh=FYC8R>*ml6y>Onuk>icvx!wZ&% zH4I1et<+VK84KS#Wv7=&70&f+(~>|REaKG`sWBB09LxA7zeLB6#_YNM&)99@PjJ<+ zKX~xjc#QWUw;BYtiVLndX?bf*wncUhGra;y~-k>jKTW^S3UXe`W(*?8kAOc?xfkBJlPD&J7Q)^%{{bPYz(HD9)>9uz%aIsw+=fJI)25U?9nZpN08 zw(yP=HkPR!enVj`?nUG~(_A2mB9ArlVmWF&tEPiQE@fu;0qGAXH=q?t5jm!Q+P{{$+_fg3X=HP7kAUIk)MBzoy<+SDp2R7zI z=0K)EJg6#csqo|%4!NHi@eJ+`#yJ+zq}#7hyRnjLN?*g^Ce!rZm{4I>Lis2&&iRwx zID3tJnUVW$^GJB;8LYfmAij(<&QS#LUB-n%Q3|}9WEpEARYM;SH_I8=V@dQhwMBxW zCf4Z+MXIYdwRkT{A`gxA)i{%=cR_siJkl+-K`IYYGIXLfA87? zWRHiLsi$wl!O#?EO(N|-U@G|&pcsA5{>25a{|HX!hhOmb;HQu9JNzFKZ7{A$0RG7B zZ4GQXT#E&`Ygw;|gAvCUpO^hJribhi)+^j#({gWmQy`D*-k62{u&&B|CjRK3yjY)? z{TIItnxUw`!;u+Mp(Elfg=g@lK9tAQ_=uUseMU%V{KyPN6TYJ8{zgk)#ccF}-v$q$ z&v5t?yJEz-l3CgwAJ*EH=olL~vw90zmSQG3LNu7NG|1t@l-su=tt2fAIaS|zS%suP z#hz{S`C7-D=lT0J5>we`i%U$_gMSOyywZEeHxXAPx5#Nd?6$ViRt$Y6rYM2eM!1a+ z2DU;j@>^-ea9i0X;#`CELpcuiT2C_g7h8nN$Rj!+S-T}82v z4SxoZ`N6dVQjHl01%V{QLInh4DlH&p*TqA7QV0ZF1sP*Me1$Fg<0)^)fH!UU-?#3% zR-ajiHBRIYzBoF@cfbzhF2!tY+n0zA}ku%-$>$_bjIYTIVmBWK_gt;BEhT&lN zuJ)}n5*6;