update packages

This commit is contained in:
2022-01-04 21:35:17 +01:00
parent 1d5275c946
commit 8de00e5202
700 changed files with 42441 additions and 85378 deletions

View File

@@ -57,7 +57,6 @@ Contributors
- Alexey Voinov <alexey.v.voinov@gmail.com>
- Alex Kost <alezost@gmail.com>
- Alex Ott <alexott@gmail.com>
- Allen <darkfeline@felesatra.moe>
- Allen Li <darkfeline@felesatra.moe>
- Andreas Fuchs <asf@boinkor.net>
- Andreas Liljeqvist <andreas.liljeqvist@robacks.se>
@@ -65,6 +64,7 @@ Contributors
- Andrei Chițu <andrei.chitu1@gmail.com>
- Andrew Eggenberger <andrew.eggenberger@gmail.com>
- Andrew Kirkpatrick <andrew.kirkpatrick@adelaide.edu.au>
- Andrew Psaltis <apsaltis@vmware.com>
- Andrew Schwartzmeyer <andrew@schwartzmeyer.com>
- Andrey Smirnov <andrew.smirnov@gmail.com>
- Andriy Kmit' <dev@madand.net>
@@ -72,15 +72,18 @@ Contributors
- Aria Edmonds <aria@ar1as.space>
- Arialdo Martini <arialdomartini@gmail.com>
- Arnau Roig Ninerola <arnau.ninerola@outlook.com>
- Ashlynn Anderson <pea@pea.sh>
- Barak A. Pearlmutter <barak+git@pearlmutter.net>
- Bar Magal <bmagamb@gmail.com>
- Bart Bakker <bart@thesoftwarecraft.com>
- Basil L. Contovounesios <contovob@tcd.ie>
- Bastian Beischer <beischer@physik.rwth-aachen.de>
- Bastian Beranek <bastian.beranek@inovex.de>
- Benjamin Motz <benjamin.motz@mailbox.org>
- Ben North <ben@redfrontdoor.org>
- Ben Walton <bwalton@artsci.utoronto.ca>
- Bob Uhl <buhl@zvelo.com>
- Boruch Baum <boruch_baum@gmx.com>
- Bradley Wright <brad@intranation.com>
- Brandon W Maister <quodlibetor@gmail.com>
- Brian Leung <leungbk@mailfence.com>
@@ -108,17 +111,18 @@ Contributors
- Dan Erikson <derikson3@gmail.com>
- Daniel Brockman <daniel@gointeractive.se>
- Daniel Farina <drfarina@acm.org>
- Daniel Fleischer <danflscr@gmail.com>
- Daniel Gröber <daniel@dps.uibk.ac.at>
- Daniel Hackney <dan@haxney.org>
- Daniel Kraus <daniel@kraus.my>
- Daniel Mai <daniel@danielmai.net>
- Daniel Martín <mardani29@yahoo.es>
- Daniel Nagy <danielnagy@posteo.de>
- Dan LaManna <dan.lamanna@gmail.com>
- Danny Zhu <dzhu@dzhu.us>
- Dato Simó <dato@net.com.org.es>
- David Abrahams <dave@boostpro.com>
- David Ellison <davidehellison@gmail.com>
- David Ellison <davide@voicebox.com>
- David Hull <david.hull@openx.com>
- David L. Rager <ragerdl@gmail.com>
- David Wallin <david.wallin@gmail.com>
@@ -126,7 +130,6 @@ Contributors
- Dennis Paskorz <dennis@walltowall.com>
- Divye Kapoor <divye@google.com>
- Dominique Quatravaux <dominique.quatravaux@epfl.ch>
- Dominique Quatravaux <domq@google.com>
- Duianto Vebotci <vebotci@openmailbox.org>
- Eli Barzilay <eli@barzilay.org>
- Eric Davis <ed@npri.org>
@@ -142,6 +145,8 @@ Contributors
- Felix Yan <felixonmars@archlinux.org>
- Feng Li <fengli@blackmagicdesign.com>
- Florian Ragwitz <rafl@debian.org>
- Franklin Delehelle <franklin.delehelle@odena.eu>
- Frédéric Giquel <frederic.giquel@laposte.net>
- Fritz Grabo <fritz.grabo@gmail.com>
- Fritz Stelzer <brotzeitmacher@gmail.com>
- Geoff Shannon <geoffpshannon@gmail.com>
@@ -158,6 +163,8 @@ Contributors
- Hussein Ait-Lahcen <hussein.ait-lahcen@fretlink.com>
- Ian Eure <ian.eure@gmail.com>
- Ian Milligan <ianmllgn@gmail.com>
- Ilya Grigoriev <ilyagr@users.noreply.github.com>
- Ingmar Sittl <ingmar.sittl@elektrobit.com>
- Ingo Lohmar <i.lohmar@gmail.com>
- Ioan-Adrian Ratiu <adi@adirat.com>
- Ivan Brennan <ivan.brennan@gmail.com>
@@ -180,6 +187,7 @@ Contributors
- Jonathan del Strother <me@delstrother.com>
- Jonathan Leech-Pepin <jonathan.leechpepin@gmail.com>
- Jonathan Roes <jroes@jroes.net>
- Jonathon McKitrick <jonathon.mckitrick@doublethedonation.com>
- Jon Vanderwijk <jonathn@github.com>
- Jordan Galby <gravemind2a@gmail.com>
- Jordan Greenberg <jordan@softwareslave.com>
@@ -207,6 +215,7 @@ Contributors
- Leonardo Etcheverry <leo@kalio.net>
- Leo Vivier <leo.vivier+dev@gmail.com>
- Lingchao Xin <douglarek@users.noreply.github.com>
- Lin Sun <sunlin7@yahoo.com>
- Li-Yun Chang <michael142536@gmail.com>
- Lluís Vilanova <vilanova@ac.upc.edu>
- Loic Dachary <loic@dachary.org>
@@ -228,6 +237,8 @@ Contributors
- Mark Hepburn <Mark.Hepburn@csiro.au>
- Mark Karpov <markkarpov@opmbx.org>
- Mark Oteiza <mvoteiza@udel.edu>
- Martin Joerg <martin.joerg@gmail.com>
- Martin Polden <mpolden@yahoo-inc.com>
- Matthew Fluet <matthew.fluet@gmail.com>
- Matthew Kraai <kraai@ftbfs.org>
- Matthieu Hauglustaine <matt.hauglustaine@gmail.com>
@@ -256,10 +267,12 @@ Contributors
- Nikolay Martynov <mar.kolya@gmail.com>
- Noam Postavsky <npostavs@users.sourceforge.net>
- N. Troy de Freitas <me@ntdef.com>
- Ola x Nilsson <olani@axis.com>
- Ole Arndt <oliver.arndt@cegedim.com>
- Oleh Krehel <ohwoeowho@gmail.com>
- Orivej Desh <orivej@gmx.fr>
- Óscar Fuentes <ofv@wanadoo.es>
- Pancho Horrillo <pancho@pancho.name>
- Paul Stadig <paul@stadig.name>
- Pavel Holejsovsky <pavel.holejsovsky@upek.com>
- Pekka Pessi <nospam@pessi.fi>
@@ -267,6 +280,7 @@ Contributors
- Peter Jaros <peter.a.jaros@gmail.com>
- Peter J. Weisberg <pj@irregularexpressions.net>
- Peter Vasil <mail@petervasil.net>
- Philippe Cavalaria <philippe.cavalaria@gmail.com>
- Philippe Vaucher <philippe.vaucher@gmail.com>
- Philipp Fehre <pfehre@twitter.com>
- Philipp Haselwarter <philipp@haselwarter.org>
@@ -277,6 +291,7 @@ Contributors
- Pierre Neidhardt <ambrevar@gmail.com>
- Pieter Praet <pieter@praet.org>
- Prathamesh Sonpatki <csonpatki@gmail.com>
- Pritam Baral <pritam@pritambaral.com>
- rabio <rabiodev@o2.pl>
- Radon Rosborough <radon.neon@gmail.com>
- Rafael Laboissiere <rafael@laboissiere.net>
@@ -296,6 +311,7 @@ Contributors
- Rüdiger Sonderfeld <ruediger@c-plusplus.net>
- Russell Black <black.russell@gmail.com>
- Ryan C. Thompson <rct@thompsonclan.org>
- Sam Cedarbaum <scedarbaum@gmail.com>
- Samuel Bronson <naesten@gmail.com>
- Samuel W. Flint <swflint@flintfam.org>
- Sanjoy Das <sanjoy@playingwithpointers.com>
@@ -308,6 +324,7 @@ Contributors
- Sergey Pashinin <sergey@pashinin.com>
- Sergey Vinokurov <serg.foo@gmail.com>
- Servilio Afre Puentes <afrepues@mcmaster.ca>
- Siavash Askari Nasr <siavash.askari.nasr@gmail.com>
- Silent Sphere <silentsphere110@gmail.com>
- Simon Pintarelli <simon.pintarelli@cscs.ch>
- Štěpán Němec <stepnem@gmail.com>
@@ -322,6 +339,7 @@ Contributors
- Szunti <Szunti@users.noreply.github.com>
- Takafumi Arakaki <aka.tkf@gmail.com>
- Tassilo Horn <tsdh@gnu.org>
- TEC <tec@tecosaur.com>
- Teemu Likonen <tlikonen@iki.fi>
- Teruki Shigitani <teruki.shigitani@gmail.com>
- Thierry Volpiatto <thievol@posteo.net>
@@ -336,6 +354,7 @@ Contributors
- Tim Wraight <tim@wraight.net>
- Ting-Yu Lin <aethanyc@gmail.com>
- Tom Feist <shabble@metavore.org>
- Toon Claes <toon@iotcl.com>
- Topi Miettinen <toiwoton@gmail.com>
- Troy Hinckley <t.macman@gmail.com>
- Tsuyoshi Kitamoto <tsuyoshi.kitamoto@gmail.com>

View File

@@ -1,12 +1,11 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
@@ -69,7 +68,7 @@ patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
TERMS AND CONDITIONS
0. Definitions.
@@ -77,7 +76,7 @@ modification follow.
"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.
@@ -510,7 +509,7 @@ 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
@@ -619,9 +618,9 @@ 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
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
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
@@ -646,7 +645,7 @@ the "copyright" line and a pointer to where the full notice is found.
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 <http://www.gnu.org/licenses/>.
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
@@ -665,12 +664,11 @@ 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
<http://www.gnu.org/licenses/>.
<https://www.gnu.org/licenses/>.
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
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
<https://www.gnu.org/licenses/why-not-lgpl.html>.

View File

@@ -1,6 +1,6 @@
;;; git-rebase.el --- Edit Git rebase files -*- lexical-binding: t -*-
;; Copyright (C) 2010-2021 The Magit Project Contributors
;; Copyright (C) 2010-2022 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.
@@ -8,7 +8,7 @@
;; Author: Phil Jackson <phil@shellarchive.co.uk>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; This file is not part of GNU Emacs.
;; SPDX-License-Identifier: GPL-3.0-or-later
;; 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
@@ -74,21 +74,13 @@
;;; Code:
(require 'dash)
(require 'magit)
(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))
(defvar recentf-exclude)
;;; Options
;;;; Variables
@@ -120,32 +112,37 @@
:group 'faces
:group 'git-rebase)
(defface git-rebase-hash '((t (:inherit magit-hash)))
(defface git-rebase-hash '((t :inherit magit-hash))
"Face for commit hashes."
:group 'git-rebase-faces)
(defface git-rebase-label '((t (:inherit magit-refname)))
(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
(defface git-rebase-description '((t nil))
"Face for commit descriptions."
:group 'git-rebase-faces)
(defface git-rebase-action
'((t :inherit font-lock-keyword-face))
"Face for action keywords."
:group 'git-rebase-faces)
(defface git-rebase-killed-action
'((t (:inherit font-lock-comment-face :strike-through t)))
'((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)))
'((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)
:group 'git-rebase-faces)
;;; Keymaps
@@ -451,7 +448,7 @@ current line."
(when bounds
(magit-section-make-overlay (car bounds) (cadr bounds)
'magit-section-heading-selection))
(if (and bounds (not magit-keep-region-overlay))
(if (and bounds (not magit-section-keep-region-overlay))
(funcall (default-value 'redisplay-unhighlight-region-function) rol)
(funcall (default-value 'redisplay-highlight-region-function)
start end window rol))))
@@ -739,25 +736,25 @@ running 'man git-rebase' at the command line) for details."
(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)
(1 'git-rebase-action)
(3 'git-rebase-hash)
(4 'git-rebase-description))
(,(concat "^" (cdr (assq 'exec git-rebase-line-regexps)))
(1 'font-lock-keyword-face)
(1 'git-rebase-action)
(3 'git-rebase-description))
(,(concat "^" (cdr (assq 'bare git-rebase-line-regexps)))
(1 'font-lock-keyword-face))
(1 'git-rebase-action))
(,(concat "^" (cdr (assq 'label git-rebase-line-regexps)))
(1 'font-lock-keyword-face)
(1 'git-rebase-action)
(3 'git-rebase-label)
(4 'font-lock-comment-face))
("^\\(m\\(?:erge\\)?\\) -[Cc] \\([^ \n]+\\) \\([^ \n]+\\)\\( #.*\\)?"
(1 'font-lock-keyword-face)
(1 'git-rebase-action)
(2 'git-rebase-hash)
(3 'git-rebase-label)
(4 'font-lock-comment-face))
("^\\(m\\(?:erge\\)?\\) \\([^ \n]+\\)"
(1 'font-lock-keyword-face)
(1 'git-rebase-action)
(2 'git-rebase-label))
(,(concat git-rebase-comment-re " *"
(cdr (assq 'commit git-rebase-line-regexps)))
@@ -826,8 +823,8 @@ By default, this is the same except for the \"pick\" command."
(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))
(with-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)

View File

@@ -1,6 +1,6 @@
;;; magit-apply.el --- apply Git diffs -*- lexical-binding: t -*-
;; Copyright (C) 2010-2021 The Magit Project Contributors
;; Copyright (C) 2010-2022 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.
@@ -8,6 +8,8 @@
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; SPDX-License-Identifier: GPL-3.0-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)
@@ -30,9 +32,6 @@
;;; Code:
(eval-when-compile
(require 'subr-x))
(require 'magit-core)
(require 'magit-diff)
(require 'magit-wip)
@@ -40,8 +39,8 @@
(require 'transient) ; See #3732.
;; For `magit-apply'
(declare-function magit-am "magit-sequence" ())
(declare-function magit-patch-apply "magit-files" ())
(declare-function magit-am "magit-sequence" () t)
(declare-function magit-patch-apply "magit-patch" () t)
;; For `magit-discard-files'
(declare-function magit-checkout-stage "magit-merge" (file arg))
(declare-function magit-checkout-read-stage "magit-merge" (file))
@@ -56,6 +55,11 @@
(declare-function borg-assimilate "borg" (package url &optional partially))
(defvar borg-user-emacs-directory)
(cl-eval-when (compile load)
(when (< emacs-major-version 26)
(defalias 'smerge-keep-upper 'smerge-keep-mine)
(defalias 'smerge-keep-lower 'smerge-keep-other)))
;;; Options
(defcustom magit-delete-by-moving-to-trash t
@@ -178,7 +182,7 @@ adjusted as \"@@ -10,6 +10,7 @@\" and \"@@ -18,6 +19,7 @@\"."
(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"))))
(error "Header hunks have to be applied individually"))))
(if (= offset 0)
hunks
(mapcar (lambda (hunk)
@@ -208,10 +212,15 @@ adjusted as \"@@ -10,6 +10,7 @@\" and \"@@ -18,6 +19,7 @@\"."
(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)))))
(let* ((header (car (oref section value)))
(header (and (symbolp header) header))
(content (magit-apply--section-content section)))
(magit-apply-patch
(oref section parent) args
(concat (magit-diff-file-header section (not (eq header 'rename)))
(if header
content
(magit-apply--adjust-hunk-new-start content))))))
(defun magit-apply-region (section &rest args)
(when (string-match "^diff --cc" (magit-section-parent-value section))
@@ -232,7 +241,7 @@ adjusted as \"@@ -10,6 +10,7 @@\" and \"@@ -18,6 +19,7 @@\"."
(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))
(when (and magit-wip-before-change-mode (not magit-inhibit-refresh))
(magit-wip-commit-before-change files (concat " before " command)))
(with-temp-buffer
(insert patch)
@@ -240,7 +249,7 @@ adjusted as \"@@ -10,6 +10,7 @@\" and \"@@ -18,6 +19,7 @@\"."
"apply" args "-p0"
(and ignore-context "-C0")
"--ignore-space-change" "-"))
(unless inhibit-magit-refresh
(unless magit-inhibit-refresh
(when magit-wip-after-apply-mode
(magit-wip-commit-after-apply files (concat " after " command)))
(magit-refresh))))
@@ -445,6 +454,8 @@ without requiring confirmation."
(defun magit-unstage-all ()
"Remove all changes from the staging area."
(interactive)
(unless (magit-anything-staged-p)
(user-error "Nothing to unstage"))
(when (or (magit-anything-unstaged-p)
(magit-untracked-files))
(magit-confirm 'unstage-all-changes))
@@ -455,7 +466,11 @@ without requiring confirmation."
;;;; Discard
(defun magit-discard ()
"Remove the change at point."
"Remove the change at point.
On a hunk or file with unresolved conflicts prompt which side to
keep (while discarding the other). If point is within the text
of a side, then keep that side without prompting."
(interactive)
(--when-let (magit-apply--get-selection)
(pcase (list (magit-diff-type) (magit-diff-scope))
@@ -474,7 +489,10 @@ without requiring confirmation."
(defun magit-discard-hunk (section)
(magit-confirm 'discard "Discard hunk")
(magit-discard-apply section 'magit-apply-hunk))
(let ((file (magit-section-parent-value section)))
(pcase (cddr (car (magit-file-status file)))
(`(?U ?U) (magit-smerge-keep-current))
(_ (magit-discard-apply section 'magit-apply-hunk)))))
(defun magit-discard-apply (section apply)
(if (eq (magit-diff-type section) 'unstaged)
@@ -483,7 +501,7 @@ without requiring confirmation."
nil (if (magit-file-section-p section)
(oref section value)
(magit-section-parent-value section)))
(progn (let ((inhibit-magit-refresh t))
(progn (let ((magit-inhibit-refresh t))
(funcall apply section "--reverse" "--cached")
(funcall apply section "--reverse" "--reject"))
(magit-refresh))
@@ -503,7 +521,7 @@ without requiring confirmation."
nil (if (magit-file-section-p section)
(oref section value)
(magit-section-parent-value section)))
(progn (let ((inhibit-magit-refresh t))
(progn (let ((magit-inhibit-refresh t))
(funcall apply sections "--reverse" "--cached")
(funcall apply sections "--reverse" "--reject"))
(magit-refresh))
@@ -541,7 +559,7 @@ without requiring confirmation."
(`(?Y ,_ ?D ) (push file resurrect))
(`(?X ?R ,(or ? ?M ?D)) (push file rename)))))
(unwind-protect
(let ((inhibit-magit-refresh t))
(let ((magit-inhibit-refresh t))
(magit-wip-commit-before-change files " before discard")
(when resolve
(magit-discard-files--resolve (nreverse resolve)))
@@ -731,6 +749,60 @@ a separate commit. A typical workflow would be:
(interactive)
(magit-reverse (cons "--cached" args)))
;;; Smerge Support
(defun magit-smerge-keep-current ()
"Keep the current version of the conflict at point."
(interactive)
(magit-call-smerge #'smerge-keep-current))
(defun magit-smerge-keep-upper ()
"Keep the upper/our version of the conflict at point."
(interactive)
(magit-call-smerge #'smerge-keep-upper))
(defun magit-smerge-keep-base ()
"Keep the base version of the conflict at point."
(interactive)
(magit-call-smerge #'smerge-keep-base))
(defun magit-smerge-keep-lower ()
"Keep the lower/their version of the conflict at point."
(interactive)
(magit-call-smerge #'smerge-keep-lower))
(defun magit-call-smerge (fn)
(pcase-let* ((file (magit-file-at-point t t))
(keep (get-file-buffer file))
(`(,buf ,pos)
(let ((magit-diff-visit-jump-to-change nil))
(magit-diff-visit-file--noselect file))))
(with-current-buffer buf
(save-excursion
(save-restriction
(unless (<= (point-min) pos (point-max))
(widen))
(goto-char pos)
(condition-case nil
(smerge-match-conflict)
(error
(if (eq fn 'smerge-keep-current)
(when (eq this-command 'magit-discard)
(re-search-forward smerge-begin-re nil t)
(setq fn
(magit-read-char-case "Keep side: " t
(?o "[o]urs/upper" #'smerge-keep-upper)
(?b "[b]ase" #'smerge-keep-base)
(?t "[t]heirs/lower" #'smerge-keep-lower))))
(re-search-forward smerge-begin-re nil t))))
(funcall fn)))
(when (and keep (magit-anything-unmerged-p file))
(smerge-start-session))
(save-buffer))
(unless keep
(kill-buffer buf))
(magit-refresh)))
;;; _
(provide 'magit-apply)
;;; magit-apply.el ends here

View File

@@ -1,6 +1,6 @@
;;; magit-autorevert.el --- revert buffers when files in repository change -*- lexical-binding: t -*-
;; Copyright (C) 2010-2021 The Magit Project Contributors
;; Copyright (C) 2010-2022 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.
@@ -8,6 +8,8 @@
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; SPDX-License-Identifier: GPL-3.0-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)
@@ -23,9 +25,6 @@
;;; Code:
(require 'cl-lib)
(require 'dash)
(require 'magit-git)
(require 'autorevert)

View File

@@ -1,6 +1,6 @@
;;; magit-bisect.el --- bisect support for Magit -*- lexical-binding: t -*-
;; Copyright (C) 2011-2021 The Magit Project Contributors
;; Copyright (C) 2011-2022 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.
@@ -8,6 +8,8 @@
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; SPDX-License-Identifier: GPL-3.0-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)
@@ -65,9 +67,9 @@
("-p" "Follow only first parent of a merge" "--first-parent"
:if (lambda () (version<= "2.29" (magit-git-version))))
(6 magit-bisect:--term-old
:if (lambda () (version<= "2.7" (magit-git-version))))
:if (lambda () (version<= "2.7" (magit-git-version))))
(6 magit-bisect:--term-new
:if (lambda () (version<= "2.7" (magit-git-version))))]
:if (lambda () (version<= "2.7" (magit-git-version))))]
["Actions"
("B" "Start" magit-bisect-start)
("s" "Start script" magit-bisect-run)]]
@@ -76,7 +78,7 @@
("B" "Bad" magit-bisect-bad)
("g" "Good" magit-bisect-good)
(6 "m" "Mark" magit-bisect-mark
:if (lambda () (version<= "2.7" (magit-git-version))))
:if (lambda () (version<= "2.7" (magit-git-version))))
("k" "Skip" magit-bisect-skip)
("r" "Reset" magit-bisect-reset)
("s" "Run script" magit-bisect-run)])
@@ -194,7 +196,14 @@ bisect run'."
(magit-bisect-start-read-args))))
(cons (read-shell-command "Bisect shell command: ") args)))
(when (and bad good)
(magit-bisect-start bad good args))
;; Avoid `magit-git-bisect' because it's asynchronous, but the
;; next `git bisect run' call requires the bisect to be started.
(magit-with-toplevel
(magit-process-git
(list :file (magit-git-dir "BISECT_CMD_OUTPUT"))
(magit-process-git-arguments
(list "bisect" "start" bad good args)))
(magit-refresh)))
(magit-git-bisect "run" (list shell-file-name shell-command-switch cmdline)))
(defun magit-git-bisect (subcommand &optional args no-assert)

View File

@@ -1,6 +1,6 @@
;;; magit-blame.el --- blame support for Magit -*- lexical-binding: t -*-
;; Copyright (C) 2012-2021 The Magit Project Contributors
;; Copyright (C) 2012-2022 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.
@@ -8,6 +8,8 @@
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; SPDX-License-Identifier: GPL-3.0-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)
@@ -28,9 +30,6 @@
;;; Code:
(eval-when-compile
(require 'subr-x))
(require 'magit)
;;; Options
@@ -198,19 +197,19 @@ Also see option `magit-blame-styles'."
Also see option `magit-blame-styles'."
:group 'magit-faces)
(defface magit-blame-summary nil
(defface magit-blame-summary '((t nil))
"Face used for commit summaries when blaming."
:group 'magit-faces)
(defface magit-blame-hash nil
(defface magit-blame-hash '((t nil))
"Face used for commit hashes when blaming."
:group 'magit-faces)
(defface magit-blame-name nil
(defface magit-blame-name '((t nil))
"Face used for author and committer names when blaming."
:group 'magit-faces)
(defface magit-blame-date nil
(defface magit-blame-date '((t nil))
"Face used for dates when blaming."
:group 'magit-faces)
@@ -228,25 +227,27 @@ Also see option `magit-blame-styles'."
;; filename <orig-file>
(orig-file)))
(defun magit-current-blame-chunk (&optional type)
(defun magit-current-blame-chunk (&optional type noerror)
(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)))
(file (and (not (derived-mode-p 'dired-mode))
(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))))))))
(cond (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)))))
(noerror nil)
(t (error "Buffer does not visit a tracked file")))))))
(defun magit-blame-chunk-at (pos)
(--some (overlay-get it 'magit-blame-chunk)
@@ -489,10 +490,10 @@ modes is toggled, then this mode also gets toggled automatically.
(while (not done)
(cond ((looking-at "^filename \\(.+\\)")
(setq done t)
(setf orig-file (match-string 1)))
(setf orig-file (magit-decode-git-path (match-string 1))))
((looking-at "^previous \\(.\\{40\\}\\) \\(.+\\)")
(setf prev-rev (match-string 1))
(setf prev-file (match-string 2)))
(setf prev-file (magit-decode-git-path (match-string 2))))
((looking-at "^\\([^ ]+\\) \\(.+\\)")
(push (cons (match-string 1)
(match-string 2)) revinfo)))
@@ -702,9 +703,9 @@ modes is toggled, then this mode also gets toggled automatically.
(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)))))
(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.")))))
@@ -896,6 +897,7 @@ instead of the hash, like `kill-ring-save' would."
["Arguments"
("-w" "Ignore whitespace" "-w")
("-r" "Do not treat root commits as boundaries" "--root")
("-P" "Follow only first parent" "--first-parent")
(magit-blame:-M)
(magit-blame:-C)]
["Actions"
@@ -915,12 +917,14 @@ instead of the hash, like `kill-ring-save' would."
:description "Detect lines moved or copied within a file"
:class 'transient-option
:argument "-M"
:allow-empty t
:reader 'transient-read-number-N+)
(transient-define-argument magit-blame:-C ()
:description "Detect lines moved or copied between files"
:class 'transient-option
:argument "-C"
:allow-empty t
:reader 'transient-read-number-N+)
;;; Utilities

View File

@@ -1,6 +1,6 @@
;;; magit-bookmark.el --- bookmark support for Magit -*- lexical-binding: t -*-
;; Copyright (C) 2010-2021 The Magit Project Contributors
;; Copyright (C) 2010-2022 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.
@@ -10,6 +10,8 @@
;; Inspired by an earlier implementation by Yuri Khan.
;; SPDX-License-Identifier: GPL-3.0-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)
@@ -29,9 +31,6 @@
;;; Code:
(eval-when-compile
(require 'subr-x))
(require 'magit)
(require 'bookmark)
@@ -43,7 +42,11 @@ 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-make-record-default's return value does not match
;; (NAME . ALIST), even though it is used as the default value
;; of `bookmark-make-record-function', which states that such
;; functions must do that. See #4356.
(let ((bookmark (cons nil (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))
@@ -87,6 +90,9 @@ with the variables' values as arguments, which were recorded by
hidden)
(magit-section-hide child)
(magit-section-show child)))))
;; Compatibility with `bookmark+' package. See #4356.
(when (bound-and-true-p bmkp-jump-display-function)
(funcall bmkp-jump-display-function (current-buffer)))
nil))
(cl-defgeneric magit-bookmark-name ()

View File

@@ -1,6 +1,6 @@
;;; magit-branch.el --- branch support -*- lexical-binding: t -*-
;; Copyright (C) 2010-2021 The Magit Project Contributors
;; Copyright (C) 2010-2022 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.
@@ -8,6 +8,8 @@
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; SPDX-License-Identifier: GPL-3.0-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)
@@ -31,9 +33,6 @@
;;; Code:
(eval-when-compile
(require 'subr-x))
(require 'magit)
(require 'magit-reset)
@@ -115,7 +114,8 @@ 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.
element is used whose UPSTREAM exists and whose RULE matches
the name of the new branch. Subsequent 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.
@@ -129,7 +129,7 @@ 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\"))
((\"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:
@@ -141,6 +141,16 @@ Of course you can also fine-tune:
((\"origin/maint\" . \"\\\\\\=`hotfix/\")
(\"origin/master\" . \"\\\\\\=`feature/\"))
UPSTREAM can be a local branch:
((\"master\" . (\"master\" \"next\" \"maint\")))
Because the main branch is no longer almost always named \"master\"
you should also account for other common names:
((\"main\" . (\"main\" \"master\" \"next\" \"maint\"))
(\"master\" . (\"main\" \"master\" \"next\" \"maint\")))
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."
@@ -204,6 +214,10 @@ has to be used to view and change branch related variables."
(transient-define-prefix magit-branch (branch)
"Add, configure or remove a branch."
:man-page "git-branch"
["Arguments"
(7 "-r" "Recurse submodules when checking out an existing branch"
"--recurse-submodules"
:if (lambda () (version<= "2.13" (magit-git-version))))]
["Variables"
:if (lambda ()
(and magit-branch-direct-configure
@@ -235,18 +249,22 @@ has to be used to view and change branch related variables."
(interactive (list (magit-get-current-branch)))
(transient-setup 'magit-branch nil nil :scope branch))
(defun magit-branch-arguments ()
(transient-args 'magit-branch))
;;;###autoload
(defun magit-checkout (revision)
(defun magit-checkout (revision &optional args)
"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")))
(interactive (list (magit-read-other-branch-or-commit "Checkout")
(magit-branch-arguments)))
(when (string-match "\\`heads/\\(.+\\)" revision)
(setq revision (match-string 1 revision)))
(magit-run-git "checkout" revision))
(magit-run-git "checkout" args revision))
;;;###autoload
(defun magit-branch-create (branch start-point)
@@ -257,12 +275,13 @@ changes.
(magit-refresh))
;;;###autoload
(defun magit-branch-and-checkout (branch start-point)
(defun magit-branch-and-checkout (branch start-point &optional args)
"Create and checkout BRANCH at branch or revision START-POINT."
(interactive (magit-branch-read-args "Create and checkout branch"))
(interactive (append (magit-branch-read-args "Create and checkout branch")
(list (magit-branch-arguments))))
(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-call-git "checkout" args "-b" branch start-point)
(magit-branch-maybe-adjust-upstream branch start-point)
(magit-refresh)))
@@ -339,16 +358,18 @@ when using `magit-branch-and-checkout'."
(t
(list choice (magit-read-starting-point "Create" choice))))))
(if (not start-point)
(magit-checkout branch)
(magit-checkout branch (magit-branch-arguments))
(when (magit-anything-modified-p t)
(user-error "Cannot checkout when there are uncommitted changes"))
(magit-branch-and-checkout branch start-point)
(let ((magit-inhibit-refresh t))
(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"))))))
(magit-set remote "branch" branch "pushRemote"))))
(magit-refresh)))
(defun magit-branch-maybe-adjust-upstream (branch start-point)
(--when-let
@@ -356,10 +377,13 @@ when using `magit-branch-and-checkout'."
(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)))))
(-some (pcase-lambda (`(,upstream . ,rule))
(and (magit-branch-p upstream)
(if (listp rule)
(not (member name rule))
(string-match-p rule name))
upstream))
magit-branch-adjust-remote-upstream-alist))))
(magit-call-git "branch" (concat "--set-upstream-to=" it) branch)))
;;;###autoload
@@ -498,7 +522,7 @@ that is being reset."
(or (and (not (equal branch atpoint)) atpoint)
(magit-get-upstream-branch branch)))
current-prefix-arg)))
(let ((inhibit-magit-refresh t))
(let ((magit-inhibit-refresh t))
(if (equal branch (magit-get-current-branch))
(if (and (magit-anything-modified-p)
(not (yes-or-no-p
@@ -562,16 +586,32 @@ defaulting to the branch at point."
((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"
(and (or force magit-branch-delete-never-verify) "--no-verify")
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))))
(cond
((magit-confirm 'delete-branch-on-remote
"Delete %s on the remote (not just locally)"
"Delete %i branches on the remote (not just locally)"
'noabort branches)
;; The ref may actually point at another rev on the remote,
;; but this is better than nothing.
(dolist (ref refs)
(message "Delete %s (was %s)" ref
(magit-rev-parse "--short" ref)))
;; Assume the branches actually still exist on the remote.
(magit-run-git-async
"push"
(and (or force magit-branch-delete-never-verify) "--no-verify")
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)))
(t
(dolist (ref refs)
(message "Delete %s (was %s)" ref
(magit-rev-parse "--short" ref))
(magit-call-git "update-ref" "-d" ref))
(magit-refresh)))))
((> (length branches) 1)
(setq branches (delete (magit-get-current-branch) branches))
(mapc 'magit-branch-maybe-delete-pr-remote branches)
@@ -579,17 +619,21 @@ defaulting to the branch at point."
(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)))
(prompt (format "Branch %s is checked out. " branch))
(target (magit-get-upstream-branch)))
(when (equal branch (magit-get-current-branch))
(pcase (if (or (equal branch "master")
(not (magit-rev-verify "master")))
(when (or (equal branch target)
(not target))
(setq target (magit-main-branch)))
(pcase (if (or (equal branch target)
(not target))
(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)))
(?d "[d]etach HEAD & delete" 'detach)
(?c (format "[c]heckout %s & delete" target) 'target)
(?a "[a]bort" 'abort)))
(`detach (unless (or (equal force '(4))
(member branch force)
(magit-branch-merged-p branch t))
@@ -597,13 +641,13 @@ defaulting to the branch at point."
"Delete unmerged branch %s" ""
nil (list branch)))
(magit-call-git "checkout" "--detach"))
(`master (unless (or (equal force '(4))
(`target (unless (or (equal force '(4))
(member branch force)
(magit-branch-merged-p branch "master"))
(magit-branch-merged-p branch target))
(magit-confirm 'delete-unmerged-branch
"Delete unmerged branch %s" ""
nil (list branch)))
(magit-call-git "checkout" "master"))
(magit-call-git "checkout" target))
(`abort (user-error "Abort")))
(setq force t))
(magit-branch-maybe-delete-pr-remote branch)
@@ -686,15 +730,15 @@ the remote."
(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
(old-specified (magit-get "branch" old "pushRemote"))
(new-specified (magit-get "branch" new "pushRemote")))
(when (and old-specified (or force (not new-specified)))
;; Keep the target setting branch specified, 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"))
(magit-set old-specified "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))

135
lisp/magit/magit-bundle.el Normal file
View File

@@ -0,0 +1,135 @@
;;; magit-bundle.el --- bundle support for Magit -*- lexical-binding: t -*-
;; Copyright (C) 2011-2022 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 <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; SPDX-License-Identifier: GPL-3.0-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.
;;; Code:
(require 'magit)
;;; Commands
;;;###autoload (autoload 'magit-bundle "magit-bundle" nil t)
(transient-define-prefix magit-bundle ()
"Create or verify Git bundles."
:man-page "git-bundle"
["Actions"
("c" "create" magit-bundle-create)
("v" "verify" magit-bundle-verify)
("l" "list-heads" magit-bundle-list-heads)])
;;;###autoload (autoload 'magit-bundle-import "magit-bundle" nil t)
(transient-define-prefix magit-bundle-create (&optional file refs args)
"Create a bundle."
:man-page "git-bundle"
["Arguments"
("-a" "Include all refs" "--all")
("-b" "Include branches" "--branches=" :allow-empty t)
("-t" "Include tags" "--tags=" :allow-empty t)
("-r" "Include remotes" "--remotes=" :allow-empty t)
("-g" "Include refs" "--glob=")
("-e" "Exclude refs" "--exclude=")
(magit-log:-n)
(magit-log:--since)
(magit-log:--until)]
["Actions"
("c" "create regular bundle" magit-bundle-create)
("t" "create tracked bundle" magit-bundle-create-tracked)
("u" "update tracked bundle" magit-bundle-update-tracked)]
(interactive
(and (eq transient-current-command 'magit-bundle-create)
(list (read-file-name "Create bundle: " nil nil nil
(concat (file-name-nondirectory
(directory-file-name (magit-toplevel)))
".bundle"))
(magit-completing-read-multiple* "Refnames (zero or more): "
(magit-list-refnames))
(transient-args 'magit-bundle-create))))
(if file
(magit-git-bundle "create" file refs args)
(transient-setup 'magit-bundle-create)))
;;;###autoload
(defun magit-bundle-create-tracked (file tag branch refs args)
"Create and track a new bundle."
(interactive
(let ((tag (magit-read-tag "Track bundle using tag"))
(branch (magit-read-branch "Bundle branch"))
(refs (magit-completing-read-multiple*
"Additional refnames (zero or more): "
(magit-list-refnames))))
(list (read-file-name "File: " nil nil nil (concat tag ".bundle"))
tag branch
(if (equal branch (magit-get-current-branch))
(cons "HEAD" refs)
refs)
(transient-args 'magit-bundle-create))))
(magit-git-bundle "create" file (cons branch refs) args)
(magit-git "tag" "--force" tag branch
"-m" (concat ";; git-bundle tracking\n"
(pp-to-string `((file . ,file)
(branch . ,branch)
(refs . ,refs)
(args . ,args))))))
;;;###autoload
(defun magit-bundle-update-tracked (tag)
"Update a bundle that is being tracked using TAG."
(interactive (list (magit-read-tag "Update bundle tracked by tag" t)))
(let (msg)
(let-alist (magit--with-temp-process-buffer
(save-excursion
(magit-git-insert "for-each-ref" "--format=%(contents)"
(concat "refs/tags/" tag)))
(setq msg (buffer-string))
(ignore-errors (read (current-buffer))))
(unless (and .file .branch)
(error "Tag %s does not appear to track a bundle" tag))
(magit-git-bundle "create" .file
(cons (concat tag ".." .branch) .refs)
.args)
(magit-git "tag" "--force" tag .branch "-m" msg))))
;;;###autoload
(defun magit-bundle-verify (file)
"Check whether FILE is valid and applies to the current repository."
(interactive (list (magit-bundle--read-file-name "Verify bundle: ")))
(magit-process-buffer)
(magit-git-bundle "verify" file))
;;;###autoload
(defun magit-bundle-list-heads (file)
"List the refs in FILE."
(interactive (list (magit-bundle--read-file-name "List heads of bundle: ")))
(magit-process-buffer)
(magit-git-bundle "list-heads" file))
(defun magit-bundle--read-file-name (prompt)
(read-file-name prompt nil nil t (magit-file-at-point) #'file-regular-p))
(defun magit-git-bundle (command file &optional refs args)
(magit-git "bundle" command (magit-convert-filename-for-git file) refs args))
;;; _
(provide 'magit-bundle)
;;; magit-bundle.el ends here

View File

@@ -1,6 +1,6 @@
;;; magit-clone.el --- clone a repository -*- lexical-binding: t -*-
;; Copyright (C) 2008-2021 The Magit Project Contributors
;; Copyright (C) 2008-2022 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.
@@ -8,6 +8,8 @@
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; SPDX-License-Identifier: GPL-3.0-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)
@@ -193,11 +195,15 @@ Then show the status buffer for the new repository."
(defun magit-clone-internal (repository directory args)
(let* ((checkout (not (memq (car args) '("--bare" "--mirror"))))
(remote (or (transient-arg-value "--origin" args)
(magit-get "clone.defaultRemote")
"origin"))
(set-push-default
(and checkout
(or (eq magit-clone-set-remote.pushDefault t)
(and magit-clone-set-remote.pushDefault
(y-or-n-p "Set `remote.pushDefault' to \"origin\"? "))))))
(y-or-n-p (format "Set `remote.pushDefault' to %S? "
remote)))))))
(run-hooks 'magit-credential-hook)
(setq directory (file-name-as-directory (expand-file-name directory)))
(when (file-exists-p directory)
@@ -225,9 +231,9 @@ Then show the status buffer for the new repository."
(when checkout
(let ((default-directory directory))
(when set-push-default
(setf (magit-get "remote.pushDefault") "origin"))
(setf (magit-get "remote.pushDefault") remote))
(unless magit-clone-set-remote-head
(magit-remote-unset-head "origin"))))
(magit-remote-unset-head remote))))
(with-current-buffer (process-get process 'command-buf)
(magit-status-setup-buffer directory)))))))
@@ -251,9 +257,15 @@ Then show the status buffer for the new repository."
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://")))))
(magit-convert-filename-for-git
(read-directory-name "Clone repository: ")))
(?l "[l]ocal url"
(concat "file://"
(magit-convert-filename-for-git
(read-directory-name "Clone repository: file://"))))
(?b "or [b]undle"
(magit-convert-filename-for-git
(read-file-name "Clone from bundle: ")))))
(defun magit-clone--url-to-name (url)
(and (string-match "\\([^/:]+?\\)\\(/?\\.git\\)?$" url)

View File

@@ -1,6 +1,6 @@
;;; magit-commit.el --- create Git commits -*- lexical-binding: t -*-
;; Copyright (C) 2008-2021 The Magit Project Contributors
;; Copyright (C) 2008-2022 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.
@@ -8,6 +8,8 @@
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; SPDX-License-Identifier: GPL-3.0-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)
@@ -34,7 +36,6 @@
(eval-when-compile (require 'epa)) ; for `epa-protocol'
(eval-when-compile (require 'epg))
(eval-when-compile (require 'subr-x))
;;; Options
@@ -90,6 +91,34 @@ Also see `git-commit-post-finish-hook'."
:group 'magit-commands
:type 'hook)
(defcustom magit-commit-diff-inhibit-same-window nil
"Whether to inhibit use of same window when showing diff while committing.
When writing a commit, then a diff of the changes to be committed
is automatically shown. The idea is that the diff is shown in a
different window of the same frame and for most users that just
works. In other words most users can completely ignore this
option because its value doesn't make a difference for them.
However for users who configured Emacs to never create a new
window even when the package explicitly tries to do so, then
displaying two new buffers necessarily means that the first is
immediately replaced by the second. In our case the message
buffer is immediately replaced by the diff buffer, which is of
course highly undesirable.
A workaround is to suppress this user configuration in this
particular case. Users have to explicitly opt-in by toggling
this option. We cannot enable the workaround unconditionally
because that again causes issues for other users: if the frame
is too tiny or the relevant settings too aggressive, then the
diff buffer would end up being displayed in a new frame.
Also see https://github.com/magit/magit/issues/4132."
:package-version '(magit . "3.3.0")
:group 'magit-commands
:type 'boolean)
(defvar magit-post-commit-hook-commands
'(magit-commit-extend
magit-commit-fixup
@@ -145,28 +174,46 @@ Also see `git-commit-post-finish-hook'."
:shortarg "-S"
:argument "--gpg-sign="
:allow-empty t
:reader 'magit-read-gpg-secret-key)
:reader 'magit-read-gpg-signing-key)
(defvar magit-gpg-secret-key-hist nil)
(defun magit-read-gpg-secret-key (prompt &optional initial-input history)
(defun magit-read-gpg-secret-key
(prompt &optional initial-input history predicate)
(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))))
(let* ((keys (cl-mapcan
(lambda (cert)
(and (or (not predicate)
(funcall predicate cert))
(let* ((key (car (epg-key-sub-key-list cert)))
(fpr (epg-sub-key-fingerprint key))
(id (epg-sub-key-id key))
(author
(when-let ((id-obj
(car (epg-key-user-id-list cert))))
(let ((id-str (epg-user-id-string id-obj)))
(if (stringp id-str)
id-str
(epg-decode-dn id-obj))))))
(list
(propertize fpr 'display
(concat (substring fpr 0 (- (length id)))
(propertize id 'face 'highlight)
" " 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))
(defun magit-read-gpg-signing-key (prompt &optional initial-input history)
(magit-read-gpg-secret-key
prompt initial-input history
(lambda (cert)
(cl-some (lambda (key)
(memq 'sign (epg-sub-key-capability key)))
(epg-key-sub-key-list cert)))))
(transient-define-argument magit-commit:--reuse-message ()
:description "Reuse commit message"
:class 'transient-option
@@ -264,7 +311,10 @@ depending on the value of option `magit-commit-squash-confirm'."
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'."
depending on the value of option `magit-commit-squash-confirm'.
If you want to immediately add a message to the squash commit,
then use `magit-commit-augment' instead of this command."
(interactive (list (magit-commit-at-point)
(magit-commit-arguments)))
(magit-commit-squash-internal "--squash" commit args))
@@ -296,7 +346,7 @@ depending on the value of option `magit-commit-squash-confirm'."
(defun magit-commit-squash-internal
(option commit &optional args rebase edit confirmed)
(when-let ((args (magit-commit-assert args t)))
(when-let ((args (magit-commit-assert args (not edit))))
(when commit
(when (and rebase (not (magit-rev-ancestor-p commit "HEAD")))
(magit-read-char-case
@@ -360,9 +410,9 @@ depending on the value of option `magit-commit-squash-confirm'."
(or (member "--amend" args)
(member "--allow-empty" args)
(member "--reset-author" args)
(member "--author" args)
(member "--signoff" args)
(cl-find-if (lambda (a) (string-match-p "\\`--date=" a)) args))))
(transient-arg-value "--author=" args)
(transient-arg-value "--date=" args))))
(or args (list "--")))
((and (magit-rebase-in-progress-p)
(not (magit-anything-unstaged-p))
@@ -391,29 +441,37 @@ depending on the value of option `magit-commit-squash-confirm'."
(defvar magit--reshelve-history nil)
;;;###autoload
(defun magit-commit-reshelve (date)
(defun magit-commit-reshelve (date update-author &optional args)
"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."
The current time is used as the initial minibuffer input and the
original author or committer date is available as the previous
history element.
Both the author and the committer dates are changes, unless one
of the following is true, in which case only the committer date
is updated:
- You are not the author of the commit that is being reshelved.
- The command was invoked with a prefix argument.
- Non-interactively if UPDATE-AUTHOR is nil."
(interactive
(let ((author-p (magit-rev-author-p "HEAD")))
(push (magit-rev-format (if author-p "%ad" "%cd") "HEAD"
(let ((update-author (and (magit-rev-author-p "HEAD")
(not current-prefix-arg))))
(push (magit-rev-format (if update-author "%ad" "%cd") "HEAD"
(concat "--date=format:%F %T %z"))
magit--reshelve-history)
(list (read-string (if author-p
(list (read-string (if update-author
"Change author and committer dates to: "
"Change committer date to: ")
(cons (format-time-string "%F %T %z") 17)
'magit--reshelve-history))))
'magit--reshelve-history)
update-author
(magit-commit-arguments))))
(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)))))
(and update-author (concat "--date=" date))
args)))
;;;###autoload
(defun magit-commit-absorb-modules (phase commit)
@@ -544,7 +602,11 @@ See `magit-commit-absorb' for an alternative implementation."
(magit-inhibit-save-previous-winconf 'unset)
(magit-display-buffer-noselect t)
(inhibit-quit nil)
(display-buffer-overriding-action '(nil (inhibit-same-window t))))
(display-buffer-overriding-action
display-buffer-overriding-action))
(when magit-commit-diff-inhibit-same-window
(setq display-buffer-overriding-action
'(nil (inhibit-same-window t))))
(message "Diffing changes to be committed (C-g to abort diffing)")
(cl-case last-command
(magit-commit

View File

@@ -1,6 +1,6 @@
;;; magit-core.el --- core functionality -*- lexical-binding: t -*-
;; Copyright (C) 2010-2021 The Magit Project Contributors
;; Copyright (C) 2010-2022 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.
@@ -8,6 +8,8 @@
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; SPDX-License-Identifier: GPL-3.0-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)
@@ -94,6 +96,9 @@ Each of these options falls into one or more of these categories:
:group 'magit
:group 'faces)
(custom-add-to-group 'magit-faces 'diff-refine-added 'custom-face)
(custom-add-to-group 'magit-faces 'diff-refine-removed 'custom-face)
(defgroup magit-extensions nil
"Extensions to Magit."
:group 'magit)

View File

@@ -1,6 +1,6 @@
;;; magit-diff.el --- inspect Git diffs -*- lexical-binding: t -*-
;; Copyright (C) 2010-2021 The Magit Project Contributors
;; Copyright (C) 2010-2022 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.
@@ -8,6 +8,8 @@
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; SPDX-License-Identifier: GPL-3.0-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)
@@ -28,25 +30,27 @@
;;; Code:
(eval-when-compile
(require 'ansi-color)
(require 'subr-x))
(require 'git-commit)
(require 'magit-core)
(require 'git-commit)
(eval-when-compile (require 'ansi-color))
(require 'diff-mode)
(require 'image)
(require 'smerge-mode)
;; 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 dired-jump "dired" ; dired-x before 27.1
(&optional other-window file-name))
(declare-function magit-find-file-noselect "magit-files" (rev file))
(declare-function magit-status-setup-buffer "magit-status" (directory))
(declare-function magit-status-setup-buffer "magit-status" (&optional 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-current-blame-chunk "magit-blame" (&optional type noerror))
(declare-function magit-blame-mode "magit-blame" (&optional arg))
(defvar magit-blame-mode)
;; For `magit-diff-show-or-scroll'
@@ -59,16 +63,13 @@
(pullreq &optional endpoints))
(declare-function forge--pullreq-ref "forge-pullreq" (pullreq))
;; For `magit-diff-wash-diff'
(declare-function ansi-color-apply-on-region "ansi-color" (begin end))
(declare-function ansi-color-apply-on-region "ansi-color")
(eval-when-compile
(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
@@ -94,10 +95,10 @@
(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.
Except in status buffers, diffs 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.
@@ -283,6 +284,20 @@ that many spaces. Otherwise, highlight neither."
:group 'magit-diff
:type 'boolean)
(defcustom magit-diff-extra-stat-arguments nil
"Additional arguments to be used alongside `--stat'.
A list of zero or more arguments or a function that takes no
argument and returns such a list. These arguments are allowed
here: `--stat-width', `--stat-name-width', `--stat-graph-width'
and `--compact-summary'. See the git-diff(1) manpage."
:package-version '(magit . "3.0.0")
:group 'magit-diff
:type '(radio (function-item magit-diff-use-window-width-as-stat-width)
function
(list string)
(const :tag "None" nil)))
;;;; File Diff
(defcustom magit-diff-buffer-file-locked t
@@ -821,15 +836,15 @@ and `:slant'."
;;; Section Classes
(defclass magit-file-section (magit-section)
((keymap :initform magit-file-section-map)
((keymap :initform 'magit-file-section-map)
(source :initform nil)
(header :initform nil)))
(defclass magit-module-section (magit-file-section)
((keymap :initform magit-hunk-section-map)))
((keymap :initform 'magit-hunk-section-map)))
(defclass magit-hunk-section (magit-section)
((keymap :initform magit-hunk-section-map)
((keymap :initform 'magit-hunk-section-map)
(refined :initform nil)
(combined :initform nil)
(from-range :initform nil)
@@ -865,6 +880,7 @@ and `:slant'."
("-x" "Disallow external diff drivers" "--no-ext-diff")
("-s" "Show stats" "--stat")
("=g" "Show signature" "--show-signature")
(5 "-R" "Reverse sides" "-R")
(5 magit-diff:--color-moved)
(5 magit-diff:--color-moved-ws)]
["Actions"
@@ -900,6 +916,8 @@ and `:slant'."
:if-derived magit-diff-mode)
("=g" "Show signature" "--show-signature"
:if-derived magit-diff-mode)
(5 "-R" "Reverse sides" "-R"
:if-derived magit-diff-mode)
(5 magit-diff:--color-moved)
(5 magit-diff:--color-moved-ws)]
[["Refresh"
@@ -951,12 +969,14 @@ and `:slant'."
:description "Detect renames"
:class 'transient-option
:argument "-M"
:allow-empty t
:reader 'transient-read-number-N+)
(transient-define-argument magit-diff:-C ()
:description "Detect copies"
:class 'transient-option
:argument "-C"
:allow-empty t
:reader 'transient-read-number-N+)
(transient-define-argument magit-diff:--diff-algorithm ()
@@ -1081,8 +1101,8 @@ If no DWIM context is found, nil is returned."
([* unstaged] 'unstaged)
([* staged] 'staged)
(unmerged 'unmerged)
(unpushed (oref it value))
(unpulled (oref it value))
(unpushed (magit-diff--range-to-endpoints (oref it value)))
(unpulled (magit-diff--range-to-endpoints (oref it value)))
(branch (let ((current (magit-get-current-branch))
(atpoint (oref it value)))
(if (equal atpoint current)
@@ -1095,9 +1115,17 @@ If no DWIM context is found, nil is returned."
(or current "HEAD")
atpoint))))
(commit (cons 'commit (oref it value)))
([file commit] (cons 'commit (oref (oref it parent) value)))
([hunk file commit]
(cons 'commit (oref (oref (oref it parent) parent) value)))
(stash (cons 'stash (oref it value)))
(pullreq (forge--pullreq-range (oref it value) t))))))
(defun magit-diff--range-to-endpoints (range)
(cond ((string-match "\\.\\.\\." range) (replace-match ".." nil nil range))
((string-match "\\.\\." range) (replace-match "..." nil nil range))
(t range)))
(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
@@ -1271,9 +1299,7 @@ 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
(atpoint (or mcommit
(thing-at-point 'git-revision t)
(magit-branch-or-commit-at-point)))
(`(,args ,files) (magit-show-commit--arguments)))
@@ -1308,11 +1334,12 @@ for a revision."
(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))))))))))
(when-let ((range (oref hunk to-range)))
(pcase-let* ((`(,beg ,len) 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)))
@@ -1399,12 +1426,12 @@ instead."
(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)))))
(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))))
(magit-diff-set-context (lambda (cur) (+ (or cur 0) count))))
(defun magit-diff-default-context ()
"Reset context for diff hunks to the default height."
@@ -1490,8 +1517,8 @@ The visited version depends on what changes the diff is about.
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."
Note that this command only works if point is inside a diff.
In other cases `magit-find-file' (which see) has to be used."
(interactive (list (magit-file-at-point t t) current-prefix-arg))
(magit-diff-visit-file--internal file nil
(if other-window
@@ -1658,11 +1685,13 @@ the Magit-Status buffer for DIRECTORY."
(not (< (point) (oref section content)))
(= (char-after (line-beginning-position)) ?-)))
(defvar magit-diff-visit-jump-to-change t)
(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)
(when (and magit-diff-visit-jump-to-change (< (point) content))
(goto-char content)
(re-search-forward "^[-+]"))
(+ (car (if goto-from from-range to-range))
@@ -1896,10 +1925,14 @@ Staging and applying changes is documented in info node
(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))
(cond
((string-match-p "\\(\\.\\.\\|\\^-\\)"
magit-buffer-range)
(format "Changes in %s" magit-buffer-range))
((member "-R" magit-buffer-diff-args)
(format "Changes from working tree to %s" magit-buffer-range))
(t
(format "Changes from %s to working tree" magit-buffer-range)))
(if (equal magit-buffer-typearg "--cached")
"Staged changes"
"Unstaged changes"))
@@ -1924,8 +1957,10 @@ Staging and applying changes is documented in info node
(defvar magit-diff-section-base-map
(let ((map (make-sparse-keymap)))
(define-key map (kbd "C-j") 'magit-diff-visit-worktree-file)
(define-key map [C-return] 'magit-diff-visit-worktree-file)
(define-key map (kbd "C-j") 'magit-diff-visit-worktree-file)
(define-key map (kbd "C-<return>") 'magit-diff-visit-worktree-file)
(define-key map (kbd "C-x 4 <return>") 'magit-diff-visit-file-other-window)
(define-key map (kbd "C-x 5 <return>") 'magit-diff-visit-file-other-frame)
(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)
@@ -1950,6 +1985,12 @@ Staging and applying changes is documented in info node
(defvar magit-hunk-section-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map magit-diff-section-base-map)
(let ((m (make-sparse-keymap)))
(define-key m (kbd "RET") 'magit-smerge-keep-current)
(define-key m (kbd "u") 'magit-smerge-keep-upper)
(define-key m (kbd "b") 'magit-smerge-keep-base)
(define-key m (kbd "l") 'magit-smerge-keep-lower)
(define-key map smerge-command-prefix m))
map)
"Keymap for `hunk' sections.")
@@ -2006,27 +2047,42 @@ Staging and applying changes is documented in info node
(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))
(pcase-let ((`(,cmd . ,args)
(-flatten args))
(magit-git-global-arguments
(remove "--literal-pathspecs" magit-git-global-arguments)))
;; As of Git 2.19.0, we need to generate diffs with
;; --ita-visible-in-index so that `magit-stage' can work with
;; intent-to-add files (see #4026). Cache the result for each
;; repo to avoid a `git version' call for every diff insertion.
(when (and (not (equal (car args) "merge-tree"))
(when (and (not (equal cmd "merge-tree"))
(pcase (magit-repository-local-get 'diff-ita-kludge-p 'unset)
(`unset
(let ((val (version<= "2.19.0" (magit-git-version))))
(magit-repository-local-set 'diff-ita-kludge-p val)
val))
(val val)))
(push "--ita-visible-in-index" (cdr args)))
(push "--ita-visible-in-index" args))
(setq args (magit-diff--maybe-add-stat-arguments args))
(when (cl-member-if (lambda (arg) (string-prefix-p "--color-moved" arg)) args)
(push "--color=always" (cdr args))
(push "--color=always" 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)))
(magit-git-wash #'magit-diff-wash-diffs cmd args)))
(defun magit-diff--maybe-add-stat-arguments (args)
(if (member "--stat" args)
(append (if (functionp magit-diff-extra-stat-arguments)
(funcall magit-diff-extra-stat-arguments)
magit-diff-extra-stat-arguments)
args)
args))
(defun magit-diff-use-window-width-as-stat-width ()
"Use the `window-width' as the value of `--stat-width'."
(when-let ((window (get-buffer-window (current-buffer) 'visible)))
(list (format "--stat-width=%d" (window-width window)))))
(defun magit-diff-wash-diffs (args &optional limit)
(run-hooks 'magit-diff-wash-diffs-hook)
@@ -2056,10 +2112,25 @@ section or a child thereof."
(defun magit-diff-wash-signature ()
(when (looking-at "^gpg: ")
(magit-insert-section (signature)
(while (looking-at "^gpg: ")
(forward-line))
(insert "\n"))))
(let (title end)
(save-excursion
(while (looking-at "^gpg: ")
(cond
((looking-at "^gpg: Good signature from")
(setq title (propertize
(buffer-substring (point) (line-end-position))
'face 'magit-signature-good)))
((looking-at "^gpg: Can't check signature")
(setq title (propertize
(buffer-substring (point) (line-end-position))
'face '(italic bold)))))
(forward-line))
(setq end (point-marker)))
(magit-insert-section (signature magit-buffer-revision title)
(when title
(magit-insert-heading title))
(goto-char end)
(insert "\n")))))
(defun magit-diff-wash-diffstat ()
(let (heading (beg (point)))
@@ -2136,7 +2207,7 @@ section or a child thereof."
((looking-at magit-diff-conflict-headline-re)
(let ((long-status (match-string 0))
(status "BUG")
file orig base modes)
file orig base)
(if (equal long-status "merged")
(progn (setq status long-status)
(setq long-status nil))
@@ -2161,52 +2232,79 @@ section or a child thereof."
(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 long-status)))
((looking-at
"^diff --\\(?:\\(git\\) \\(?:\\(.+?\\) \\2\\)?\\|\\(cc\\|combined\\) \\(.+\\)\\)")
(or file base) orig status nil nil nil long-status)))
;; The files on this line may be ambiguous due to whitespace.
;; That's okay. We can get their names from subsequent headers.
((looking-at "^diff --\
\\(?:\\(?1:git\\) \\(?:\\(?2:.+?\\) \\2\\)?\
\\|\\(?:cc\\|combined\\) \\(?3:.+\\)\\)")
(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)))))
(orig nil)
(file (or (match-string 2) (match-string 3)))
(header (list (buffer-substring-no-properties
(line-beginning-position) (1+ (line-end-position)))))
(modes nil)
(rename nil))
(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)))
(cond
((looking-at "old mode \\(?:[^\n]+\\)\nnew mode \\(?:[^\n]+\\)\n")
(setq modes (match-string 0)))
((looking-at "deleted file .+\n")
(setq status "deleted"))
((looking-at "new file .+\n")
(setq status "new file"))
((looking-at "rename from \\(.+\\)\nrename to \\(.+\\)\n")
(setq rename (match-string 0))
(setq orig (match-string 1))
(setq file (match-string 2))
(setq status "renamed"))
((looking-at "copy from \\(.+\\)\ncopy to \\(.+\\)\n")
(setq orig (match-string 1))
(setq file (match-string 2))
(setq status "new file"))
((looking-at "similarity index .+\n"))
((looking-at "dissimilarity index .+\n"))
((looking-at "index .+\n"))
((looking-at "--- \\(.+?\\)\t?\n")
(unless (equal (match-string 1) "/dev/null")
(setq orig (match-string 1))))
((looking-at "\\+\\+\\+ \\(.+?\\)\t?\n")
(unless (equal (match-string 1) "/dev/null")
(setq file (match-string 1))))
((looking-at "Binary files .+ and .+ differ\n"))
((looking-at "Binary files differ\n"))
;; TODO Use all combined diff extended headers.
((looking-at "mode .+\n"))
(t
(error "BUG: Unknown extended header: %S"
(buffer-substring (point) (line-end-position)))))
;; These headers are treated as some sort of special hunk.
(unless (or (string-prefix-p "old mode" (match-string 0))
(string-prefix-p "rename" (match-string 0)))
(push (match-string 0) header))
(magit-delete-match))
(setq header (mapconcat #'identity (nreverse header) ""))
(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))
;; KLUDGE `git-diff' ignores `--no-prefix' for new files and renames at
;; least. And `git-log' ignores `--no-prefix' when `-L' is used.
(when (or (and file orig
(string-prefix-p "a/" orig)
(string-prefix-p "b/" file))
(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)))))
(magit-diff-insert-file-section file orig status modes rename header)))))
(defun magit-diff-insert-file-section
(file orig status modes header &optional long-status)
(file orig status modes rename header &optional long-status)
(magit-insert-section section
(file file (or (equal status "deleted")
(derived-mode-p 'magit-status-mode)))
@@ -2222,9 +2320,13 @@ section or a child thereof."
(oset section source orig))
(oset section header header)
(when modes
(magit-insert-section (hunk)
(magit-insert-section (hunk '(chmod))
(insert modes)
(magit-insert-heading)))
(when rename
(magit-insert-section (hunk '(rename))
(insert rename)
(magit-insert-heading)))
(magit-wash-sequence #'magit-diff-wash-hunk)))
(defun magit-diff-wash-submodule ()
@@ -2243,7 +2345,7 @@ section or a child thereof."
(equal (match-string 1) module))
(magit-bind-match-strings (_module range rewind) nil
(magit-delete-line)
(while (looking-at "^ \\([<>]\\) \\(.+\\)$")
(while (looking-at "^ \\([<>]\\) \\(.*\\)$")
(magit-delete-line))
(when rewind
(setq range (replace-regexp-in-string "[^.]\\(\\.\\.\\)[^.]"
@@ -2293,7 +2395,7 @@ section or a child thereof."
(when (looking-at "^@\\{2,\\} \\(.+?\\) @\\{2,\\}\\(?: \\(.*\\)\\)?")
(let* ((heading (match-string 0))
(ranges (mapcar (lambda (str)
(mapcar (lambda (n) (string-to-number n))
(mapcar #'string-to-number
(split-string (substring str 1) ",")))
(split-string (match-string 1))))
(about (match-string 2))
@@ -2363,15 +2465,15 @@ Staging and applying changes is documented in info node
(magit-buffer-diff-files-suspended nil)))
(defun magit-revision-refresh-buffer ()
(setq magit-buffer-revision-hash (magit-rev-parse magit-buffer-revision))
(magit-set-header-line-format
(concat (capitalize (magit-object-type magit-buffer-revision))
(concat (magit-object-type magit-buffer-revision-hash)
" " 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)))
@@ -2420,8 +2522,7 @@ or a ref which is not a branch, then it inserts nothing."
(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))
(magit-process-git t "verify-tag" magit-buffer-revision))
(goto-char (point-max)))
(insert ?\n))))
@@ -2625,9 +2726,11 @@ or a ref which is not a branch, then it inserts nothing."
(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))))))))
(list gravatar-size rev
(point-marker)
align-to column))))))))
(defun magit-insert-revision-gravatar-cb (image rev marker align-to column)
(defun magit-insert-revision-gravatar-cb (image size rev marker align-to column)
(unless (eq image 'error)
(when-let ((buffer (marker-buffer marker)))
(with-current-buffer buffer
@@ -2641,10 +2744,13 @@ or a ref which is not a branch, then it inserts nothing."
(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)))
;; `image-property' wasn't added until 26.1.
(setcdr image (plist-put (cdr image) :ascent 'center))
(setcdr image (plist-put (cdr image) :relief 1))
(setcdr image (plist-put (cdr image) :scale 1))
(setcdr image (plist-put (cdr image) :height size))
(let ((top (list image '(slice 0.0 0.0 1.0 0.5)))
(bot (list image '(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))
@@ -2822,7 +2928,7 @@ Do not confuse this with `magit-diff-scope' (which see)."
(oref section children))
(magit-section-match [* file commit] section))
'committed
'undefined))
'undefined))
(t 'undefined))))
(cl-defun magit-diff-scope (&optional (section nil ssection) strict)
@@ -2866,8 +2972,7 @@ actually a `diff' but a `diffstat' section."
(`(file ,_ ,_ ,_) 'file)
(`(module t t nil) 'files)
(`(module ,_ ,_ ,_) 'file)
(`(,(or `staged `unstaged `untracked)
nil ,_ ,_) 'list)))))
(`(,(or `staged `unstaged `untracked) nil ,_ ,_) 'list)))))
(defun magit-diff-use-hunk-region-p ()
(and (region-active-p)
@@ -3144,7 +3249,8 @@ are highlighted."
(defun magit-diff-update-hunk-region (section)
"Highlight the hunk-internal region if any."
(when (eq (magit-diff-scope section t) 'region)
(when (and (eq (oref section type) 'hunk)
(eq (magit-diff-scope section t) 'region))
(magit-diff--make-hunk-overlay
(oref section start)
(1- (oref section content))
@@ -3249,11 +3355,15 @@ last (visual) lines of the region."
;;; Diff Extract
(defun magit-diff-file-header (section)
(defun magit-diff-file-header (section &optional no-rename)
(when (magit-hunk-section-p section)
(setq section (oref section parent)))
(when (magit-file-section-p section)
(oref section header)))
(and (magit-file-section-p section)
(let ((header (oref section header)))
(if no-rename
(replace-regexp-in-string
"^--- \\(.+\\)" (oref section value) header t t 1)
header))))
(defun magit-diff-hunk-region-header (section)
(let ((patch (magit-diff-hunk-region-patch section)))

View File

@@ -1,6 +1,6 @@
;;; magit-ediff.el --- Ediff extension for Magit -*- lexical-binding: t -*-
;; Copyright (C) 2010-2021 The Magit Project Contributors
;; Copyright (C) 2010-2022 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.
@@ -8,6 +8,8 @@
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; SPDX-License-Identifier: GPL-3.0-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)
@@ -99,6 +101,12 @@ tree at the time of stashing."
:group 'magit-ediff
:type 'boolean)
(defcustom magit-ediff-use-indirect-buffers nil
"Whether to use indirect buffers."
:package-version '(magit . "3.1.0")
:group 'magit-ediff
:type 'boolean)
;;; Commands
(defvar magit-ediff-previous-winconf nil)
@@ -155,6 +163,45 @@ conflicts, including those already resolved by Git, use
(let ((magit-ediff-previous-winconf smerge-ediff-windows))
(run-hooks 'magit-ediff-quit-hook)))))))
(defmacro magit-ediff-buffers (quit &rest spec)
(declare (indent 1))
(let ((fn (if (= (length spec) 3) 'ediff-buffers3 'ediff-buffers))
(char ?@)
get make kill)
(pcase-dolist (`(,g ,m) spec)
(let ((b (intern (format "buf%c" (cl-incf char)))))
(push `(,b ,g) get)
(push `(if ,b
(if magit-ediff-use-indirect-buffers
(prog1
(make-indirect-buffer
,b (generate-new-buffer-name (buffer-name ,b)) t)
(setq ,b nil))
,b)
,m)
make)
(push `(unless ,b
(ediff-kill-buffer-carefully
,(intern (format "ediff-buffer-%c" char))))
kill)))
(setq get (nreverse get))
(setq make (nreverse make))
(setq kill (nreverse kill))
`(magit-with-toplevel
(let ((conf (current-window-configuration))
,@get)
(,fn
,@make
(list (lambda ()
(setq-local
ediff-quit-hook
(list ,@(and quit (list quit))
(lambda ()
,@kill
(let ((magit-ediff-previous-winconf conf))
(run-hooks 'magit-ediff-quit-hook)))))))
',fn)))))
;;;###autoload
(defun magit-ediff-stage (file)
"Stage and unstage changes to FILE using Ediff.
@@ -164,43 +211,34 @@ FILE has to be relative to the top directory of the repository."
(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)))
(let* ((bufA (magit-get-revision-buffer "HEAD" file))
(bufB (magit-get-revision-buffer "{index}" file))
(lockB (and bufB (buffer-local-value 'buffer-read-only bufB)))
(bufC (get-file-buffer file))
;; Use the same encoding for all three buffers or we
;; may end up changing the file in an unintended way.
(bufC* (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))))
(buffer-local-value 'buffer-file-coding-system bufC*))
(bufA* (magit-find-file-noselect-1 "HEAD" file t))
(bufB* (magit-find-file-index-noselect file t)))
(setf (buffer-local-value 'buffer-read-only bufB*) nil)
(magit-ediff-buffers
(lambda ()
(when (buffer-live-p ediff-buffer-B)
(when lockB
(setf (buffer-local-value 'buffer-read-only bufB) t))
(when (buffer-modified-p ediff-buffer-B)
(with-current-buffer ediff-buffer-B
(magit-update-index))))
(when (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)))))
(bufA bufA*)
(bufB bufB*)
(bufC bufC*)))))
;;;###autoload
(defun magit-ediff-compare (revA revB fileA fileB)
@@ -220,30 +258,11 @@ range)."
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))))
(magit-ediff-buffers nil
((if revA (magit-get-revision-buffer revA fileA) (get-file-buffer fileA))
(if revA (magit-find-file-noselect revA fileA) (find-file-noselect fileA)))
((if revB (magit-get-revision-buffer revB fileB) (get-file-buffer fileB))
(if revB (magit-find-file-noselect revB fileB) (find-file-noselect fileB)))))
(defun magit-ediff-compare--read-revisions (&optional arg mbase)
(let ((input (or arg (magit-diff-read-range-or-commit
@@ -358,21 +377,11 @@ FILE must be relative to the top directory of the repository."
(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)))
(magit-ediff-buffers nil
((magit-get-revision-buffer "HEAD" file)
(magit-find-file-noselect "HEAD" file))
((get-buffer (concat file ".~{index}~"))
(magit-find-file-index-noselect file t))))
;;;###autoload
(defun magit-ediff-show-unstaged (file)
@@ -386,22 +395,11 @@ FILE must be relative to the top directory of the repository."
(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))))
(magit-ediff-buffers nil
((get-buffer (concat file ".~{index}~"))
(magit-find-file-index-noselect file t))
((get-file-buffer file)
(find-file-noselect file))))
;;;###autoload
(defun magit-ediff-show-working-tree (file)
@@ -411,22 +409,11 @@ FILE must be relative to the top directory of the repository."
(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))))
(magit-ediff-buffers nil
((magit-get-revision-buffer "HEAD" file)
(magit-find-file-noselect "HEAD" file))
((get-file-buffer file)
(find-file-noselect file))))
;;;###autoload
(defun magit-ediff-show-commit (commit)
@@ -452,27 +439,13 @@ stash that were staged."
(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-buffers nil
((magit-get-revision-buffer revA fileA)
(magit-find-file-noselect revA fileA))
((magit-get-revision-buffer revB fileB)
(magit-find-file-noselect revB fileB))
((magit-get-revision-buffer revC fileC)
(magit-find-file-noselect revC fileC)))
(magit-ediff-compare revA revC fileA fileC))))
(defun magit-ediff-cleanup-auxiliary-buffers ()

View File

@@ -1,10 +1,15 @@
;;; magit-extras.el --- additional functionality for Magit -*- lexical-binding: t -*-
;; Copyright (C) 2008-2021 The Magit Project Contributors
;; Copyright (C) 2008-2022 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 <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; SPDX-License-Identifier: GPL-3.0-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)
@@ -24,11 +29,10 @@
;;; Code:
(eval-when-compile
(require 'subr-x))
(require 'magit)
(declare-function change-log-insert-entries "add-log" (changelogs))
(declare-function diff-add-log-current-defuns "diff-mode" ())
(declare-function dired-read-shell-command "dired-aux" (prompt arg files))
;; For `magit-project-status'.
(declare-function project-root "project" (project))
@@ -61,8 +65,7 @@
(defun magit-run-git-gui ()
"Run `git gui' for the current git repository."
(interactive)
(magit-with-toplevel
(magit-process-file magit-git-executable nil 0 nil "gui")))
(magit-with-toplevel (magit-process-git 0 "gui")))
;;;###autoload
(defun magit-run-git-gui-blame (commit filename &optional linenum)
@@ -84,10 +87,10 @@ blame to center around the line point is on."
(magit-file-relative-name buffer-file-name)))
(line-number-at-pos)))))
(magit-with-toplevel
(apply #'magit-process-file magit-git-executable nil 0 nil "gui" "blame"
`(,@(and linenum (list (format "--line=%d" linenum)))
,commit
,filename))))
(magit-process-git 0 "gui" "blame"
(and linenum (list (format "--line=%d" linenum)))
commit
filename)))
;;;###autoload
(defun magit-run-gitk ()
@@ -142,13 +145,23 @@ like pretty much every other keymap:
(interactive)
(magit-status-setup-buffer (project-root (project-current t))))
(defvar magit-bind-magit-project-status t
"Whether to bind \"m\" to `magit-project-status' in `project-prefix-map'.
If so, then an entry is added to `project-switch-commands' as
well. If you want to use another key, then you must set this
to nil before loading Magit to prevent \"m\" from being bound.")
(with-eval-after-load 'project
;; Only more recent versions of project.el have `project-prefix-map' and
;; `project-switch-commands', though project.el is available in Emacs 25.
(when (boundp 'project-prefix-map)
(define-key project-prefix-map "m" #'magit-project-status))
(when (boundp 'project-switch-commands)
(add-to-list 'project-switch-commands '(?m "Magit" magit-status))))
(when (and magit-bind-magit-project-status
(boundp 'project-prefix-map)
;; Only modify if it hasn't already been modified.
(equal project-switch-commands
(eval (car (get 'project-switch-commands 'standard-value))
t)))
(define-key project-prefix-map "m" #'magit-project-status)
(add-to-list 'project-switch-commands '(magit-project-status "Magit") t)))
;;;###autoload
(defun magit-dired-jump (&optional other-window)
@@ -183,6 +196,21 @@ is no file at point, then instead visit `default-directory'."
magit-log-buffer-file-locked))
(magit--not-inside-repository-error)))
;;;###autoload
(defun magit-dired-am-apply-patches (repo &optional arg)
"In Dired, apply the marked (or next ARG) files as patches.
If inside a repository, then apply in that. Otherwise prompt
for a repository."
(interactive (list (or (magit-toplevel)
(magit-read-repository t))
current-prefix-arg))
;; Note: The ERROR argument of `dired-get-marked-files' isn't
;; available until Emacs 27.
(let ((files (or (dired-get-marked-files nil arg)
(user-error "No files specified"))))
(magit-status-setup-buffer repo)
(magit-am-apply-patches files)))
;;;###autoload
(defun magit-do-async-shell-command (file)
"Open FILE with `dired-do-async-shell-command'.
@@ -413,7 +441,7 @@ Otherwise the author dates are also changed."
:type 'boolean)
;;;###autoload
(defun magit-reshelve-since (rev)
(defun magit-reshelve-since (rev keyid)
"Change the author and committer dates of the commits since REV.
Ask the user for the first reachable commit whose dates should
@@ -423,8 +451,14 @@ 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))
be used on highly rearranged and unpublished history.
If KEYID is non-nil, then use that to sign all reshelved commits.
Interactively use the value of the \"--gpg-sign\" option in the
list returned by `magit-rebase-arguments'."
(interactive (list nil
(transient-arg-value "--gpg-sign="
(magit-rebase-arguments))))
(let* ((current (or (magit-get-current-branch)
(user-error "Refusing to reshelve detached head")))
(backup (concat "refs/original/refs/heads/" current)))
@@ -434,7 +468,9 @@ be used on highly rearranged and unpublished history."
(not (magit-y-or-n-p
(format "Backup ref %s already exists. Override? " backup))))
(user-error "Abort"))
(magit-log-select 'magit-reshelve-since
(magit-log-select
(lambda (rev)
(magit-reshelve-since rev keyid))
"Type %p on a commit to reshelve it and the commits above it,"))
(t
(cl-flet ((adjust (time offset)
@@ -474,7 +510,11 @@ be used on highly rearranged and unpublished history."
(format "export GIT_COMMITTER_DATE=\"%s\";;" date))
(cl-incf date 60)))
(magit-git-lines "rev-list" "--reverse" range)
" "))
" "))
(and keyid
(list "--commit-filter"
(format "git commit-tree --gpg-sign=%s \"$@\";"
keyid)))
range "--"))
(set-process-sentinel
magit-this-process
@@ -491,7 +531,9 @@ be used on highly rearranged and unpublished history."
(defvar magit-revision-stack nil)
(defcustom magit-pop-revision-stack-format
'("[%N: %h] " "%N: %H\n %s\n" "\\[\\([0-9]+\\)[]:]")
'("[%N: %h] "
"%N: %cs %H\n %s\n"
"\\[\\([0-9]+\\)[]:]")
"Control how `magit-pop-revision-stack' inserts a revision.
The command `magit-pop-revision-stack' inserts a representation
@@ -522,7 +564,7 @@ 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")
:package-version '(magit . "3.2.0")
:group 'magit-commands
:type '(list (choice (string :tag "Insert at point format")
(cons (string :tag "Insert at point format")
@@ -726,6 +768,55 @@ abbreviated revision to the `kill-ring' and the
(push (list rev default-directory) magit-revision-stack)
(kill-new (message "%s" rev))))))
;;; Buffer Switching
;;;###autoload
(defun magit-display-repository-buffer (buffer)
"Display a Magit buffer belonging to the current Git repository.
The buffer is displayed using `magit-display-buffer', which see."
(interactive (list (magit--read-repository-buffer
"Display magit buffer: ")))
(magit-display-buffer buffer))
;;;###autoload
(defun magit-switch-to-repository-buffer (buffer)
"Switch to a Magit buffer belonging to the current Git repository."
(interactive (list (magit--read-repository-buffer
"Switch to magit buffer: ")))
(switch-to-buffer buffer))
;;;###autoload
(defun magit-switch-to-repository-buffer-other-window (buffer)
"Switch to a Magit buffer belonging to the current Git repository."
(interactive (list (magit--read-repository-buffer
"Switch to magit buffer in another window: ")))
(switch-to-buffer-other-window buffer))
;;;###autoload
(defun magit-switch-to-repository-buffer-other-frame (buffer)
"Switch to a Magit buffer belonging to the current Git repository."
(interactive (list (magit--read-repository-buffer
"Switch to magit buffer in another frame: ")))
(switch-to-buffer-other-frame buffer))
(defun magit--read-repository-buffer (prompt)
(if-let ((topdir (magit-rev-parse-safe "--show-toplevel")))
(read-buffer
prompt (magit-get-mode-buffer 'magit-status-mode) t
(pcase-lambda (`(,_ . ,buf))
(and buf
(with-current-buffer buf
(and (or (derived-mode-p 'magit-mode
'magit-repolist-mode
'magit-submodule-list-mode
'git-rebase-mode)
(and buffer-file-name
(string-match-p git-commit-filename-regexp
buffer-file-name)))
(equal (magit-rev-parse-safe "--show-toplevel")
topdir))))))
(user-error "Not inside a Git repository")))
;;; Miscellaneous
;;;###autoload

View File

@@ -1,6 +1,6 @@
;;; magit-fetch.el --- download objects and refs -*- lexical-binding: t -*-
;; Copyright (C) 2008-2021 The Magit Project Contributors
;; Copyright (C) 2008-2022 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.
@@ -8,6 +8,8 @@
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; SPDX-License-Identifier: GPL-3.0-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)
@@ -29,14 +31,11 @@
(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))
(defvar magit-fetch-modules-jobs nil)
(make-obsolete-variable
'magit-fetch-modules-jobs
"invoke `magit-fetch-modules' with a prefix argument instead."
"Magit 3.0.0")
;;; Commands
@@ -165,22 +164,39 @@ removed on the respective remote."
(run-hooks 'magit-credential-hook)
(magit-run-git-async "remote" "update"))
;;;###autoload
(defun magit-fetch-modules (&optional all)
;;;###autoload (autoload 'magit-fetch-modules "magit-fetch" nil t)
(transient-define-prefix magit-fetch-modules (&optional transient args)
"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"))))
Fetching is done using \"git fetch --recurse-submodules\", which
means that the super-repository and recursively all submodules
are also fetched.
To set and potentially save other arguments invoke this command
with a prefix argument."
:man-page "git-fetch"
:value (list "--verbose"
(cond (magit-fetch-modules-jobs
(format "--jobs=%s" magit-fetch-modules-jobs))
(t "--jobs=4")))
["Arguments"
("-v" "verbose" "--verbose")
("-a" "all remotes" "--all")
("-j" "number of jobs" "--jobs=" :reader transient-read-number-N+)]
["Action"
("m" "fetch modules" magit-fetch-modules)]
(interactive (if current-prefix-arg
(list t)
(list nil (transient-args 'magit-fetch-modules))))
(if transient
(transient-setup 'magit-fetch-modules)
(let ((git-version (magit-git-version)))
(when (version< git-version "2.8.0")
(when-let ((value (transient-arg-value "--jobs=" args)))
(message "Dropping --jobs; not supported by Git v%s" git-version)
(setq args (remove (format "--jobs=%s" value) args)))))
(magit-with-toplevel
(magit-run-git-async "fetch" "--recurse-submodules" args))))
;;; _
(provide 'magit-fetch)

View File

@@ -1,6 +1,6 @@
;;; magit-files.el --- finding files -*- lexical-binding: t -*-
;; Copyright (C) 2010-2021 The Magit Project Contributors
;; Copyright (C) 2010-2022 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.
@@ -8,6 +8,8 @@
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; SPDX-License-Identifier: GPL-3.0-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)
@@ -30,9 +32,6 @@
;;; Code:
(eval-when-compile
(require 'subr-x))
(require 'magit)
;;; Find Blob
@@ -206,21 +205,25 @@ is done using `magit-find-index-noselect'."
(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"))
(let ((index (make-temp-name (magit-git-dir "magit-update-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))
(unwind-protect
(progn
(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)
"--" (magit-convert-filename-for-git index))
file)))
(ignore-errors (delete-file index)))
(set-buffer-modified-p nil)
(when magit-wip-after-apply-mode
(magit-wip-commit-after-apply (list file) " after un-/stage")))
@@ -248,7 +251,7 @@ reading the FILENAME."
(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.
"Edit a file located in the current repo'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
@@ -264,7 +267,7 @@ directory, while reading the FILENAME."
(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.
"Edit a file located in the current repo'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
@@ -297,7 +300,8 @@ to `magit-dispatch'."
("g" "Status" magit-status-here)]
[("L" "Log..." magit-log)
("l" "Log" magit-log-buffer-file)
("t" "Trace" magit-log-trace-definition)]
("t" "Trace" magit-log-trace-definition)
(7 "M" "Merged" magit-log-merged)]
[("B" "Blame..." magit-blame)
("b" "Blame" magit-blame-addition)
("r" "...removal" magit-blame-removal)
@@ -314,7 +318,7 @@ to `magit-dispatch'."
(5 "C-c c" "Checkout file" magit-file-checkout)]]
(interactive)
(transient-setup
(if (or buffer-file-name magit-buffer-file-name)
(if (magit-file-relative-name)
'magit-file-dispatch
'magit-dispatch)))

View File

@@ -1,6 +1,6 @@
;;; magit-git.el --- Git functionality -*- lexical-binding: t -*-
;; Copyright (C) 2010-2021 The Magit Project Contributors
;; Copyright (C) 2010-2022 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.
@@ -8,6 +8,8 @@
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; SPDX-License-Identifier: GPL-3.0-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)
@@ -27,12 +29,6 @@
;;; Code:
(require 'cl-lib)
(require 'dash)
(eval-when-compile
(require 'subr-x))
(require 'magit-utils)
(require 'magit-section)
@@ -57,7 +53,9 @@
;; 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-file "magit-process"
(process &optional infile buffer display &rest args))
(declare-function magit-process-git "magit-process" (destination &rest args))
(declare-function magit-process-insert-section "magit-process"
(pwd program args &optional errcode errlog))
(defvar magit-this-error)
@@ -66,7 +64,12 @@
;; From later in `magit-git'.
(defvar magit-tramp-process-environment nil)
;; From `magit-blame'.
(declare-function magit-current-blame-chunk "magit-blame"
(&optional type noerror))
(eval-when-compile
(cl-pushnew 'orig-rev eieio--known-slot-names)
(cl-pushnew 'number eieio--known-slot-names))
;;; Git implementations
@@ -74,12 +77,12 @@
(defvar magit-inhibit-libgit nil
"Whether to inhibit the use of libgit.")
(defvar magit--libgit-available-p eieio-unbound
(defvar magit--libgit-available-p 'unknown
"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)
(if (eq magit--libgit-available-p 'unknown)
(setq magit--libgit-available-p
(and module-file-suffix
(let ((libgit (locate-library "libgit")))
@@ -131,12 +134,9 @@ 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 where we would otherwise end up using 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)
;; Avoid the wrappers "cmd/git.exe" and "cmd/git.cmd",
;; which are much slower than using "bin/git.exe" directly.
(--when-let (executable-find "git")
(ignore-errors
;; Git for Windows 2.x provides cygpath so we can
@@ -163,8 +163,21 @@ successfully.")
(setcdr hack-entry path-hack)
(push (cons core-exe path-hack) magit-git-w32-path-hack))
core-exe))))
(and (eq system-type 'darwin)
(executable-find "git"))
"git")
"The Git executable used by Magit."
"The Git executable used by Magit on the local host.
On remote machines `magit-remote-git-executable' is used instead."
:package-version '(magit . "3.2.0")
:group 'magit-process
:type 'string)
(defcustom magit-remote-git-executable "git"
"The Git executable used by Magit on remote machines.
On the local host `magit-git-executable' is used instead.
Consider customizing `tramp-remote-path' instead of this
option."
:package-version '(magit . "3.2.0")
:group 'magit-process
:type 'string)
@@ -210,8 +223,9 @@ 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.")
permanently, that would negatively affect performance.
Also see `magit-process-extreme-logging'.")
(defcustom magit-prefer-remote-upstream nil
"Whether to favor remote branches when reading the upstream branch.
@@ -227,6 +241,20 @@ that change the upstream and many that create new branches."
:group 'magit-commands
:type 'boolean)
(defcustom magit-list-refs-namespaces
'("refs/heads"
"refs/remotes"
"refs/tags"
"refs/pullreqs")
"List of ref namespaces considered when reading a ref.
This 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."
:package-version '(magit . "3.1.0")
:group 'magit-commands
:type '(repeat string))
(defcustom magit-list-refs-sortby nil
"How to sort the ref collection in the prompt.
@@ -310,6 +338,14 @@ as for that macro."
(setq-local process-environment ,p)
,@body))))
(defsubst magit-git-executable ()
"Return value of `magit-git-executable' or `magit-remote-git-executable'.
The variable is chosen depending on whether `default-directory'
is remote."
(if (file-remote-p default-directory)
magit-remote-git-executable
magit-git-executable))
(defun magit-process-git-arguments (args)
"Prepare ARGS for a function that invokes Git.
@@ -332,8 +368,7 @@ to do the following.
(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)))
(magit-process-git nil args))
(defun magit-git-success (&rest args)
"Execute Git with ARGS, returning t if its exit code is 0."
@@ -353,8 +388,7 @@ This is an experimental replacement for `magit-git-string', and
still subject to major changes."
(magit--with-refresh-cache (cons default-directory args)
(magit--with-temp-process-buffer
(and (zerop (apply #'magit-process-file magit-git-executable nil t nil
(magit-process-git-arguments args)))
(and (zerop (magit-process-git t args))
(not (bobp))
(progn
(goto-char (point-min))
@@ -374,8 +408,7 @@ still subject to major changes. Also see `magit-git-string-p'."
(list default-directory 'magit-git-string-ng args)
(magit--with-temp-process-buffer
(let* ((args (magit-process-git-arguments args))
(status (apply #'magit-process-file magit-git-executable
nil t nil args)))
(status (magit-process-git t args)))
(if (zerop status)
(and (not (bobp))
(progn
@@ -401,8 +434,7 @@ ignore `magit-git-debug'."
(setq args (-flatten args))
(magit--with-refresh-cache (cons default-directory args)
(magit--with-temp-process-buffer
(apply #'magit-process-file magit-git-executable nil (list t nil) nil
(magit-process-git-arguments args))
(magit-process-git (list t nil) args)
(unless (bobp)
(goto-char (point-min))
(buffer-substring-no-properties (point) (line-end-position))))))
@@ -412,8 +444,7 @@ ignore `magit-git-debug'."
(setq args (-flatten args))
(magit--with-refresh-cache (cons default-directory args)
(magit--with-temp-process-buffer
(apply #'magit-process-file magit-git-executable nil (list t nil) nil
(magit-process-git-arguments args))
(magit-process-git (list t nil) args)
(buffer-substring-no-properties (point-min) (point-max)))))
(define-error 'magit-invalid-git-boolean "Not a Git boolean")
@@ -425,7 +456,7 @@ 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))))
(output (signal 'magit-invalid-git-boolean (list output)))))
(defun magit-git-false (&rest args)
"Execute Git with ARGS, returning t if it prints \"false\".
@@ -434,7 +465,22 @@ 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))))
(output (signal 'magit-invalid-git-boolean (list output)))))
(defun magit-git-config-p (variable &optional default)
"Return the boolean value of the Git variable VARIABLE.
VARIABLE has to be specified as a string. Return DEFAULT (which
defaults to nil) if VARIABLE is unset. If VARIABLE's value isn't
a boolean, then raise an error."
(let ((args (list "config" "--bool" "--default" (if default "true" "false")
variable)))
(magit--with-refresh-cache (cons default-directory args)
(magit--with-temp-process-buffer
(let ((status (magit-process-git t args))
(output (buffer-substring (point-min) (1- (point-max)))))
(if (zerop status)
(equal output "true")
(signal 'magit-invalid-git-boolean (list output))))))))
(defun magit-git-insert (&rest args)
"Execute Git with ARGS, inserting its output at point.
@@ -447,8 +493,7 @@ add a section in the respective process buffer."
(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)))
(let ((exit (magit-process-git (list t log) args)))
(when (> exit 0)
(let ((msg "Git failed"))
(when (file-exists-p log)
@@ -466,8 +511,7 @@ add a section in the respective process buffer."
(message "%s" msg)))
exit))
(ignore-errors (delete-file log))))
(apply #'magit-process-file magit-git-executable
nil (list t nil) nil args)))
(magit-process-git (list t nil) args)))
(defun magit--locate-error-message ()
(goto-char (point-max))
@@ -542,8 +586,8 @@ call function WASHER with ARGS as its sole argument."
(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))
(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"))
@@ -569,11 +613,13 @@ call function WASHER with ARGS as its sole argument."
(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."
"Return the boolean value of the Git variable specified by KEYS.
Also see `magit-git-config-p'."
(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"))))
(equal (if magit--refresh-cache
(car (last (magit-config-get-from-cached-list key)))
(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."
@@ -752,13 +798,27 @@ returning the truename."
(magit--not-inside-repository-error)))))
(define-error 'magit-outside-git-repo "Not inside Git repository")
(define-error 'magit-corrupt-git-config "Corrupt Git configuration")
(define-error 'magit-git-executable-not-found
"Git executable cannot be found (see https://magit.vc/goto/e6a78ed2)")
(defun magit--assert-usable-git ()
(if (not (executable-find (magit-git-executable)))
(signal 'magit-git-executable-not-found (magit-git-executable))
(let ((magit-git-debug
(lambda (err)
(signal 'magit-corrupt-git-config
(format "%s: %s" default-directory err)))))
;; This should always succeed unless there's a corrupt config
;; (or at least a similarly severe failing state). Note that
;; git-config's --default is avoided because it's not available
;; until Git 2.18.
(magit-git-string "config" "--get-color" "" "reset"))
nil))
(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)))
(magit--assert-usable-git)
(signal 'magit-outside-git-repo default-directory))
(defun magit-inside-gitdir-p (&optional noerror)
"Return t if `default-directory' is below the repository directory.
@@ -959,15 +1019,18 @@ Sorted from longest to shortest CYGWIN name."
(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."
1. If it's a absolute filename, then pass through `expand-file-name'
to replace things such as \"~/\" that Git does not understand.
2. If it's a remote filename, then remove the remote part.
3. 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))
(let ((expanded (expand-file-name filename)))
(or (file-remote-p expanded 'localname)
expanded)))
filename))
(defun magit-decode-git-path (path)
@@ -1191,9 +1254,11 @@ Git."
(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))))
(when-let ((name (magit-rev-name rev "refs/tags/*")))
(when (string-suffix-p "^0" name)
(setq name (substring name 0 -2)))
(and (or lax (not (string-match-p "[~^]" name)))
(substring name 5))))
(defun magit-ref-abbrev (refname)
"Return an unambiguous abbreviation of REFNAME."
@@ -1247,7 +1312,7 @@ to, or to some other symbolic-ref that points to the same ref."
(magit-ref-equal a b)))))
(defun magit-headish ()
"Return \"HEAD\" or if that doesn't exist the hash of the empty tree."
"Return the `HEAD' or if that doesn't exist the hash of the empty tree."
(if (magit-no-commit-p)
(magit-git-string "mktree")
"HEAD"))
@@ -1289,15 +1354,16 @@ to, or to some other symbolic-ref that points to the same ref."
(defun magit-commit-at-point ()
(or (magit-section-value-if 'commit)
(thing-at-point 'git-revision t)
(when-let ((chunk (magit-current-blame-chunk 'addition t)))
(oref chunk orig-rev))
(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
(or (magit-section-case
(branch (magit-ref-maybe-qualify (oref it value)))
(commit (or (magit--painted-branch-at-point)
(let ((rev (oref it value)))
@@ -1309,6 +1375,10 @@ to, or to some other symbolic-ref that points to the same ref."
(magit-ref-p (format "refs/pullreqs/%s"
(oref (oref it value) number))))))
(thing-at-point 'git-revision t)
(when-let ((chunk (magit-current-blame-chunk 'addition t)))
(oref chunk orig-rev))
(and magit-buffer-file-name
magit-buffer-refname)
(and (derived-mode-p 'magit-stash-mode
'magit-merge-preview-mode
'magit-revision-mode)
@@ -1325,7 +1395,7 @@ to, or to some other symbolic-ref that points to the same ref."
(defun magit-remote-at-point ()
(magit-section-case
(remote (oref it value))
(branch (magit-section-parent-value it))))
([branch remote] (magit-section-parent-value it))))
(defun magit-module-at-point (&optional predicate)
(when (magit-section-match 'magit-module-section)
@@ -1383,7 +1453,7 @@ remote-tracking branch 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 the name of an existing local or
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."
(magit--with-refresh-cache (list 'magit-get-upstream-branch branch)
@@ -1445,7 +1515,7 @@ according to the branch type."
(when-let ((remotes (magit-list-remotes))
(remote (if (= (length remotes) 1)
(car remotes)
(car (member "origin" remotes)))))
(magit-primary-remote))))
(magit--propertize-face remote 'magit-branch-remote))))
(defun magit-get-push-remote (&optional branch)
@@ -1478,11 +1548,36 @@ according to the branch type."
(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)))))
(when-let ((main (magit-main-branch)))
(magit-get-remote main))
(magit-primary-remote)
(car (magit-list-remotes))))
(defvar magit-primary-remote-names
'("upstream" "origin"))
(defun magit-primary-remote ()
"Return the primary remote.
The primary remote is the remote that tracks the repository that
other repositories are forked from. It often is called \"origin\"
but because many people name their own fork \"origin\", using that
term would be ambiguous. Likewise we avoid the term \"upstream\"
because a branch's @{upstream} branch may be a local branch or a
branch from a remote other than the primary remote.
If a remote exists whose name matches `magit.primaryRemote', then
that is considered the primary remote. If no remote by that name
exists, then remotes in `magit-primary-remote-names' are tried in
order and the first remote from that list that actually exists in
the current repository is considered its primary remote."
(let ((remotes (magit-list-remotes)))
(seq-find (lambda (name)
(member name remotes))
(delete-dups
(delq nil
(cons (magit-get "magit.primaryRemote")
magit-primary-remote-names))))))
(defun magit-branch-merged-p (branch &optional target)
"Return non-nil if BRANCH is merged into its upstream and TARGET.
@@ -1574,9 +1669,6 @@ where COMMITS is the number of commits in TAG but not in REV."
(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.
@@ -1585,7 +1677,7 @@ 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\".
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'"
@@ -1636,7 +1728,7 @@ SORTBY is a key or list of keys to pass to the `--sort' flag of
(defun magit-list-branches-pointing-at (commit)
(let ((re (format "\\`%s refs/\\(heads\\|remotes\\)/\\(.*\\)\\'"
(magit-rev-verify commit))))
(magit-rev-verify commit))))
(--keep (and (string-match re it)
(let ((name (match-string 2 it)))
(and (not (string-suffix-p "HEAD" name))
@@ -1732,14 +1824,23 @@ PATH has to be relative to the super-repository."
(magit-git-string "submodule--helper" "name" path))
(defun magit-list-worktrees ()
(let (worktrees worktree)
(let ((remote (file-remote-p default-directory))
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))
(let ((path (substring line 9)))
(when remote
(setq path (concat remote path)))
;; If the git directory is separate from the main
;; worktree, then "git worktree" returns the git
;; directory instead of the worktree, which isn't
;; what it is supposed to do and not what we want.
(setq path (magit-toplevel path))
(setq worktree (list path nil nil nil))
(push worktree worktrees)))
((string-equal line "bare")
(let* ((default-directory (car worktree))
(wt (and (not (magit-get-boolean "core.bare"))
@@ -1786,6 +1887,27 @@ PATH has to be relative to the super-repository."
(defun magit-remote-p (string)
(car (member string (magit-list-remotes))))
(defvar magit-main-branch-names
;; These are the names that Git suggests
;; if `init.defaultBranch' is undefined.
'("main" "master" "trunk" "development"))
(defun magit-main-branch ()
"Return the main branch.
If a branch exists whose name matches `init.defaultBranch', then
that is considered the main branch. If no branch by that name
exists, then the branch names in `magit-main-branch-names' are
tried in order. The first branch from that list that actually
exists in the current repository is considered its main branch."
(let ((branches (magit-list-local-branch-names)))
(seq-find (lambda (name)
(member name branches))
(delete-dups
(delq nil
(cons (magit-get "init.defaultBranch")
magit-main-branch-names))))))
(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)."
@@ -1840,7 +1962,7 @@ Return a list of two integers: (A>B B>A)."
(magit--with-temp-process-buffer
(magit-process-file
shell-file-name nil '(t nil) nil shell-command-switch
(let ((exec (shell-quote-argument magit-git-executable)))
(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)))))
@@ -2092,12 +2214,23 @@ and this option only controls what face is used.")
(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))))
(and (>= (length text) 7)
(string-match-p "[a-z]" text)
(magit-commit-p text)
text))))
;;; Completion
(defvar magit-revision-history nil)
(defun magit--minibuf-default-add-commit ()
(let ((fn minibuffer-default-add-function))
(lambda ()
(if-let ((commit (with-selected-window (minibuffer-selected-window)
(magit-commit-at-point))))
(cons commit (delete commit (funcall fn)))
(funcall fn)))))
(defun magit-read-branch (prompt &optional secondary-default)
(magit-completing-read prompt (magit-list-branch-names)
nil t nil 'magit-revision-history
@@ -2106,12 +2239,13 @@ and this option only controls what face is used.")
(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")))
(let ((minibuffer-default-add-function (magit--minibuf-default-add-commit)))
(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
@@ -2124,10 +2258,12 @@ and this option only controls what face is used.")
(magit-get-current-branch))))
(defun magit-read-range (prompt &optional default)
(magit-completing-read-multiple prompt
(magit-list-refnames)
"\\.\\.\\.?"
default 'magit-revision-history))
(let ((minibuffer-default-add-function (magit--minibuf-default-add-commit))
(crm-separator "\\.\\.\\.?"))
(magit-completing-read-multiple*
(concat prompt ": ")
(magit-list-refnames)
nil nil nil 'magit-revision-history default nil t)))
(defun magit-read-remote-branch
(prompt &optional remote default local-branch require-match)
@@ -2158,7 +2294,8 @@ and this option only controls what face is used.")
(magit-get-current-branch))))
(defun magit-read-local-branch-or-commit (prompt)
(let ((choices (nconc (magit-list-local-branch-names)
(let ((minibuffer-default-add-function (magit--minibuf-default-add-commit))
(choices (nconc (magit-list-local-branch-names)
(magit-list-special-refnames)))
(commit (magit-commit-at-point)))
(when commit
@@ -2166,7 +2303,7 @@ and this option only controls what face is used.")
(or (magit-completing-read prompt choices
nil nil nil 'magit-revision-history
(or (magit-local-branch-at-point) commit))
(user-error "Nothing selected"))))
(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)
@@ -2191,7 +2328,8 @@ and this option only controls what face is used.")
(defun magit-read-other-branch-or-commit
(prompt &optional exclude secondary-default)
(let* ((current (magit-get-current-branch))
(let* ((minibuffer-default-add-function (magit--minibuf-default-add-commit))
(current (magit-get-current-branch))
(atpoint (magit-branch-or-commit-at-point))
(exclude (or exclude current))
(default (or (and (not (equal atpoint exclude))
@@ -2248,9 +2386,10 @@ out. Only existing branches can be selected."
(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)))
(when-let ((main (magit-main-branch)))
(let ((r (car (member (concat "origin/" main) branches)))
(l (car (member main 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)

View File

@@ -1,6 +1,6 @@
;;; magit-gitignore.el --- intentionally untracked files -*- lexical-binding: t -*-
;; Copyright (C) 2008-2021 The Magit Project Contributors
;; Copyright (C) 2008-2022 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.
@@ -8,6 +8,8 @@
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; SPDX-License-Identifier: GPL-3.0-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)
@@ -27,9 +29,6 @@
;;; Code:
(eval-when-compile
(require 'subr-x))
(require 'magit)
;;; Transient
@@ -71,8 +70,8 @@ repository. Also stage the file."
;;;###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
"Add the Git ignore RULE to a \".gitignore\" file in DIRECTORY.
Prompt 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."
@@ -81,7 +80,7 @@ Also stage the file."
(magit-with-toplevel
(let ((file (expand-file-name ".gitignore" directory)))
(magit--gitignore rule file)
(magit-run-git "add" file))))
(magit-run-git "add" (magit-convert-filename-for-git file)))))
;;;###autoload
(defun magit-gitignore-in-gitdir (rule)

View File

@@ -1,6 +1,6 @@
;;; magit-imenu.el --- Integrate Imenu in magit major modes -*- lexical-binding: t -*-
;; Copyright (C) 2010-2021 The Magit Project Contributors
;; Copyright (C) 2010-2022 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.
@@ -8,6 +8,8 @@
;; Author: Damien Cassou <damien@cassou.me>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; SPDX-License-Identifier: GPL-3.0-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)
@@ -33,9 +35,6 @@
;;; Code:
(eval-when-compile
(require 'subr-x))
(require 'magit)
(require 'git-rebase)
@@ -48,21 +47,28 @@ 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
ENTRY-TYPES. Elements of MENU-TYPES are used to categorize
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)))
;; If `which-function-mode' is active, then the create-index
;; function is called at the time the major-mode is being enabled.
;; Modes that derive from `magit-mode' have not populated the buffer
;; at that time yet, so we have to abort.
(when-let ((section (magit-current-section))
(entries (make-hash-table :test 'equal)))
(goto-char (point-max))
(unless (oref section parent)
(forward-line -1))
(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)))))
(and (memq type entry-types)
(memq parent-type menu-types)))))
(let* ((section (magit-current-section))
(name (buffer-substring-no-properties
(line-beginning-position)
@@ -71,6 +77,8 @@ This function is used as a helper for functions set as
(parent-title (buffer-substring-no-properties
(oref parent start)
(1- (oref parent content)))))
(when (string-match " ([0-9]*)\\'" parent-title)
(setq parent-title (substring parent-title 0 (match-beginning 0))))
(puthash parent-title
(cons (cons name (point))
(gethash parent-title entries (list)))
@@ -134,10 +142,10 @@ beginning of the line."
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)))
'(file commit stash pullreq issue)
'(unpushed unstaged unpulled untracked staged stashes pullreqs issues)))
;;;; Refs mode
;;; Refs mode
;;;###autoload
(defun magit-imenu--refs-create-index-function ()
@@ -148,7 +156,7 @@ This function is used as a value for
'(branch commit tag)
'(local remote tags)))
;;;; Cherry mode
;;; Cherry mode
;;;###autoload
(defun magit-imenu--cherry-create-index-function ()
@@ -159,7 +167,7 @@ This function is used as a value for
'(commit)
'(cherries)))
;;;; Submodule list mode
;;; Submodule list mode
;;;###autoload
(defun magit-imenu--submodule-prev-index-position-function ()
@@ -177,7 +185,7 @@ This function is used as a value for
beginning of the line."
(elt (tabulated-list-get-entry) 0))
;;;; Repolist mode
;;; Repolist mode
;;;###autoload
(defun magit-imenu--repolist-prev-index-position-function ()
@@ -198,7 +206,7 @@ beginning of the line."
(elt entry 0)
(elt entry (1- (length entry))))))
;;;; Process mode
;;; Process mode
;;;###autoload
(defun magit-imenu--process-prev-index-position-function ()
@@ -218,7 +226,7 @@ beginning of the line."
(buffer-substring-no-properties (line-beginning-position)
(line-end-position)))
;;;; Rebase mode
;;; Rebase mode
;;;###autoload
(defun magit-imenu--rebase-prev-index-position-function ()

View File

@@ -1,6 +1,6 @@
;;; magit-log.el --- inspect Git history -*- lexical-binding: t -*-
;; Copyright (C) 2010-2021 The Magit Project Contributors
;; Copyright (C) 2010-2022 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.
@@ -8,6 +8,8 @@
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; SPDX-License-Identifier: GPL-3.0-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)
@@ -32,7 +34,7 @@
(require 'magit-core)
(require 'magit-diff)
(declare-function magit-blob-visit "magit-files" (blob-or-file line))
(declare-function magit-blob-visit "magit-files" (blob-or-file))
(declare-function magit-insert-head-branch-header "magit-status"
(&optional branch))
(declare-function magit-insert-upstream-branch-header "magit-status"
@@ -53,9 +55,6 @@
(require 'crm)
(require 'which-func)
(eval-when-compile
(require 'subr-x))
;;; Options
;;;; Log Mode
@@ -78,11 +77,11 @@
:options '("--follow" "--grep" "-G" "-S" "-L"))
(defcustom magit-log-revision-headers-format "\
%+b
%+b%+N
Author: %aN <%aE>
Committer: %cN <%cE>"
"Additional format string used with the `++header' argument."
:package-version '(magit . "2.3.0")
:package-version '(magit . "3.2.0")
:group 'magit-log
:type 'string)
@@ -407,10 +406,11 @@ the upstream isn't ahead of the current branch) show."
["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)
(7 magit-log:--since)
(7 magit-log:--until)
(magit-log:--grep)
(7 "-I" "Invert search pattern" "--invert-grep")
(7 "-i" "Search case-insensitive" ("-i" "--regexp-ignore-case"))
(7 "-I" "Invert search pattern" "--invert-grep")
(magit-log:-G) ;2
(magit-log:-S) ;2
(magit-log:-L) ;2
@@ -471,7 +471,8 @@ the upstream isn't ahead of the current branch) show."
(magit-log:-n)
(magit:--author)
(magit-log:--grep)
(7 "-I" "Invert search pattern" "--invert-grep")
(7 "-i" "Search case-insensitive" ("-i" "--regexp-ignore-case"))
(7 "-I" "Invert search pattern" "--invert-grep")
(magit-log:-G)
(magit-log:-S)
(magit-log:-L)]
@@ -549,6 +550,20 @@ the upstream isn't ahead of the current branch) show."
:argument "--author="
:reader 'magit-transient-read-person)
(transient-define-argument magit-log:--since ()
:description "Limit to commits since"
:class 'transient-option
:key "=s"
:argument "--since="
:reader 'transient-read-date)
(transient-define-argument magit-log:--until ()
:description "Limit to commits until"
:class 'transient-option
:key "=u"
:argument "--until="
:reader 'transient-read-date)
(transient-define-argument magit-log:--*-order ()
:description "Order commits by"
:class 'transient-switches
@@ -594,16 +609,17 @@ the upstream isn't ahead of the current branch) show."
(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))))
(let ((crm-separator "\\(\\.\\.\\.?\\|[, ]\\)")
(crm-local-completion-map magit-log-read-revs-map))
(split-string (magit-completing-read-multiple*
"Log rev,s: "
(magit-list-refnames nil t)
nil nil nil 'magit-revision-history
(or (magit-branch-or-commit-at-point)
(unless use-current
(magit-get-previous-branch)))
nil t)
"[, ]" t))))
(defun magit-log-read-pattern (option)
"Read a string from the user to pass as parameter to OPTION."
@@ -768,7 +784,7 @@ 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")))
(append (let ((commit (magit-read-branch-or-commit "Log merge of commit")))
(list commit
(magit-read-other-branch "Merged into" commit)))
(magit-log-arguments)))
@@ -778,11 +794,9 @@ 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 exit (magit-process-git t "when-merged" "-c"
(magit-abbrev-arg)
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))
@@ -876,6 +890,26 @@ is displayed in the current frame."
"\\[magit-log-double-commit-limit] first"))))
(user-error "Parent %s does not exist" parent-rev))))))
(defun magit-log-move-to-revision (rev)
"Read a revision and move to it in current log buffer.
If the chosen reference or revision isn't being displayed in
the current log buffer, then inform the user about that and do
nothing else.
If invoked outside any log buffer, then display the log buffer
of the current repository first; creating it if necessary."
(interactive (list (magit-read-branch-or-commit "In log, jump to")))
(with-current-buffer
(cond ((derived-mode-p 'magit-log-mode)
(current-buffer))
((when-let ((buf (magit-get-mode-buffer 'magit-log-mode)))
(pop-to-buffer-same-window buf)))
(t
(apply #'magit-log-all-branches (magit-log-arguments))))
(unless (magit-log-goto-commit-section (magit-rev-abbrev rev))
(user-error "%s isn't visible in the current log buffer" rev))))
;;;; Shortlog Commands
;;;###autoload (autoload 'magit-shortlog "magit-log" nil t)
@@ -896,11 +930,15 @@ is displayed in the current frame."
("r" "range" magit-shortlog-range)])
(defun magit-git-shortlog (rev args)
(with-current-buffer (get-buffer-create "*magit-shortlog*")
(erase-buffer)
(save-excursion
(magit-git-insert "shortlog" args rev))
(switch-to-buffer-other-window (current-buffer))))
(let ((dir default-directory))
(with-current-buffer (get-buffer-create "*magit-shortlog*")
(setq default-directory dir)
(setq buffer-read-only t)
(let ((inhibit-read-only t))
(erase-buffer)
(save-excursion
(magit-git-insert "shortlog" args rev))
(switch-to-buffer-other-window (current-buffer))))))
;;;###autoload
(defun magit-shortlog-since (rev args)
@@ -927,9 +965,10 @@ is displayed in the current frame."
(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 (kbd "C-c C-b") 'magit-go-backward)
(define-key map (kbd "C-c C-f") 'magit-go-forward)
(define-key map (kbd "C-c C-n") 'magit-log-move-to-parent)
(define-key map "j" 'magit-log-move-to-revision)
(define-key map "=" 'magit-log-toggle-commit-limit)
(define-key map "+" 'magit-log-double-commit-limit)
(define-key map "-" 'magit-log-half-commit-limit)
@@ -982,9 +1021,7 @@ Type \\[magit-reset] to reset `HEAD' to the commit at point.
(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)))
(unless (= (length files) 1)
(setq args (remove "--follow" args)))
(when (and (car magit-log-remove-graph-args)
(--any-p (string-match-p
@@ -1069,6 +1106,7 @@ Do not add this to a hook variable."
(setq args (cons "--decorate=full" (remove "--decorate" args))))
(when (member "--reverse" args)
(setq args (remove "--graph" args)))
(setq args (magit-diff--maybe-add-stat-arguments args))
args)
"--use-mailmap" "--no-prefix" revs "--" files)))
@@ -1211,6 +1249,17 @@ Do not add this to a hook variable."
(`stash (oset section type 'stash))
(`module (oset section type 'module-commit))
(`bisect-log (setq hash (magit-rev-parse "--short" hash))))
(setq hash (propertize hash 'font-lock-face
(pcase (and gpg (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)
(?N 'magit-hash)
(_ 'magit-hash))))
(when cherry
(when (and (derived-mode-p 'magit-refs-mode)
magit-refs-show-commit-count)
@@ -1227,11 +1276,11 @@ Do not add this to a hook variable."
'magit-cherry-unmatched)))
(insert ?\s))
(when align
(insert (propertize hash 'font-lock-face 'magit-hash) ?\s))
(insert hash ?\s))
(when graph
(insert graph))
(unless align
(insert (propertize hash 'font-lock-face 'magit-hash) ?\s))
(insert hash ?\s))
(when (and refs (not magit-log-show-refname-after-summary))
(insert (magit-format-ref-labels refs) ?\s))
(when (eq style 'reflog)
@@ -1240,16 +1289,6 @@ Do not add this to a hook variable."
(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)
@@ -1363,9 +1402,8 @@ If there is no revision buffer in the same frame, then do nothing."
(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)))))
(let ((args (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)
@@ -1402,8 +1440,7 @@ If there is no blob buffer in the same frame, then do nothing."
(save-excursion
(magit-blob-visit (list (magit-rev-parse rev)
(magit-file-relative-name
magit-buffer-file-name))
(line-number-at-pos))))))))))))
magit-buffer-file-name)))))))))))))
(defun magit-log-goto-commit-section (rev)
(let ((abbrev (magit-rev-format "%h" rev)))
@@ -1445,7 +1482,8 @@ The shortstat style is experimental and rather slow."
(truncate-string-to-width
(or author "")
details-width
nil ?\s (make-string 1 magit-ellipsis))
nil ?\s
(if (char-displayable-p ?…) "" ">"))
'magit-log-author)
" "))
(magit--propertize-face
@@ -1504,13 +1542,13 @@ The shortstat style is experimental and rather slow."
(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)
(define-key map (kbd "C-c C-b") 'undefined)
(define-key map (kbd "C-c C-f") 'undefined)
(define-key map (kbd ".") 'magit-log-select-pick)
(define-key map (kbd "e") 'magit-log-select-pick)
(define-key map (kbd "C-c C-c") 'magit-log-select-pick)
(define-key map (kbd "q") 'magit-log-select-quit)
(define-key map (kbd "C-c C-k") 'magit-log-select-quit)
map)
"Keymap for `magit-log-select-mode'.")
@@ -1600,11 +1638,12 @@ commit as argument."
(funcall fun rev)))
(defun magit-log-select-quit ()
"Abort selecting a commit, don't act on any commit."
"Abort selecting a commit, don't act on any commit.
Call `magit-log-select-quit-function' if set."
(interactive)
(magit-mode-bury-buffer 'kill)
(when magit-log-select-quit-function
(funcall magit-log-select-quit-function)))
(let ((fun magit-log-select-quit-function))
(magit-mode-bury-buffer 'kill)
(when fun (funcall fun))))
;;; Cherry Mode

View File

@@ -1,6 +1,6 @@
;;; magit-margin.el --- margins in Magit buffers -*- lexical-binding: t -*-
;; Copyright (C) 2010-2021 The Magit Project Contributors
;; Copyright (C) 2010-2022 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.
@@ -8,6 +8,8 @@
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; SPDX-License-Identifier: GPL-3.0-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)
@@ -30,11 +32,6 @@
;;; Code:
(require 'dash)
(eval-when-compile
(require 'subr-x))
(require 'magit-section)
(require 'magit-transient)
(require 'magit-mode)

View File

@@ -1,6 +1,6 @@
;;; magit-merge.el --- merge functionality -*- lexical-binding: t -*-
;; Copyright (C) 2010-2021 The Magit Project Contributors
;; Copyright (C) 2010-2022 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.
@@ -8,6 +8,8 @@
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; SPDX-License-Identifier: GPL-3.0-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)
@@ -27,9 +29,6 @@
;;; Code:
(eval-when-compile
(require 'subr-x))
(require 'magit)
(require 'magit-diff)
@@ -48,6 +47,8 @@
("-n" "No fast-forward" "--no-ff")
(magit-merge:--strategy)
(5 magit-merge:--strategy-option)
(5 "-b" "Ignore changes in amount of whitespace" "-Xignore-space-change")
(5 "-w" "Ignore whitespace when comparing lines" "-Xignore-all-space")
(5 magit-diff:--diff-algorithm :argument "-Xdiff-algorithm=")
(5 magit:--gpg-sign)]
["Actions"
@@ -59,7 +60,7 @@
[("p" "Preview merge" magit-merge-preview)
""
("s" "Squash merge" magit-merge-squash)
("i" "Merge into" magit-merge-into)]]
("i" "Dissolve" magit-merge-into)]]
["Actions"
:if magit-merge-in-progress-p
("m" "Commit merge" magit-commit-create)
@@ -138,7 +139,7 @@ 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."
then also remove the respective remote branch."
(interactive
(list (magit-read-other-local-branch
(format "Merge `%s' into"
@@ -171,9 +172,10 @@ then also remove the respective remote branch."
(magit--merge-absorb branch args))
(defun magit--merge-absorb (branch args)
(when (equal branch "master")
(when (equal branch (magit-main-branch))
(unless (yes-or-no-p
"Do you really want to merge `master' into another branch? ")
(format "Do you really want to merge `%s' into another branch? "
branch))
(user-error "Abort")))
(if-let ((target (magit-get-push-branch branch t)))
(progn
@@ -196,7 +198,9 @@ then also remove the respective remote branch."
(format "Merge branch '%s'%s [#%s]"
branch
(let ((current (magit-get-current-branch)))
(if (equal current "master") "" (format " into %s" current)))
(if (equal current (magit-main-branch))
""
(format " into %s" current)))
pr)
branch)
(magit-run-git-async "merge" args "--no-edit" branch))

View File

@@ -1,6 +1,6 @@
;;; magit-mode.el --- create and refresh Magit buffers -*- lexical-binding: t -*-
;; Copyright (C) 2010-2021 The Magit Project Contributors
;; Copyright (C) 2010-2022 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.
@@ -8,6 +8,8 @@
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; SPDX-License-Identifier: GPL-3.0-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)
@@ -29,17 +31,13 @@
;;; Code:
(require 'cl-lib)
(require 'dash)
(eval-when-compile
(require 'subr-x))
(require 'transient)
(require 'magit-section)
(require 'magit-git)
(require 'format-spec)
(require 'help-mode)
(require 'transient)
;; For `magit-display-buffer-fullcolumn-most-v1' from `git-commit'
(defvar git-commit-mode)
;; For `magit-refresh'
@@ -51,15 +49,12 @@
;; For `magit-refresh-buffer'
(declare-function magit-process-unset-mode-line-error-status "magit-process" ())
;; For `magit-refresh-get-relative-position'
(declare-function magit-hunk-section-p "magit-diff" (obj))
(declare-function magit-hunk-section-p "magit-diff" (section) t)
;; For `magit-mode-setup-internal'
(declare-function magit-status-goto-initial-section "magit-status" ())
;; For `magit-mode' from `bookmark'
(defvar bookmark-make-record-function)
(require 'format-spec)
(require 'help-mode)
;;; Options
(defcustom magit-mode-hook
@@ -115,7 +110,7 @@ inside your function."
:type 'hook)
(defcustom magit-display-buffer-function 'magit-display-buffer-traditional
"The function used display a Magit buffer.
"The function used to display a Magit buffer.
All Magit buffers (buffers whose major-modes derive from
`magit-mode') are displayed using `magit-display-buffer',
@@ -202,9 +197,9 @@ support additional %-sequences."
:group 'magit-buffers
:type 'boolean)
(defcustom magit-bury-buffer-function 'magit-restore-window-configuration
(defcustom magit-bury-buffer-function 'magit-mode-quit-window
"The function used to bury or kill the current Magit buffer."
:package-version '(magit . "2.3.0")
:package-version '(magit . "3.2.0")
:group 'magit-buffers
:type '(radio (function-item quit-window)
(function-item magit-mode-quit-window)
@@ -231,7 +226,7 @@ Valid values are:
buffer.
For more information see info node `(magit)Transient Arguments
and Buffer Arguments'."
and Buffer Variables'."
:package-version '(magit . "3.0.0")
:group 'magit-buffers
:group 'magit-commands
@@ -264,7 +259,7 @@ Valid values are:
buffer.
For more information see info node `(magit)Transient Arguments
and Buffer Arguments'."
and Buffer Variables'."
:package-version '(magit . "3.0.0")
:group 'magit-buffers
:group 'magit-commands
@@ -341,23 +336,16 @@ recommended value."
(defvar magit-mode-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map magit-section-mode-map)
(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 [M-tab] 'magit-section-cycle-diffs)
(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 [C-return] 'magit-visit-thing)
(define-key map (kbd "RET") 'magit-visit-thing)
(define-key map (kbd "M-TAB") 'magit-dired-jump)
(define-key map [M-tab] 'magit-section-cycle-diffs)
(define-key map (kbd "SPC") 'magit-diff-show-or-scroll-up)
(define-key map (kbd "S-SPC") 'magit-diff-show-or-scroll-down)
(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 "$" 'magit-process-buffer)
(define-key map "%" 'magit-worktree)
(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 "a" 'magit-cherry-apply)
(define-key map "A" 'magit-cherry-pick)
(define-key map "b" 'magit-branch)
@@ -374,13 +362,26 @@ recommended value."
(define-key map "G" 'magit-refresh-all)
(define-key map "h" 'magit-dispatch)
(define-key map "?" 'magit-dispatch)
(define-key map "H" 'magit-describe-section)
(define-key map "i" 'magit-gitignore)
(define-key map "I" 'magit-init)
(define-key map "j" 'magit-status-quick)
(define-key map "J" 'magit-display-repository-buffer)
(define-key map "k" 'magit-delete-thing)
(define-key map "K" 'magit-file-untrack)
(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)
;; section-map "n" magit-section-forward
;; reserved "N" forge-dispatch
(define-key map "o" 'magit-submodule)
(define-key map "O" 'magit-subtree)
;; section-map "p" magit-section-backward
(define-key map "P" 'magit-push)
(define-key map "q" 'magit-mode-bury-buffer)
(define-key map "Q" 'magit-git-command)
(define-key map ":" 'magit-git-command)
(define-key map "r" 'magit-rebase)
(define-key map "R" 'magit-file-rename)
(define-key map "s" 'magit-stage-file)
@@ -398,8 +399,9 @@ recommended value."
(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 "Z" 'magit-worktree)
(define-key map "%" 'magit-worktree)
(define-key map "$" 'magit-process-buffer)
(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)
@@ -446,6 +448,11 @@ which visits the thing at point using `browse-url'."
(interactive)
(user-error "There is no thing at point that could be browsed"))
(defun magit-help ()
"Visit the Magit manual."
(interactive)
(info "magit"))
(defvar bug-reference-map)
(with-eval-after-load 'bug-reference
(define-key bug-reference-map [remap magit-visit-thing]
@@ -475,8 +482,8 @@ which visits the thing at point using `browse-url'."
["Cherry pick" magit-cherry-pick t]
["Revert commit" magit-revert t]
"---"
["Ignore globally" magit-gitignore-globally t]
["Ignore locally" magit-gitignore-locally t]
["Ignore at toplevel" magit-gitignore-in-topdir t]
["Ignore in subdirectory" magit-gitignore-in-subdir t]
["Discard" magit-discard t]
["Reset head and index" magit-reset-mixed t]
["Stash" magit-stash-both t]
@@ -518,6 +525,7 @@ Magit is documented in info node `(magit)'."
(hack-dir-local-variables-non-file-buffer)
(face-remap-add-relative 'header-line 'magit-header-line)
(setq mode-line-process (magit-repository-local-get 'mode-line-process))
(setq-local revert-buffer-function 'magit-refresh-buffer)
(setq-local bookmark-make-record-function 'magit--make-bookmark)
(setq-local isearch-filter-predicate 'magit-section--open-temporarily))
@@ -827,11 +835,11 @@ into thinking a buffer belongs to a repo that it doesn't.")
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
exist that hasn't been locked 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.
which case return the buffer that has been locked to that value.
If FRAME nil or omitted, then consider all buffers. Otherwise
If FRAME is 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.
@@ -999,7 +1007,7 @@ window."
;;; Refresh Buffers
(defvar inhibit-magit-refresh nil)
(defvar magit-inhibit-refresh nil)
(defun magit-refresh ()
"Refresh some buffers belonging to the current repository.
@@ -1009,7 +1017,7 @@ Refresh the current buffer if its major mode derives from
Run hooks `magit-pre-refresh-hook' and `magit-post-refresh-hook'."
(interactive)
(unless inhibit-magit-refresh
(unless magit-inhibit-refresh
(unwind-protect
(let ((start (current-time))
(magit--refresh-cache (or magit--refresh-cache
@@ -1061,7 +1069,7 @@ Run hooks `magit-pre-refresh-hook' and `magit-post-refresh-hook'."
(defvar-local magit-refresh-start-time nil)
(defun magit-refresh-buffer ()
(defun magit-refresh-buffer (&rest _ignore)
"Refresh the current Magit buffer."
(setq magit-refresh-start-time (current-time))
(let ((refresh (intern (format "%s-refresh-buffer"
@@ -1071,18 +1079,23 @@ Run hooks `magit-pre-refresh-hook' and `magit-post-refresh-hook'."
(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))))))
(windows (cl-mapcan
(lambda (window)
(with-selected-window window
(with-current-buffer buffer
(when-let ((section (magit-current-section)))
`(( ,window
,section
,@(magit-refresh-get-relative-position)))))))
;; If it qualifies, then the selected window
;; comes first, but we want to handle it last
;; so that its `magit-section-movement-hook'
;; run can override the effects of other runs.
(or (nreverse (get-buffer-window-list buffer nil t))
(list (selected-window))))))
(deactivate-mark)
(setq magit-section-pre-command-section nil)
(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)
@@ -1091,9 +1104,12 @@ Run hooks `magit-pre-refresh-hook' and `magit-post-refresh-hook'."
(save-excursion
(apply refresh (with-no-warnings magit-refresh-args))))
(pcase-dolist (`(,window . ,args) windows)
(with-selected-window window
(if (eq buffer (window-buffer window))
(with-selected-window window
(apply #'magit-section-goto-successor args))
(with-current-buffer buffer
(apply #'magit-section-goto-successor args))))
(let ((magit-section-movement-hook nil))
(apply #'magit-section-goto-successor args)))))
(run-hooks 'magit-refresh-buffer-hook)
(magit-section-update-highlight)
(set-buffer-modified-p nil))
@@ -1105,7 +1121,8 @@ Run hooks `magit-pre-refresh-hook' and `magit-post-refresh-hook'."
(defun magit-refresh-get-relative-position ()
(when-let ((section (magit-current-section)))
(let ((start (oref section start)))
(list (count-lines start (point))
(list (- (line-number-at-pos (point))
(line-number-at-pos start))
(- (point) (line-beginning-position))
(and (magit-hunk-section-p section)
(region-active-p)
@@ -1189,7 +1206,7 @@ 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))
(let ((remote (file-remote-p default-directory))
(save-some-buffers-action-alist
`((?Y (lambda (buffer)
(with-current-buffer buffer
@@ -1203,18 +1220,19 @@ argument (the prefix) non-nil means save all with no questions."
,@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)))))))
(and buffer-file-name
;; - Check whether refreshing is disabled.
(not magit-inhibit-refresh-save)
;; - Check whether the visited file is either on the
;; same remote as the repository, or both are on
;; the local system.
(equal (file-remote-p buffer-file-name) remote)
;; Delayed checks that are more expensive for remote
;; repositories, due to the required network access.
;; - Check whether the file is inside the repository.
(equal (magit-rev-parse-safe "--show-toplevel") topdir)
;; - Check whether the file is actually writable.
(file-writable-p buffer-file-name)))))))
;;; Restore Window Configuration
@@ -1416,7 +1434,7 @@ repository's Magit buffers."
(dolist (buffer (magit-mode-get-buffers))
(with-current-buffer buffer
(setq magit-section-visibility-cache nil)))
(setq magit--libgit-available-p eieio-unbound))
(setq magit--libgit-available-p 'unknown))
;;; Utilities

View File

@@ -1,6 +1,6 @@
;;; magit-notes.el --- notes support -*- lexical-binding: t -*-
;; Copyright (C) 2010-2021 The Magit Project Contributors
;; Copyright (C) 2010-2022 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.
@@ -8,6 +8,8 @@
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; SPDX-License-Identifier: GPL-3.0-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)
@@ -93,7 +95,7 @@
:prompt "Set global notes.displayRef")
(transient-define-argument magit-notes:--ref ()
:description "Merge strategy"
:description "Manipulate ref"
:class 'transient-option
:key "-r"
:argument "--ref="
@@ -174,7 +176,7 @@ Also see `magit-notes-merge'."
it
(concat "refs/notes/" it))))
(defun magit-notes-read-refs (prompt)
(defun magit-notes-read-refs (prompt &optional _initial-input _history)
(mapcar (lambda (ref)
(if (string-prefix-p "refs/" ref)
ref
@@ -190,10 +192,10 @@ Also see `magit-notes-merge'."
","))))
(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))))
(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)

View File

@@ -1,6 +1,6 @@
;;; magit-obsolete.el --- obsolete definitions -*- lexical-binding: t -*-
;; Copyright (C) 2010-2021 The Magit Project Contributors
;; Copyright (C) 2010-2022 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.
@@ -8,6 +8,8 @@
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; SPDX-License-Identifier: GPL-3.0-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)
@@ -52,6 +54,9 @@
(define-obsolete-variable-alias 'magit-disable-line-numbers
'magit-section-disable-line-numbers "Magit 3.0.0")
(define-obsolete-variable-alias 'inhibit-magit-refresh
'magit-inhibit-refresh "Magit 3.0.0")
(defun magit--magit-popup-warning ()
(display-warning 'magit "\
Magit no longer uses Magit-Popup.

View File

@@ -1,6 +1,6 @@
;;; magit-patch.el --- creating and applying patches -*- lexical-binding: t -*-
;; Copyright (C) 2008-2021 The Magit Project Contributors
;; Copyright (C) 2008-2022 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.
@@ -8,6 +8,8 @@
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; SPDX-License-Identifier: GPL-3.0-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)
@@ -27,9 +29,6 @@
;;; Code:
(eval-when-compile
(require 'subr-x))
(require 'magit)
;;; Options
@@ -58,10 +57,11 @@ the prefix argument."
(transient-define-prefix 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)])
[("c" "Create patches" magit-patch-create)
("w" "Apply patches" magit-am)]
[("a" "Apply plain 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)
(transient-define-prefix magit-patch-create (range args files)

View File

@@ -1,12 +1,13 @@
(define-package "magit" "20210105.1030" "A Git porcelain inside Emacs."
(define-package "magit" "20220102.1825" "A Git porcelain inside Emacs."
'((emacs "25.1")
(async "20200113")
(dash "20200524")
(git-commit "20200516")
(transient "20200601")
(with-editor "20200522"))
:commit "25f432551347468ce97b8b03987e59092e91f8f0" :authors
'(("Marius Vollmer" . "marius.vollmer@gmail.com"))
(dash "20210826")
(git-commit "20211004")
(magit-section "20211004")
(transient "20210920")
(with-editor "20211001"))
:commit "2e73b66c2980abb9211d9881a8710c8ac5a33184" :authors
'(("Marius Vollmer" . "marius.vollmer@gmail.com")
("Jonas Bernoulli" . "jonas@bernoul.li"))
:maintainer
'("Jonas Bernoulli" . "jonas@bernoul.li")
:keywords

View File

@@ -1,6 +1,6 @@
;;; magit-process.el --- process functionality -*- lexical-binding: t -*-
;; Copyright (C) 2010-2021 The Magit Project Contributors
;; Copyright (C) 2010-2022 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.
@@ -8,6 +8,8 @@
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; SPDX-License-Identifier: GPL-3.0-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)
@@ -31,19 +33,14 @@
;;; 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)
(require 'ansi-color)
(require 'with-editor)
(declare-function auth-source-search "auth-source"
(&rest spec &key max require create delete &allow-other-keys))
@@ -100,11 +97,14 @@ When this is nil, no sections are ever removed."
:type '(choice (const :tag "Never remove old sections" nil) integer))
(defvar magit-process-extreme-logging nil
"Whether `magit-process-file' logs to *Messages* buffer.
"Whether `magit-process-file' logs to the *Messages* buffer.
Only intended for temporary use when you try to figure out how
Magit uses Git behind the scene. Output that normally goes to
the magit-process buffer continues to go there. Not all output
goes to either of these two buffers.")
goes to either of these two buffers.
Also see `magit-git-debug'.")
(defcustom magit-process-error-tooltip-max-lines 20
"The number of lines for `magit-process-error-lines' to return.
@@ -176,11 +176,12 @@ itself from the hook, to avoid further futile attempts."
"Please enter the passphrase for the ssh key"
"Please enter the passphrase to unlock the OpenPGP secret key"
"^.*'s password: ?$"
"^Token: $" ; For git-credential-manager-core (#4318).
"^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")
:package-version '(magit . "3.0.0")
:group 'magit-process
:type '(repeat (regexp)))
@@ -355,7 +356,7 @@ then raise an error."
(defun magit-run-git (&rest args)
"Call Git synchronously in a separate process, and refresh.
Option `magit-git-executable' specifies the Git executable and
Function `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.
@@ -377,7 +378,7 @@ Process output goes into a new section in the buffer returned by
(defun magit-call-git (&rest args)
"Call Git synchronously in a separate process.
Option `magit-git-executable' specifies the Git executable and
Function `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.
@@ -386,7 +387,8 @@ 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
(apply #'magit-call-process
(magit-git-executable)
(magit-process-git-arguments args))))
(defun magit-call-process (program &rest args)
@@ -400,6 +402,17 @@ Process output goes into a new section in the buffer returned by
(apply #'magit-process-file program nil process-buf nil args))
process-buf (current-buffer) default-directory section)))
(defun magit-process-git (destination &rest args)
"Call Git synchronously in a separate process, returning its exit code.
DESTINATION specifies how to handle the output, like for
`call-process', except that file handlers are supported.
Enable Cygwin's \"noglob\" option during the call and
ensure unix eol conversion."
(apply #'magit-process-file
(magit-git-executable)
nil destination nil
(magit-process-git-arguments args)))
(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
@@ -437,9 +450,10 @@ conversion."
ARGS is flattened and then used as arguments to Git.
The current buffer's content is used as the process's standard
input.
input. The buffer is assumed to be temporary and thus OK to
modify.
Option `magit-git-executable' specifies the Git executable and
Function `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."
@@ -460,11 +474,11 @@ flattened before use."
(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))
(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)
(magit-git-executable) nil process-buf nil flat-args)
process-buf nil default-directory section))))
;;; Asynchronous Processes
@@ -480,7 +494,7 @@ 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
(message "Running %s %s" (magit-git-executable)
(let ((m (mapconcat #'identity (-flatten args) " ")))
(remove-list-of-text-properties 0 (length m) '(face) m)
m))
@@ -528,7 +542,7 @@ 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
Function `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.
@@ -540,7 +554,7 @@ 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
(apply #'magit-start-process (magit-git-executable) input
(magit-process-git-arguments args))))
(defun magit-start-process (program &optional input &rest args)
@@ -580,11 +594,11 @@ Magit status buffer."
(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))
(set-process-coding-system process nil '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
(when magit-inhibit-refresh
(process-put process 'inhibit-refresh t))
(oset section process process)
(with-current-buffer process-buf
@@ -611,7 +625,7 @@ Magit status buffer."
(default-process-coding-system
(magit--process-coding-system)))
(apply #'start-file-process "git" process-buf
magit-git-executable args))))
(magit-git-executable) args))))
(process-put process 'command-buf command-buf)
(process-put process 'parsed (point))
(setq magit-this-process process)
@@ -652,12 +666,15 @@ Magit status buffer."
(defun magit-process--format-arguments (program args)
(cond
((and args (equal program magit-git-executable))
((and args (equal program (magit-git-executable)))
(setq args (-split-at (length magit-git-global-arguments) args))
(concat (propertize (file-name-nondirectory program)
'font-lock-face 'magit-section-heading)
" "
(propertize (char-to-string magit-ellipsis)
(propertize (if (stringp magit-ellipsis)
magit-ellipsis
;; For backward compatibility.
(char-to-string magit-ellipsis))
'font-lock-face 'magit-section-heading
'help-echo (mapconcat #'identity (car args) " "))
" "
@@ -758,7 +775,9 @@ Magit status buffer."
(let ((map (cl-gensym)))
`(let ((,map (make-sparse-keymap)))
(set-keymap-parent ,map minibuffer-local-map)
(define-key ,map "\C-g"
;; Note: Leaving (kbd ...) unevaluated leads to the
;; magit-process:password-prompt test failing.
(define-key ,map ,(kbd "C-g")
(lambda ()
(interactive)
(ignore-errors (kill-process ,proc))
@@ -790,13 +809,38 @@ To use this function add it to the appropriate hook
'magit-process-password-auth-source)
KEY typically derives from a prompt such as:
Password for 'https://tarsius@bitbucket.org'
Password for 'https://yourname@github.com'
in which case it would be the string
tarsius@bitbucket.org
yourname@github.com
which matches the ~/.authinfo.gpg entry
machine bitbucket.org login tarsius password 12345
machine github.com login yourname password 12345
or iff that is undefined, for backward compatibility
machine tarsius@bitbucket.org password 12345"
machine yourname@github.com password 12345
On github.com you should not use your password but a
personal access token, see [1]. For information about
the peculiarities of other forges, please consult the
respective documentation.
After manually editing ~/.authinfo.gpg you must reset
the cache using
M-x auth-source-forget-all-cached RET
The above will save you from having to repeatedly type
your token or password, but you might still repeatedly
be asked for your username. To prevent that, change an
URL like
https://github.com/foo/bar.git
to
https://yourname@github.com/foo/bar.git
Instead of changing all such URLs manually, they can
be translated on the fly by doing this once
git config --global \
url.https://yourname@github.com.insteadOf \
https://github.com
[1]: https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token."
(require 'auth-source)
(and (string-match "\\`\\(.+\\)@\\([^@]+\\)\\'" key)
(let* ((user (match-string 1 key))
@@ -810,12 +854,26 @@ or iff that is undefined, for backward compatibility
(funcall secret)
secret))))
(defun magit-process-git-credential-manager-core (process string)
"Authenticate using `git-credential-manager-core'.
To use this function add it to the appropriate hook
(add-hook \\='magit-process-prompt-functions
\\='magit-process-git-credential-manager-core)"
(and (string-match "^option (enter for default): $" string)
(progn
(magit-process-buffer)
(let ((option (format "%c\n"
(read-char-choice "Option: " '(?\r ?\j ?1 ?2)))))
(insert-before-markers-and-inherit option)
(process-send-string process option)))))
(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
the password. If all functions return nil, then read the password
from the user."
(when-let ((prompt (magit-process-match-prompt
magit-process-password-prompt-regexps string)))
@@ -879,7 +937,7 @@ as argument."
(condition-case nil
(start-process "git-credential-cache--daemon"
" *git-credential-cache--daemon*"
magit-git-executable
(magit-git-executable)
"credential-cache--daemon"
magit-credential-cache-daemon-socket)
;; Some Git implementations (e.g. Windows) won't have
@@ -922,7 +980,7 @@ as argument."
(defun magit-process-set-mode-line (program args)
"Display the git command (sans arguments) in the mode line."
(when (equal program magit-git-executable)
(when (equal program (magit-git-executable))
(setq args (nthcdr (length magit-git-global-arguments) args)))
(let ((str (concat " " (propertize
(concat (file-name-nondirectory program)
@@ -971,8 +1029,8 @@ If STR is supplied, it replaces the `mode-line-process' text."
;; 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 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

View File

@@ -1,6 +1,6 @@
;;; magit-pull.el --- update local objects and refs -*- lexical-binding: t -*-
;; Copyright (C) 2008-2021 The Magit Project Contributors
;; Copyright (C) 2008-2022 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.
@@ -8,6 +8,8 @@
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; SPDX-License-Identifier: GPL-3.0-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)
@@ -43,8 +45,10 @@
(transient-define-prefix magit-pull ()
"Pull from another repository."
:man-page "git-pull"
:incompatible '(("--ff-only" "--rebase"))
[:description
(lambda () (if magit-pull-or-fetch "Pull arguments" "Arguments"))
("-f" "Fast-forward only" "--ff-only")
("-r" "Rebase local commits" ("-r" "--rebase"))
("-A" "Autostash" "--autostash" :level 7)]
[:description

View File

@@ -1,6 +1,6 @@
;;; magit-push.el --- update remote objects and refs -*- lexical-binding: t -*-
;; Copyright (C) 2008-2021 The Magit Project Contributors
;; Copyright (C) 2008-2022 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.
@@ -8,6 +8,8 @@
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; SPDX-License-Identifier: GPL-3.0-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)
@@ -27,9 +29,6 @@
;;; Code:
(eval-when-compile
(require 'subr-x))
(require 'magit)
;;; Commands
@@ -91,8 +90,10 @@ argument the push-remote can be changed before pushed to it."
(magit--select-push-remote "push there")))
(when changed
(magit-confirm 'set-and-push
(format "Really use \"%s\" as push-remote and push \"%s\" there"
remote branch)))
(replace-regexp-in-string
"%" "%%"
(format "Really use \"%s\" as push-remote and push \"%s\" there"
remote branch))))
(run-hooks 'magit-credential-hook)
(magit-run-git-async "push" "-v" args remote
(format "refs/heads/%s:refs/heads/%s"
@@ -151,8 +152,10 @@ the upstream."
;; is what the user wants to happen.
(setq merge (concat "refs/heads/" merge)))
(magit-confirm 'set-and-push
(format "Really use \"%s\" as upstream and push \"%s\" there"
upstream branch)))
(replace-regexp-in-string
"%" "%%"
(format "Really use \"%s\" as upstream and push \"%s\" there"
upstream branch))))
(cl-pushnew "--set-upstream" args :test #'equal))
(run-hooks 'magit-credential-hook)
(magit-run-git-async "push" "-v" args remote (concat branch ":" merge))))
@@ -218,11 +221,10 @@ 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-completing-read-multiple*
"Push refspec,s: "
(cons "HEAD" (magit-list-local-branch-names))
nil nil nil 'magit-push-refspecs-history)
(magit-push-arguments)))
(run-hooks 'magit-credential-hook)
(magit-run-git-async "push" "-v" args remote refspecs))
@@ -284,8 +286,8 @@ If you add this suffix to a transient prefix without explicitly
specifying the description, then an attempt is made to predict
what this command will do. For example:
(transient-insert-suffix 'magit-push \"p\"
'(\"i\" magit-push-implicitly))"
(transient-insert-suffix \\='magit-push \"p\"
\\='(\"i\" magit-push-implicitly))"
:description 'magit-push-implicitly--desc
(interactive (list (magit-push-arguments)))
(run-hooks 'magit-credential-hook)
@@ -295,7 +297,7 @@ what this command will do. For example:
(let ((default (magit-get "push.default")))
(unless (equal default "nothing")
(or (when-let ((remote (or (magit-get-remote)
(magit-remote-p "origin")))
(magit-primary-remote)))
(refspec (magit-get "remote" remote "push")))
(format "%s using %s"
(magit--propertize-face remote 'magit-branch-remote)

View File

@@ -1,6 +1,6 @@
;;; magit-reflog.el --- inspect ref history -*- lexical-binding: t -*-
;; Copyright (C) 2010-2021 The Magit Project Contributors
;; Copyright (C) 2010-2022 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.
@@ -8,6 +8,8 @@
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; SPDX-License-Identifier: GPL-3.0-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)
@@ -30,9 +32,6 @@
(require 'magit-core)
(require 'magit-log)
(eval-when-compile
(require 'subr-x))
;;; Options
(defcustom magit-reflog-limit 256
@@ -137,8 +136,8 @@ If `HEAD' is detached, then show the reflog for that instead."
(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)
(define-key map (kbd "C-c C-n") 'undefined)
(define-key map (kbd "L") 'magit-margin-settings)
map)
"Keymap for `magit-reflog-mode'.")

View File

@@ -1,6 +1,6 @@
;;; magit-refs.el --- listing references -*- lexical-binding: t -*-
;; Copyright (C) 2010-2021 The Magit Project Contributors
;; Copyright (C) 2010-2022 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.
@@ -8,6 +8,8 @@
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; SPDX-License-Identifier: GPL-3.0-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)
@@ -27,9 +29,6 @@
;;; Code:
(eval-when-compile
(require 'subr-x))
(require 'magit)
;;; Options
@@ -64,7 +63,7 @@ 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'"
`magit-refs-set-show-commit-count'."
:package-version '(magit . "2.1.0")
:group 'magit-refs
:safe (lambda (val) (memq val '(all branch nil)))
@@ -278,8 +277,8 @@ the outcome.
(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)
(define-key map (kbd "C-y") 'magit-refs-set-show-commit-count)
(define-key map (kbd "L") 'magit-margin-settings)
map)
"Keymap for `magit-refs-mode'.")
@@ -342,7 +341,9 @@ Type \\[magit-reset] to reset `HEAD' to the commit at point.
["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)]
("o" "Show refs, comparing them with other branch" magit-show-refs-other)
("r" "Show refs, changing commit count display"
magit-refs-set-show-commit-count)]
(interactive (list (or (derived-mode-p 'magit-refs-mode)
current-prefix-arg)))
(if transient
@@ -528,9 +529,12 @@ line is inserted at all."
(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)
(make-string
(max 1 (- (if (consp magit-refs-primary-column-width)
(car magit-refs-primary-column-width)
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))
@@ -569,9 +573,12 @@ line is inserted at all."
(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)
(make-string
(max 1 (- (if (consp magit-refs-primary-column-width)
(car magit-refs-primary-column-width)
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))
@@ -646,8 +653,7 @@ line is inserted at all."
(if branch
(magit-refs--propertize-branch
branch ref (and headp 'magit-branch-current))
(magit--propertize-face "(detached)"
'font-lock-warning-face)))
(magit--propertize-face "(detached)" 'magit-branch-warning)))
(u:ahead (and u:track
(string-match "ahead \\([0-9]+\\)" u:track)
(magit--propertize-face

View File

@@ -1,6 +1,6 @@
;;; magit-remote.el --- transfer Git commits -*- lexical-binding: t -*-
;; Copyright (C) 2008-2021 The Magit Project Contributors
;; Copyright (C) 2008-2022 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.
@@ -8,6 +8,8 @@
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; SPDX-License-Identifier: GPL-3.0-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)
@@ -85,7 +87,8 @@ has to be used to view and change remote related variables."
("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)]]
("P" "Prune stale refspecs" magit-remote-prune-refspecs)
(7 "z" "Unshallow remote" magit-remote-unshallow)]]
(interactive (list (magit-get-current-remote)))
(transient-setup 'magit-remote nil nil :scope remote))
@@ -255,6 +258,24 @@ Delete the symbolic-ref \"refs/remotes/<remote>/HEAD\"."
(interactive (list (magit-read-remote "Unset HEAD for remote")))
(magit-run-git "remote" "set-head" remote "--delete"))
;;;###autoload
(defun magit-remote-unshallow (remote)
"Convert a shallow remote into a full one.
If only a single refspec is set and it does not contain a
wildcard, then also offer to replace it with the standard
refspec."
(interactive (list (or (magit-get-current-remote)
(magit-read-remote "Delete remote"))))
(let ((refspecs (magit-get-all "remote" remote "fetch"))
(standard (format "+refs/heads/*:refs/remotes/%s/*" remote)))
(when (and (= (length refspecs) 1)
(not (string-match-p "\\*" (car refspecs)))
(yes-or-no-p (format "Also replace refspec %s with %s? "
(car refspecs)
standard)))
(magit-set standard "remote" remote "fetch"))
(magit-git-fetch "--unshallow" remote)))
;;; Configure
;;;###autoload (autoload 'magit-remote-configure "magit-remote" nil t)

View File

@@ -1,6 +1,6 @@
;;; magit-repos.el --- listing repositories -*- lexical-binding: t -*-
;; Copyright (C) 2010-2021 The Magit Project Contributors
;; Copyright (C) 2010-2022 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.
@@ -8,6 +8,8 @@
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; SPDX-License-Identifier: GPL-3.0-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)
@@ -29,12 +31,9 @@
;;; Code:
(eval-when-compile
(require 'subr-x))
(require 'magit-core)
(declare-function magit-status-setup-buffer "magit-status" (directory))
(declare-function magit-status-setup-buffer "magit-status" (&optional directory))
(defvar x-stretch-cursor)
@@ -89,10 +88,16 @@ 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."
actually support that yet.
You may wish to display a range of numeric columns using just one
character per column and without any padding between columns, in
which case you should use an appropriat HEADER, set WIDTH to 1,
and set `:pad-right' to 0. \"+\" is substituted for numbers higher
than 9."
:package-version '(magit . "2.12.0")
:group 'magit-repolist
:type `(repeat (list :tag "Column"
:type '(repeat (list :tag "Column"
(string :tag "Header Label")
(integer :tag "Column Width")
(function :tag "Inserter Function")
@@ -119,6 +124,18 @@ as the value of `magit-repolist-column-flag'."
:type '(alist :key-type (function :tag "Predicate Function")
:value-type (string :tag "Flag")))
(defcustom magit-repolist-sort-key '("Path" . nil)
"Initial sort key for buffer created by `magit-list-repositories'.
If nil, no additional sorting is performed. Otherwise, this
should be a cons cell (NAME . FLIP). NAME is a string matching
one of the column names in `magit-repolist-columns'. FLIP, if
non-nil, means to invert the resulting sort."
:package-version '(magit . "3.2.0")
:group 'magit-repolist
:type '(choice (const nil)
(cons (string :tag "Column name")
(boolean :tag "Flip order"))))
;;; List Repositories
;;;; Command
;;;###autoload
@@ -128,14 +145,7 @@ as the value of `magit-repolist-column-flag'."
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")))
(magit-repolist-setup (default-value 'magit-repolist-columns)))
;;;; Mode
@@ -157,64 +167,98 @@ repositories are displayed."
"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-setup (columns)
(unless magit-repository-directories
(user-error "You need to customize `magit-repository-directories' %s"
"before you can list repositories"))
(with-current-buffer (get-buffer-create "*Magit Repositories*")
(magit-repolist-mode)
(setq-local magit-repolist-columns columns)
(magit-repolist-refresh)
(switch-to-buffer (current-buffer))))
(defun magit-repolist-refresh ()
(unless tabulated-list-sort-key
(setq tabulated-list-sort-key
(pcase-let ((`(,column . ,flip) magit-repolist-sort-key))
(cons (or (car (assoc column magit-repolist-columns))
(caar magit-repolist-columns))
flip))))
(setq tabulated-list-format
(vconcat (mapcar (pcase-lambda (`(,title ,width ,_fn ,props))
(nconc (list title width t)
(-flatten props)))
magit-repolist-columns)))
(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)))))
(vconcat
(mapcar (pcase-lambda (`(,title ,width ,fn ,props))
(or (funcall fn `((:id ,id)
(:title ,title)
(:width ,width)
,@props))
""))
magit-repolist-columns)))))
(magit-list-repos-uniquify
(--map (cons (file-name-nondirectory (directory-file-name it))
it)
(magit-list-repos))))))
(magit-list-repos)))))
(message "Listing repositories...")
(tabulated-list-init-header)
(tabulated-list-print t)
(message "Listing repositories...done"))
;;;; Columns
(defun magit-repolist-column-ident (id)
(defun magit-repolist-column-ident (spec)
"Insert the identification of the repository.
Usually this is just its basename."
id)
(cadr (assq :id spec)))
(defun magit-repolist-column-path (_id)
(defun magit-repolist-column-path (_)
"Insert the absolute path of the repository."
(abbreviate-file-name default-directory))
(defun magit-repolist-column-version (_id)
(defun magit-repolist-column-version (_)
"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))
(when (string-match
"\\(?:-\\([0-9]*\\)-g[a-z0-9]*\\)?\\(?:-\\(dirty\\)\\)?\\'" v)
(magit--put-face (match-beginning 0) (match-end 0) 'shadow v)
(when (match-end 1)
(magit--put-face (match-beginning 1) (match-end 1) 'bold v))
(when (match-end 2)
(magit--put-face (match-beginning 2) (match-end 2) 'error v)))
(if (and v (string-match "\\`[0-9]" v))
(concat " " v)
(when (and v (string-match "\\`[^0-9]+" v))
(magit--put-face 0 (match-end 0) 'shadow v))
v))))
(defun magit-repolist-column-branch (_id)
(defun magit-repolist-column-branch (_)
"Insert the current branch."
(magit-get-current-branch))
(let ((branch (magit-get-current-branch)))
(if (member branch magit-main-branch-names)
(magit--propertize-face branch 'shadow)
branch)))
(defun magit-repolist-column-upstream (_id)
(defun magit-repolist-column-upstream (_)
"Insert the upstream branch of the current branch."
(magit-get-upstream-branch))
(defun magit-repolist-column-flag (_id)
(defun magit-repolist-column-flag (_)
"Insert a flag as specified by `magit-repolist-column-flag-alist'.
By default this indicates whether there are uncommitted changes.
@@ -226,43 +270,50 @@ Only one letter is shown, the first that applies."
(and (funcall fun) flag))
magit-repolist-column-flag-alist))
(defun magit-repolist-column-unpulled-from-upstream (_id)
(defun magit-repolist-column-flags (_)
"Insert all flags as specified by `magit-repolist-column-flag-alist'.
This is an alternative to function `magit-repolist-column-flag',
which only lists the first one found."
(mapconcat (pcase-lambda (`(,fun . ,flag))
(if (funcall fun) flag " "))
magit-repolist-column-flag-alist
""))
(defun magit-repolist-column-unpulled-from-upstream (spec)
"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)))))
(magit-repolist-insert-count (cadr (magit-rev-diff-count "HEAD" it)) spec)))
(defun magit-repolist-column-unpulled-from-pushremote (_id)
(defun magit-repolist-column-unpulled-from-pushremote (spec)
"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)))))
(magit-repolist-insert-count (cadr (magit-rev-diff-count "HEAD" it)) spec)))
(defun magit-repolist-column-unpushed-to-upstream (_id)
(defun magit-repolist-column-unpushed-to-upstream (spec)
"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)))))
(magit-repolist-insert-count (car (magit-rev-diff-count "HEAD" it)) spec)))
(defun magit-repolist-column-unpushed-to-pushremote (_id)
(defun magit-repolist-column-unpushed-to-pushremote (spec)
"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)))))
(magit-repolist-insert-count (car (magit-rev-diff-count "HEAD" it)) spec)))
(defun magit-repolist-column-branches (_id)
(defun magit-repolist-column-branches (spec)
"Insert number of branches."
(let ((n (length (magit-list-local-branches))))
(magit--propertize-face (number-to-string n) (if (> n 1) 'bold 'shadow))))
(magit-repolist-insert-count (length (magit-list-local-branches))
`((:normal-count 1) ,@spec)))
(defun magit-repolist-column-stashes (_id)
(defun magit-repolist-column-stashes (spec)
"Insert number of stashes."
(let ((n (length (magit-list-stashes))))
(magit--propertize-face (number-to-string n) (if (> n 0) 'bold 'shadow))))
(magit-repolist-insert-count (length (magit-list-stashes)) spec))
(defun magit-repolist-insert-count (n spec)
(magit--propertize-face
(if (and (> n 9) (= (cadr (assq :width spec)) 1))
"+"
(number-to-string n))
(if (> n (or (cadr (assq :normal-count spec)) 0)) 'bold 'shadow)))
;;; Read Repository

View File

@@ -1,6 +1,6 @@
;;; magit-reset.el --- reset fuctionality -*- lexical-binding: t -*-
;; Copyright (C) 2010-2021 The Magit Project Contributors
;; Copyright (C) 2010-2022 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.
@@ -8,6 +8,8 @@
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; SPDX-License-Identifier: GPL-3.0-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)

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
;;; magit-sequence.el --- history manipulation in Magit -*- lexical-binding: t -*-
;; Copyright (C) 2011-2021 The Magit Project Contributors
;; Copyright (C) 2011-2022 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.
@@ -8,6 +8,8 @@
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; SPDX-License-Identifier: GPL-3.0-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)
@@ -29,9 +31,6 @@
;;; Code:
(eval-when-compile
(require 'subr-x))
(require 'magit)
;; For `magit-rebase--todo'.
@@ -149,7 +148,8 @@ This discards all changes made since the sequence started."
["Apply here"
("A" "Pick" magit-cherry-copy)
("a" "Apply" magit-cherry-apply)
("h" "Harvest" magit-cherry-harvest)]
("h" "Harvest" magit-cherry-harvest)
("m" "Squash" magit-merge-squash)]
["Apply elsewhere"
("d" "Donate" magit-cherry-donate)
("n" "Spinout" magit-cherry-spinout)
@@ -172,24 +172,25 @@ This discards all changes made since the sequence started."
(magit-read-other-branch-or-commit prompt))
(transient-args 'magit-cherry-pick)))
(defun magit--cherry-move-read-args (verb away fn)
(defun magit--cherry-move-read-args (verb away fn &optional allow-detached)
(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))))
(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 (or (magit-get-current-branch)
(and allow-detached (magit-rev-parse "HEAD")))))
(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
@@ -230,7 +231,10 @@ process manually."
(0 nil)
(1 (car branches))
(_ (magit-completing-read
(format "Remove %s cherries from branch" (length commits))
(let ((len (length commits)))
(if (= len 1)
"Remove 1 cherry from branch"
(format "Remove %s cherries from branch" len)))
branches nil t))))))))
(magit--cherry-move commits branch (magit-get-current-branch) args nil t))
@@ -239,13 +243,20 @@ process manually."
"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."
process manually. `HEAD' is allowed to be detached initially."
(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))
(list (magit-read-other-branch
(let ((len (length commits)))
(if (= len 1)
"Move 1 cherry to branch"
(format "Move %s cherries to branch" len))))))
'allow-detached))
(magit--cherry-move commits
(or (magit-get-current-branch)
(magit-rev-parse "HEAD"))
branch args))
;;;###autoload
(defun magit-cherry-spinout (commits branch start-point &optional args)
@@ -436,6 +447,7 @@ without prompting."
:description "Remove leading slashes from paths"
:class 'transient-option
:argument "-p"
:allow-empty t
:reader 'transient-read-number-N+)
;;;###autoload
@@ -498,6 +510,7 @@ This discards all changes made since the sequence started."
(transient-define-prefix magit-rebase ()
"Transplant commits and/or modify existing commits."
:man-page "git-rebase"
:value '("--autostash")
["Arguments"
:if-not magit-rebase-in-progress-p
("-k" "Keep empty commits" "--keep-empty")
@@ -669,8 +682,13 @@ START has to be selected from a list of recent commits."
(unless (member "--root" args) commit)))
(magit-log-select
`(lambda (commit)
(magit-rebase-interactive-1 commit (list ,@args)
,message ,editor ,delay-edit-confirm ,noassert))
;; In some cases (currently just magit-rebase-remove-commit), "-c
;; commentChar=#" is added to the global arguments for git. Ensure
;; that the same happens when we chose the commit via
;; magit-log-select, below.
(let ((magit-git-global-arguments (list ,@magit-git-global-arguments)))
(magit-rebase-interactive-1 commit (list ,@args)
,message ,editor ,delay-edit-confirm ,noassert)))
message)))
(defvar magit--rebase-published-symbol nil)
@@ -755,10 +773,14 @@ START has to be selected from a list of recent commits."
"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))
;; magit-rebase--perl-editor assumes that the comment character is "#".
(let ((magit-git-global-arguments
(nconc (list "-c" "core.commentChar=#")
magit-git-global-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))))
@@ -1033,12 +1055,12 @@ status buffer (i.e. the reverse of how they will be applied)."
(t
(list "done" rev 'magit-sequence-done)))))
(magit-sequence-insert-commit "onto" onto
(if (equal onto head)
'magit-sequence-head
'magit-sequence-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-section (commit hash)
(magit-insert-heading
(propertize type 'font-lock-face face) "\s"
(magit-format-rev-summary hash) "\n")))

View File

@@ -1,6 +1,6 @@
;;; magit-stash.el --- stash support for Magit -*- lexical-binding: t -*-
;; Copyright (C) 2008-2021 The Magit Project Contributors
;; Copyright (C) 2008-2022 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.
@@ -8,6 +8,8 @@
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; SPDX-License-Identifier: GPL-3.0-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)
@@ -27,15 +29,9 @@
;;; Code:
(eval-when-compile
(require 'subr-x))
(require 'magit)
(require 'magit-reflog)
;; For `magit-stash-drop'.
(defvar helm-comp-read-use-marked)
;;; Options
(defgroup magit-stash nil
@@ -126,7 +122,14 @@ AUTHOR-WIDTH has to be an integer. When the name of the author
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))
(interactive
(progn (when (and (magit-merge-in-progress-p)
(not (magit-y-or-n-p "\
Stashing and resetting during a merge conflict. \
Applying the resulting stash won't restore the merge state. \
Proceed anyway? ")))
(user-error "Abort"))
(magit-stash-read-args)))
(magit-stash-save message t t include-untracked t))
;;;###autoload
@@ -217,6 +220,7 @@ are staged changes, apply without preserving the stash index."
(magit-refresh)
(magit-run-git "stash" "apply" stash)))
;;;###autoload
(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
@@ -234,21 +238,14 @@ 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)
(let ((helm-comp-read-use-marked t))
(magit-read-stash "Drop stash")))))
(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-call-git "stash" "drop" stash))
(magit-refresh))
;;;###autoload
@@ -273,7 +270,7 @@ 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))
(let ((magit-inhibit-refresh t))
(magit-branch-and-checkout branch (or (magit-get-current-branch) "HEAD")))
(magit-stash-apply stash))

View File

@@ -1,6 +1,6 @@
;;; magit-status.el --- the grand overview -*- lexical-binding: t -*-
;; Copyright (C) 2010-2021 The Magit Project Contributors
;; Copyright (C) 2010-2022 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.
@@ -8,6 +8,8 @@
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; SPDX-License-Identifier: GPL-3.0-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)
@@ -27,9 +29,6 @@
;;; Code:
(eval-when-compile
(require 'subr-x))
(require 'magit)
;;; Options
@@ -269,8 +268,9 @@ 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)))
(progn (magit--assert-usable-git)
(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
@@ -309,6 +309,30 @@ also contains other useful hints.")
(put 'magit-status-here 'interactive-only 'magit-status-setup-buffer)
;;;###autoload
(defun magit-status-quick ()
"Show the status of the current Git repository, maybe without refreshing.
If the status buffer of the current Git repository exists but
isn't being displayed in the selected frame, then display it
without refreshing it.
If the status buffer is being displayed in the selected frame,
then also refresh it.
Prefix arguments have the same meaning as for `magit-status',
and additionally cause the buffer to be refresh.
To use this function instead of `magit-status', add this to your
init file: (global-set-key (kbd \"C-x g\") 'magit-status-quick)."
(interactive)
(if-let ((buffer
(and (not current-prefix-arg)
(not (magit-get-mode-buffer 'magit-status-mode nil 'selected))
(magit-get-mode-buffer 'magit-status-mode))))
(magit-display-buffer buffer)
(call-interactively #'magit-status)))
(defvar magit--remotes-using-recent-git nil)
(defun magit--tramp-asserts (directory)
@@ -324,25 +348,14 @@ 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))
Check the value of `magit-remote-git-executable' and consult
the info node `(tramp)Remote programs'.
" 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)))))
Check the value of `magit-remote-git-executable' and consult
the info node `(tramp)Remote programs'." remote) :error)))))
;;; Mode
@@ -386,7 +399,8 @@ doesn't find the executable, then consult the info node
("a " "Assumed unstaged" magit-jump-to-assume-unchanged
:if (lambda () (memq 'magit-insert-assume-unchanged-files magit-status-sections-hook)))
("w " "Skip worktree" magit-jump-to-skip-worktree
:if (lambda () (memq 'magit-insert-skip-worktree-files magit-status-sections-hook)))]])
:if (lambda () (memq 'magit-insert-skip-worktree-files magit-status-sections-hook)))]
[("i" "Using Imenu" imenu)]])
(define-derived-mode magit-status-mode magit-mode "Magit"
"Mode for looking at Git status.
@@ -537,8 +551,7 @@ the status buffer causes this section to disappear again."
(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))
(insert (propertize magit-this-error 'font-lock-face 'error))
(when-let ((key (car (where-is-internal 'magit-process-buffer))))
(insert (format " [Type `%s' for details]" (key-description key))))
(insert ?\n))
@@ -623,17 +636,18 @@ arguments are for internal use only."
((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-local) " "
(propertize "does not exist"
'font-lock-face 'magit-branch-warning))
(format
"%s %s %s"
(propertize merge 'font-lock-face 'magit-branch-remote)
(propertize " does not exist on "
'font-lock-face 'font-lock-warning-face)
(propertize "does not exist on"
'font-lock-face 'magit-branch-warning)
(propertize remote 'font-lock-face 'magit-branch-remote))))
(t
(propertize "invalid upstream configuration"
'font-lock-face 'font-lock-warning-face)))))
'font-lock-face 'magit-branch-warning)))))
(insert ?\n))))))
(defun magit-insert-push-branch-header ()
@@ -655,12 +669,12 @@ arguments are for internal use only."
"(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))))))
(concat target " "
(propertize "does not exist"
'font-lock-face 'magit-branch-warning))
(concat remote " "
(propertize "remote does not exist"
'font-lock-face 'magit-branch-warning))))))
(insert ?\n))))
(defun magit-insert-tags-header ()

View File

@@ -1,6 +1,6 @@
;;; magit-submodule.el --- submodule support for Magit -*- lexical-binding: t -*-
;; Copyright (C) 2011-2021 The Magit Project Contributors
;; Copyright (C) 2011-2022 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.
@@ -8,6 +8,8 @@
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; SPDX-License-Identifier: GPL-3.0-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)
@@ -23,12 +25,10 @@
;;; Code:
(eval-when-compile
(require 'subr-x))
(require 'magit)
(defvar x-stretch-cursor)
;;; Options
(defcustom magit-module-sections-hook
@@ -83,9 +83,15 @@ 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'."
an alist that supports the keys `:right-align' and `:pad-right'.
You may wish to display a range of numeric columns using just one
character per column and without any padding between columns, in
which case you should use an appropriat HEADER, set WIDTH to 1,
and set `:pad-right' to 0. \"+\" is substituted for numbers higher
than 9."
:package-version '(magit . "2.8.0")
:group 'magit-repolist-mode
:group 'magit-repolist
:type `(repeat (list :tag "Column"
(string :tag "Header Label")
(integer :tag "Column Width")
@@ -97,6 +103,18 @@ an alist that supports the keys `:right-align' and `:pad-right'."
(symbol))
(sexp :tag "Value"))))))
(defcustom magit-submodule-list-sort-key '("Path" . nil)
"Initial sort key for buffer created by `magit-list-submodules'.
If nil, no additional sorting is performed. Otherwise, this
should be a cons cell (NAME . FLIP). NAME is a string matching
one of the column names in `magit-submodule-list-columns'. FLIP,
if non-nil, means to invert the resulting sort."
:package-version '(magit . "3.2.0")
:group 'magit-repolist
:type '(choice (const nil)
(cons (string :tag "Column name")
(boolean :tag "Flip order"))))
(defcustom magit-submodule-remove-trash-gitdirs nil
"Whether `magit-submodule-remove' offers to trash module gitdirs.
@@ -584,13 +602,7 @@ These sections can be expanded to show the respective commits."
(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))
(magit-submodule-list-setup magit-submodule-list-columns))
(defvar magit-submodule-list-mode-map
(let ((map (make-sparse-keymap)))
@@ -601,36 +613,63 @@ These sections can be expanded to show the respective commits."
(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)
(setq-local x-stretch-cursor nil)
(setq tabulated-list-padding 0)
(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))
(defvar-local magit-submodule-list-predicate nil)
(defun magit-submodule-list-setup (columns &optional predicate)
(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)
(setq-local magit-repolist-columns columns)
(setq-local magit-submodule-list-predicate predicate)
(magit-submodule-list-refresh))
(defun magit-submodule-list-refresh ()
(unless tabulated-list-sort-key
(setq tabulated-list-sort-key
(pcase-let ((`(,column . ,flip) magit-submodule-list-sort-key))
(cons (or (car (assoc column magit-submodule-list-columns))
(caar magit-submodule-list-columns))
flip))))
(setq tabulated-list-format
(vconcat (mapcar (pcase-lambda (`(,title ,width ,_fn ,props))
(nconc (list title width t)
(-flatten props)))
magit-repolist-columns)))
(setq tabulated-list-entries
(-keep (lambda (module)
(let ((default-directory
(expand-file-name (file-name-as-directory module))))
(and (file-exists-p ".git")
(or (not magit-submodule-list-predicate)
(funcall magit-submodule-list-predicate module))
(list module
(vconcat
(--map (or (funcall (nth 2 it) module) "")
magit-submodule-list-columns))))))
(magit-list-module-paths))))
(mapcar (pcase-lambda (`(,title ,width ,fn ,props))
(or (funcall fn `((:path ,module)
(:title ,title)
(:width ,width)
,@props))
""))
magit-repolist-columns))))))
(magit-list-module-paths)))
(message "Listing submodules...")
(tabulated-list-init-header)
(tabulated-list-print t)
(message "Listing submodules...done"))
(defun magit-modulelist-column-path (path)
(defun magit-modulelist-column-path (spec)
"Insert the relative path of the submodule."
path)
(cadr (assq :path spec)))
;;; Utilities

View File

@@ -1,6 +1,6 @@
;;; magit-subtree.el --- subtree support for Magit -*- lexical-binding: t -*-
;; Copyright (C) 2011-2021 The Magit Project Contributors
;; Copyright (C) 2011-2022 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.
@@ -8,6 +8,8 @@
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; SPDX-License-Identifier: GPL-3.0-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)

View File

@@ -1,6 +1,6 @@
;;; magit-tag.el --- tag functionality -*- lexical-binding: t -*-
;; Copyright (C) 2010-2021 The Magit Project Contributors
;; Copyright (C) 2010-2022 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.
@@ -8,6 +8,8 @@
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; SPDX-License-Identifier: GPL-3.0-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)
@@ -56,7 +58,7 @@
:class 'transient-option
:shortarg "-u"
:argument "--local-user="
:reader 'magit-read-gpg-secret-key
:reader 'magit-read-gpg-signing-key
:history-key 'magit:--gpg-sign)
;;;###autoload

View File

@@ -1,6 +1,6 @@
;;; magit-transient.el --- support for transients -*- lexical-binding: t -*-
;; Copyright (C) 2008-2021 The Magit Project Contributors
;; Copyright (C) 2008-2022 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.
@@ -8,6 +8,8 @@
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; SPDX-License-Identifier: GPL-3.0-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)
@@ -28,15 +30,12 @@
;;; Code:
(eval-when-compile
(require 'subr-x))
(require 'transient)
(require 'magit-git)
(require 'magit-mode)
(require 'magit-process)
(require 'transient)
;;; Classes
(defclass magit--git-variable (transient-variable)
@@ -199,4 +198,3 @@
;;; _
(provide 'magit-transient)
;;; magit-transient.el ends here

View File

@@ -1,6 +1,6 @@
;;; magit-utils.el --- various utilities -*- lexical-binding: t; coding: utf-8 -*-
;; Copyright (C) 2010-2021 The Magit Project Contributors
;; Copyright (C) 2010-2022 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.
@@ -11,6 +11,8 @@
;; Contains code from GNU Emacs https://www.gnu.org/software/emacs,
;; released under the GNU General Public License version 3 or later.
;; SPDX-License-Identifier: GPL-3.0-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)
@@ -40,17 +42,13 @@
(require 'cl-lib)
(require 'dash)
(eval-when-compile
(require 'subr-x))
(require 'eieio)
(require 'seq)
(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))
@@ -108,7 +106,8 @@ alphabetical order, depending on your version of Ivy."
(forge-edit-topic-note nil t)
(forge-pull-pullreq nil t)
(forge-visit-issue nil t)
(forge-visit-pullreq nil t))
(forge-visit-pullreq nil t)
(forge-visit-topic nil t))
"When not to offer alternatives and ask for confirmation.
Many commands by default ask the user to select from a list of
@@ -161,6 +160,7 @@ The value has the form ((COMMAND nil|PROMPT DEFAULT)...).
(const abort-merge)
(const merge-dirty)
(const delete-unmerged-branch)
(const delete-branch-on-remote)
(const delete-pr-remote)
(const drop-stashes)
(const set-and-push)
@@ -241,6 +241,13 @@ References:
choice (or selecting another branch), but when a branch has
not been merged yet, also make sure the user is aware of that.
`delete-branch-on-remote' Deleting a \"remote branch\" may mean
deleting the (local) \"remote-tracking\" branch only, or also
removing it from the remote itself. The latter often makes more
sense because otherwise simply fetching from the remote would
restore the remote-tracking branch, but doing that can be
surprising and hard to recover from, so we ask.
`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
@@ -271,11 +278,11 @@ Edit published history:
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\".
`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
modify a commit other than `HEAD', namely the various fixup
and squash variants.
`edit-published' Affects the commands `magit-edit-line-commit'
@@ -379,14 +386,21 @@ Messages which can currently be suppressed using this option are:
:group 'magit-miscellaneous
:type '(repeat string))
(defcustom magit-ellipsis ?…
"Character used to abbreviate text.
(defcustom magit-ellipsis (if (char-displayable-p ?…) "" "...")
"String used to abbreviate text in process buffers.
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")
Currently this is only used to elide `magit-git-global-arguments'
in process buffers. In the future it may be used in other places
as well, but not the following:
- Author names in the log margin are always abbreviated using
\"\" or if that is not displayable, then \">\".
- Whether collapsed sections are indicated using ellipsis is
controlled by `magit-section-visibility-indicator'."
:package-version '(magit . "3.0.0")
:group 'magit-miscellaneous
:type 'character)
:type 'string)
(defcustom magit-update-other-window-delay 0.2
"Delay before automatically updating the other window.
@@ -516,21 +530,27 @@ acts similarly to `completing-read', except for the following:
(complete-with-action action collection string pred))))
(defun magit-builtin-completing-read
(prompt choices &optional predicate require-match initial-input hist def)
(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)
(bound-and-true-p vertico-mode)
(bound-and-true-p selectrum-mode))
(setq prompt (magit-prompt-with-default prompt def)))
(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))
(cl-letf (((symbol-function 'completion-pcm--all-completions)))
(when (< emacs-major-version 26)
(fset '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)
(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
@@ -543,6 +563,7 @@ When KEYMAP is nil, it defaults to `crm-local-completion-map'.
Unlike `completing-read-multiple', the return value is not split
into a list."
(declare (obsolete magit-completing-read-multiple* "Magit 3.1.0"))
(let* ((crm-separator (or sep crm-default-separator))
(crm-completion-table (magit--completion-table choices))
(choose-completion-string-functions
@@ -553,8 +574,10 @@ into a list."
(helm-crm-default-separator nil)
(ivy-sort-matches-functions-alist nil)
(input
(cl-letf (((symbol-function 'completion-pcm--all-completions)
#'magit-completion-pcm--all-completions))
(cl-letf (((symbol-function 'completion-pcm--all-completions)))
(when (< emacs-major-version 26)
(fset '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)
@@ -566,47 +589,78 @@ into a list."
(defun magit-completing-read-multiple*
(prompt table &optional predicate require-match initial-input
hist def inherit-input-method)
hist def inherit-input-method
no-split)
"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)
(ivy-sort-matches-functions-alist 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)))
TABLE and take an additional argument NO-SPLIT, which causes
the user input to be returned as a single unmodified string.
Also work around various incompatible features of various
third-party completion frameworks."
(cl-letf*
(;; To implement NO-SPLIT we have to manipulate the respective
;; `split-string' invocation. We cannot simply advice it to
;; return the input string because `SELECTRUM' would choke on
;; that string. Use a variable to pass along the raw user
;; input string. aa5f098ab
(input nil)
(split-string (symbol-function 'split-string))
((symbol-function 'split-string)
(lambda (string &optional separators omit-nulls trim)
(when (and no-split
(equal separators crm-separator)
(equal omit-nulls t))
(setq input string))
(funcall split-string string separators omit-nulls trim)))
;; In Emacs 25 this function has a bug, so we use a copy of the
;; version from Emacs 26. bef9c7aa3
((symbol-function 'completion-pcm--all-completions)
(if (< emacs-major-version 26)
'magit-completion-pcm--all-completions
(symbol-function 'completion-pcm--all-completions)))
;; Prevent `BUILT-IN' completion from messing up our existing
;; order of the completion candidates. aa5f098ab
(table (magit--completion-table table))
;; Prevent `IVY' from messing up our existing order. c7af78726
(ivy-sort-matches-functions-alist nil)
;; Prevent `HELM' from messing up our existing order. 6fcf994bd
(helm-completion-in-region-default-sort-fn nil)
;; Prevent `HELM' from automatically appending the separator,
;; which is counterproductive when NO-SPLIT is non-nil and/or
;; when reading commit ranges. 798aff564
(helm-crm-default-separator
(if no-split nil (bound-and-true-p helm-crm-default-separator)))
(values
(if (and no-split
(advice-member-p 'consult-completing-read-multiple
'completing-read-multiple))
;; Our NO-SPLIT hack is not compatible with `CONSULT's
;; implemenation so fall back to the original function.
;; #4437
(unwind-protect
(progn
(advice-remove 'completing-read-multiple
'consult-completing-read-multiple)
(completing-read-multiple
prompt table predicate require-match initial-input
hist def inherit-input-method))
(advice-add 'completing-read-multiple :override
'consult-completing-read-multiple))
(completing-read-multiple
prompt table predicate require-match initial-input
hist def inherit-input-method))))
(if no-split input values)))
(defun magit-ido-completing-read
(prompt choices &optional predicate require-match initial-input hist def)
(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)
(if (and (require 'ido-completing-read+ nil t)
(fboundp 'ido-completing-read+))
(ido-completing-read+ prompt choices predicate require-match
initial-input hist
(or def (and require-match (car choices))))
@@ -687,9 +741,11 @@ This is similar to `read-string', but
(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))
(mapconcat #'identity
(list ,@(mapcar #'cadr clauses))
", ")
,(if verbose ", or [C-g] to abort " " "))
',(mapcar #'car clauses))
,@(--map `(,(car it) ,@(cddr it)) clauses))
(message "")))
@@ -786,11 +842,10 @@ See info node `(magit)Debugging Tools' for more information."
"with-editor"
;; Obviously `magit' itself is needed too.
"magit"
;; While this is part of the Magit repository,
;; it is distributed as a separate package.
;; While these are part of the Magit repository,
;; they are distributed as separate packages.
"magit-section"
"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")))
@@ -812,7 +867,11 @@ as STRING."
(i 0))
`(let ((,s ,string))
(let ,(save-match-data
(--map (list it (list 'match-string (cl-incf i) s)) varlist))
(cl-mapcan (lambda (sym)
(cl-incf i)
(and (not (eq (aref (symbol-name sym) 0) ?_))
(list (list sym (list 'match-string i s)))))
varlist))
,@body))))
(defun magit-delete-line ()
@@ -1001,27 +1060,26 @@ and https://github.com/magit/magit/issues/2295."
(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))))))
(when (< emacs-major-version 26)
;; In Emacs 25 `completion-pcm--all-completions' reverses the
;; completion list. This is the version from Emacs 26, which
;; fixes that issue. 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)))
(nreverse poss)))))))
(defun magit-which-function ()
"Return current function name based on point.
@@ -1140,67 +1198,6 @@ See <https://github.com/raxod502/straight.el/issues/520>."
(setq filename target))))
(file-chase-links filename))
;;; 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)

View File

@@ -1,6 +1,6 @@
;;; magit-version.el --- the Magit version you are using
(setq magit-version "20210105.1030")
(setq magit-version "3.3.0")
(provide 'migit-version)

View File

@@ -1,6 +1,6 @@
;;; magit-wip.el --- commit snapshots to work-in-progress refs -*- lexical-binding: t -*-
;; Copyright (C) 2010-2021 The Magit Project Contributors
;; Copyright (C) 2010-2022 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.
@@ -8,6 +8,8 @@
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; SPDX-License-Identifier: GPL-3.0-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)
@@ -30,9 +32,6 @@
;;; Code:
(eval-when-compile
(require 'subr-x))
(require 'magit-core)
(require 'magit-log)
@@ -288,30 +287,35 @@ commit message."
(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 (list "--reset" "-i")
(if files
;; Note: `update-index' is used instead of `add'
;; because `add' will fail if a file is already
;; deleted in the temporary index.
(magit-call-git
"update-index" "--add" "--remove"
(and (pcase (magit-repository-local-get
'update-index-has-ignore-sw-p 'unset)
(`unset
(let ((val (version<= "2.25.0"
(magit-git-version))))
(magit-repository-local-set
'update-index-has-ignore-sw-p val)
val))
(val val))
"--ignore-skip-worktree-entries")
"--" 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")))
(when (or (not files)
;; `update-index' will either ignore (before Git v2.32.0)
;; or fail when passed directories (relevant for the
;; untracked files code paths).
(setq files (seq-remove #'file-directory-p files)))
(let* ((wipref (magit--wip-wtree-ref ref))
(parent (magit-wip-get-parent ref wipref))
(tree (magit-with-temp-index parent (list "--reset" "-i")
(if files
;; Note: `update-index' is used instead of `add'
;; because `add' will fail if a file is already
;; deleted in the temporary index.
(magit-call-git
"update-index" "--add" "--remove"
(and (pcase (magit-repository-local-get
'update-index-has-ignore-sw-p 'unset)
(`unset
(let ((val (version<= "2.25.0"
(magit-git-version))))
(magit-repository-local-set
'update-index-has-ignore-sw-p val)
val))
(val val))
"--ignore-skip-worktree-entries")
"--" 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
@@ -443,7 +447,10 @@ many \"branches\" of each wip ref are shown."
(when-let ((reflog (magit-git-lines "reflog" wipref)))
(let (tips)
(while (and reflog (> count 1))
(setq reflog (cl-member "^[^ ]+ [^:]+: restart autosaving"
;; "start autosaving ..." is the current message, but it used
;; to be "restart autosaving ...", and those messages may
;; still be around (e.g., if gc.reflogExpire is to "never").
(setq reflog (cl-member "^[^ ]+ [^:]+: \\(?:re\\)?start autosaving"
reflog :test #'string-match-p))
(when (and (cadr reflog)
(string-match "^[^ ]+ \\([^:]+\\)" (cadr reflog)))

View File

@@ -1,6 +1,6 @@
;;; magit-worktree.el --- worktree support -*- lexical-binding: t -*-
;; Copyright (C) 2010-2021 The Magit Project Contributors
;; Copyright (C) 2010-2022 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.
@@ -8,6 +8,8 @@
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; SPDX-License-Identifier: GPL-3.0-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)
@@ -62,7 +64,7 @@ Used by `magit-worktree-checkout' and `magit-worktree-branch'."
(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-run-git "worktree" "add" (magit--expand-worktree path) branch)
(magit-diff-visit-directory path))
;;;###autoload
@@ -74,7 +76,7 @@ Used by `magit-worktree-checkout' and `magit-worktree-branch'."
,@(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)
branch (magit--expand-worktree path) start-point)
(magit-diff-visit-directory path))
;;;###autoload
@@ -91,7 +93,7 @@ Used by `magit-worktree-checkout' and `magit-worktree-branch'."
(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)))
(magit--expand-worktree path)))
(not (file-exists-p default-directory))
(derived-mode-p 'magit-status-mode))
(kill-buffer)
@@ -141,6 +143,9 @@ then show it in Dired instead."
:test #'equal :key #'car)))))
(magit-diff-visit-directory worktree))
(defun magit--expand-worktree (path)
(magit-convert-filename-for-git (expand-file-name path)))
;;; Sections
(defvar magit-worktree-section-map

View File

@@ -1,25 +1,27 @@
;;; magit.el --- A Git porcelain inside Emacs -*- lexical-binding: t; coding: utf-8 -*-
;; Copyright (C) 2008-2021 The Magit Project Contributors
;; Copyright (C) 2008-2022 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 <marius.vollmer@gmail.com>
;; Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
;; Kyle Meyer <kyle@kyleam.com>
;; Noam Postavsky <npostavs@users.sourceforge.net>
;; Kyle Meyer <kyle@kyleam.com>
;; Noam Postavsky <npostavs@users.sourceforge.net>
;; Former-Maintainers:
;; Nicolas Dudebout <nicolas.dudebout@gatech.edu>
;; Peter J. Weisberg <pj@irregularexpressions.net>
;; Phil Jackson <phil@shellarchive.co.uk>
;; Rémi Vanicat <vanicat@debian.org>
;; Yann Hodique <yann.hodique@gmail.com>
;; Nicolas Dudebout <nicolas.dudebout@gatech.edu>
;; Peter J. Weisberg <pj@irregularexpressions.net>
;; Phil Jackson <phil@shellarchive.co.uk>
;; Rémi Vanicat <vanicat@debian.org>
;; Yann Hodique <yann.hodique@gmail.com>
;; Keywords: git tools vc
;; Homepage: https://github.com/magit/magit
;; Magit requires at least GNU Emacs 25.1 and Git 2.2.0.
;; Package-Requires: ((emacs "25.1") (dash "2.19.1") (git-commit "3.3.0") (magit-section "3.3.0") (transient "0.3.6") (with-editor "3.0.5"))
;; Package-Version: 3.3.0
;; SPDX-License-Identifier: GPL-3.0-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
@@ -34,35 +36,34 @@
;; You should have received a copy of the GNU General Public License
;; along with Magit. If not, see http://www.gnu.org/licenses.
;; Magit requires at least GNU Emacs 25.1 and Git 2.2.0.
;;; 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.
;; Magit is a text-based Git user interface that puts an unmatched focus
;; on streamlining workflows. Commands are invoked using short mnemonic
;; key sequences that take the cursors position in the highly actionable
;; interface into account to provide context-sensitive behavior.
;; With Magit you can do nearly everything that you can do when using Git
;; on the command-line, but at greater speed and while taking advantage
;; of advanced features that previously seemed too daunting to use on a
;; daily basis. Many users will find that by using Magit they can become
;; more effective Git user.
;;; 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 'git-commit)
(require 'format-spec)
(require 'package nil t) ; used in `magit-version'
(require 'with-editor)
(defconst magit--minimal-git "2.2.0")
(defconst magit--minimal-emacs "25.1")
@@ -107,8 +108,8 @@ own faces for the `header-line', or for parts of the
: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))
'((((supports (:box t))) :inherit magit-branch-remote :box t)
(t :inherit magit-branch-remote :inverse-video t))
"Face for current branch."
:group 'magit-faces)
@@ -119,8 +120,8 @@ own faces for the `header-line', or for parts of the
: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))
'((((supports (:box t))) :inherit magit-branch-local :box t)
(t :inherit magit-branch-local :inverse-video t))
"Face for current branch."
:group 'magit-faces)
@@ -132,6 +133,11 @@ This face is only used in logs and it gets combined
and/or `magit-branch-remote-head'."
:group 'magit-faces)
(defface magit-branch-warning
'((t :inherit warning))
"Face for warning about (missing) branch."
:group 'magit-faces)
(defface magit-head
'((((class color) (background light)) :inherit magit-branch-local)
(((class color) (background dark)) :inherit magit-branch-local))
@@ -180,7 +186,7 @@ and/or `magit-branch-remote-head'."
:group 'magit-faces)
(defface magit-signature-untrusted
'((t :foreground "cyan"))
'((t :foreground "medium aquamarine"))
"Face for good untrusted signatures."
:group 'magit-faces)
@@ -200,7 +206,7 @@ and/or `magit-branch-remote-head'."
:group 'magit-faces)
(defface magit-signature-error
'((t :foreground "firebrick3"))
'((t :foreground "light blue"))
"Face for signatures that cannot be checked (e.g. missing key)."
:group 'magit-faces)
@@ -238,7 +244,7 @@ C-x g magit-status
C-x M-g magit-dispatch
C-c M-g magit-file-dispatch
These bindings may be added when `after-init-hook' is called.
These bindings may be added when `after-init-hook' is run.
Each binding is added if and only if at that time no other key
is bound to the same command and no other command is bound to
the same key. In other words we try to avoid adding bindings
@@ -252,8 +258,14 @@ is loaded or autoloaded) and to increase the likelihood that
all the potentially conflicting user bindings have already
been added.
Setting this variable after the hook has already been called
has no effect.
To set this variable use either `setq' or the Custom interface.
Do not use the function `customize-set-variable' because doing
that would cause Magit to be loaded immediately when that form
is evaluated (this differs from `custom-set-variables', which
doesn't load the libraries that define the customized variables).
Setting this variable to nil has no effect if that is done after
the key bindings have already been added.
We recommend that you bind \"C-c g\" instead of \"C-c M-g\" to
`magit-file-dispatch'. The former is a much better binding
@@ -289,7 +301,10 @@ Also see info node `(magit)Commands for Buffers Visiting Files'."
"Invoke a Magit command from a list of available commands."
:info-manual "(magit)Top"
["Transient and dwim commands"
;; → bound in magit-mode-map or magit-section-mode-map
;; ↓ bound below
[("A" "Apply" magit-cherry-pick)
;; a ↓
("b" "Branch" magit-branch)
("B" "Bisect" magit-bisect)
("c" "Commit" magit-commit)
@@ -297,28 +312,51 @@ Also see info node `(magit)Commands for Buffers Visiting Files'."
("d" "Diff" magit-diff)
("D" "Diff (change)" magit-diff-refresh)
("e" "Ediff (dwim)" magit-ediff-dwim)
("E" "Ediff" magit-ediff)]
[("f" "Fetch" magit-fetch)
("E" "Ediff" magit-ediff)
("f" "Fetch" magit-fetch)
("F" "Pull" magit-pull)
;; g ↓
;; G → magit-refresh-all
("h" "Help" magit-help)
("H" "Section info" magit-describe-section :if-derived magit-mode)]
[("i" "Ignore" magit-gitignore)
("I" "Init" magit-init)
("j" "Jump to section"magit-status-jump :if-mode magit-status-mode)
("j" "Display status" magit-status-quick :if-not-mode magit-status-mode)
("J" "Display buffer" magit-display-repository-buffer)
;; k ↓
;; K → magit-file-untrack
("l" "Log" magit-log)
("L" "Log (change)" magit-log-refresh)
("m" "Merge" magit-merge)
("M" "Remote" magit-remote)
;; n → magit-section-forward
;; N reserved → forge-dispatch
("o" "Submodule" magit-submodule)
("O" "Subtree" magit-subtree)]
[("P" "Push" magit-push)
("r" "Rebase" magit-rebase)
("O" "Subtree" magit-subtree)
;; p magit-section-backward
("P" "Push" magit-push)
;; q → magit-mode-bury-buffer
("Q" "Command" magit-git-command)]
[("r" "Rebase" magit-rebase)
;; R → magit-file-rename
;; s ↓
;; S ↓
("t" "Tag" magit-tag)
("T" "Note" magit-notes)
;; u ↓
;; U ↓
;; v ↓
("V" "Revert" magit-revert)
("w" "Apply patches" magit-am)
("W" "Format patches" magit-patch)
("X" "Reset" magit-reset)]
[("y" "Show Refs" magit-show-refs)
;; x magit-reset-quickly
("X" "Reset" magit-reset)
("y" "Show Refs" magit-show-refs)
("Y" "Cherries" magit-cherry)
("z" "Stash" magit-stash)
("!" "Run" magit-run)
("%" "Worktree" magit-worktree)]]
("Z" "Worktree" magit-worktree)
("!" "Run" magit-run)]]
["Applying changes"
:if-derived magit-mode
[("a" "Apply" magit-apply)
@@ -333,7 +371,7 @@ Also see info node `(magit)Commands for Buffers Visiting Files'."
("g" " refresh current buffer" magit-refresh)
("<tab>" " toggle section at point" magit-section-toggle)
("<return>" "visit thing at point" magit-visit-thing)
("C-h m" " show all key bindings" describe-mode)])
("C-x m" " show all key bindings" describe-mode)])
;;; Git Popup
@@ -350,8 +388,6 @@ This affects `magit-git-command', `magit-git-command-topdir',
;;;###autoload (autoload 'magit-run "magit" nil t)
(transient-define-prefix 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)]
@@ -465,8 +501,10 @@ and Emacs to it."
(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")))
(member (file-name-nondirectory toplib)
'("magit.el" "magit.el.gz")))
(let ((load-suffixes (reverse load-suffixes))) ; prefer .el than .elc
(setq toplib (locate-library "magit"))))
(setq toplib (and toplib (magit--straight-chase-links toplib)))
(push toplib debug)
(when toplib
@@ -526,8 +564,19 @@ and Emacs to it."
(magit-git-string "rev-parse" "HEAD"))))))))
(if (stringp magit-version)
(when print-dest
(princ (format "Magit %s, Git %s, Emacs %s, %s"
(princ (format "Magit %s%s, Git %s, Emacs %s, %s"
(or magit-version "(unknown)")
(or (and (ignore-errors (version< "2008" magit-version))
(ignore-errors
(require 'lisp-mnt)
(and (fboundp 'lm-header)
(format
" [>= %s]"
(with-temp-buffer
(insert-file-contents
(locate-library "magit.el" t))
(lm-header "Package-Version"))))))
"")
(or (let ((magit-git-debug
(lambda (err)
(display-warning '(magit git)
@@ -541,7 +590,7 @@ and Emacs to it."
(setq magit-version 'error)
(when magit-version
(push magit-version debug))
(unless (equal (getenv "TRAVIS") "true")
(unless (equal (getenv "CI") "true")
;; The repository is a sparse clone.
(message "Cannot determine Magit's version %S" debug)))
magit-version))
@@ -550,11 +599,14 @@ and Emacs to it."
(defun magit-debug-git-executable ()
"Display a buffer with information about `magit-git-executable'.
Also include information about `magit-remote-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 (format "magit-remote-git-executable: %S\n"
magit-remote-git-executable))
(insert (concat
(format "magit-git-executable: %S" magit-git-executable)
(and (not (file-name-absolute-p magit-git-executable))
@@ -596,7 +648,7 @@ 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")))
(not (equal (getenv "CI") "true")))
(display-warning 'magit (format "\
Magit requires Git >= %s, you are using %s.
@@ -663,8 +715,8 @@ For X11 something like ~/.xinitrc should work.\n"
(require 'magit-imenu)
(require 'magit-bookmark)))
(eval-after-load 'bookmark
'(require 'magit-bookmark))
(with-eval-after-load 'bookmark
(require 'magit-bookmark))
(if after-init-time
(progn (magit-startup-asserts)

View File

@@ -1,6 +1,6 @@
This is magit.info, produced by makeinfo version 6.5 from magit.texi.
This is magit.info, produced by makeinfo version 6.7 from magit.texi.
Copyright (C) 2015-2021 Jonas Bernoulli <jonas@bernoul.li>
Copyright (C) 2015-2022 Jonas Bernoulli <jonas@bernoul.li>
You can redistribute this document and/or modify it under the terms
of the GNU General Public License as published by the Free Software
@@ -20,172 +20,178 @@ END-INFO-DIR-ENTRY

Indirect:
magit.info-1: 754
magit.info-2: 301793
magit.info-2: 301526

Tag Table:
(Indirect)
Node: Top754
Node: Introduction6512
Node: Installation11235
Node: Installing from Melpa11565
Node: Installing from the Git Repository12638
Node: Post-Installation Tasks15370
Node: Getting Started16655
Node: Interface Concepts21895
Node: Modes and Buffers22256
Node: Switching Buffers24005
Node: Naming Buffers28756
Node: Quitting Windows32063
Node: Automatic Refreshing of Magit Buffers33809
Node: Automatic Saving of File-Visiting Buffers36661
Node: Automatic Reverting of File-Visiting Buffers37846
Node: Risk of Reverting Automatically42841
Node: Sections45223
Node: Section Movement46149
Node: Section Visibility51059
Node: Section Hooks57136
Node: Section Types and Values59543
Node: Section Options60846
Node: Transient Commands61318
Node: Transient Arguments and Buffer Variables62555
Node: Completion Confirmation and the Selection69573
Node: Action Confirmation70017
Node: Completion and Confirmation77833
Node: The Selection81019
Node: The hunk-internal region83918
Node: Support for Completion Frameworks85007
Node: Additional Completion Options89914
Node: Running Git90513
Node: Viewing Git Output90786
Node: Git Process Status91919
Node: Running Git Manually92884
Node: Git Executable95354
Node: Global Git Arguments97636
Node: Inspecting98442
Node: Status Buffer99599
Node: Status Sections103589
Node: Status Header Sections109141
Node: Status Module Sections111771
Node: Status Options114276
Node: Repository List115745
Node: Logging118783
Node: Refreshing Logs121344
Node: Log Buffer122790
Node: Log Margin126646
Node: Select from Log129825
Node: Reflog132050
Node: Cherries133707
Node: Diffing135555
Node: Refreshing Diffs138634
Node: Commands Available in Diffs142213
Node: Diff Options144749
Node: Revision Buffer149787
Node: Ediffing153117
Node: References Buffer156765
Node: References Sections167285
Node: Bisecting168146
Node: Visiting Files and Blobs170498
Node: General-Purpose Visit Commands170968
Node: Visiting Files and Blobs from a Diff171924
Node: Blaming175383
Node: Manipulating181724
Node: Creating Repository182066
Node: Cloning Repository182621
Node: Staging and Unstaging188026
Node: Staging from File-Visiting Buffers192109
Node: Applying193277
Node: Committing195170
Node: Initiating a Commit195753
Node: Editing Commit Messages199138
Node: Using the Revision Stack201941
Node: Commit Pseudo Headers204992
Node: Commit Mode and Hooks206328
Node: Commit Message Conventions209266
Node: Branching211394
Node: The Two Remotes211620
Node: Branch Commands214273
Node: Branch Git Variables226654
Node: Auxiliary Branch Commands232045
Node: Merging233163
Node: Resolving Conflicts237171
Node: Rebasing242172
Node: Editing Rebase Sequences247031
Node: Information About In-Progress Rebase251359
Ref: Information About In-Progress Rebase-Footnote-1260241
Node: Cherry Picking260837
Node: Reverting265168
Node: Resetting266617
Node: Stashing268483
Node: Transferring273184
Node: Remotes273406
Node: Remote Commands273558
Node: Remote Git Variables277639
Node: Fetching278918
Node: Pulling281405
Node: Pushing282451
Node: Plain Patches286204
Node: Maildir Patches287695
Node: Miscellaneous289209
Node: Tagging289523
Node: Notes291440
Node: Submodules293812
Node: Listing Submodules294030
Node: Submodule Transient295436
Node: Subtree297958
Node: Worktree299934
Node: Common Commands301793
Node: Wip Modes303916
Node: Wip Graph308847
Node: Legacy Wip Modes311161
Node: Commands for Buffers Visiting Files314056
Node: Minor Mode for Buffers Visiting Blobs319678
Node: Customizing320489
Node: Per-Repository Configuration322085
Node: Essential Settings324340
Node: Safety324685
Node: Performance326446
Node: Microsoft Windows Performance333614
Node: MacOS Performance334805
Ref: MacOS Performance-Footnote-1335982
Node: Default Bindings336064
Node: Plumbing337919
Node: Calling Git338748
Node: Getting a Value from Git340273
Node: Calling Git for Effect343359
Node: Section Plumbing349881
Node: Creating Sections350109
Node: Section Selection354009
Node: Matching Sections355808
Node: Refreshing Buffers361781
Node: Conventions364929
Node: Theming Faces365121
Node: FAQ373236
Node: FAQ - How to ...?373678
Node: How to pronounce Magit?374091
Node: How to show git's output?374893
Node: How to install the gitman info manual?375679
Node: How to show diffs for gpg-encrypted files?376649
Node: How does branching and pushing work?377245
Node: Can Magit be used as ediff-version-control-package?377608
Node: Should I disable VC?379626
Node: FAQ - Issues and Errors380244
Node: Magit is slow381140
Node: I changed several thousand files at once and now Magit is unusable381354
Node: I am having problems committing382083
Node: I am using MS Windows and cannot push with Magit382564
Node: I am using OS X and SOMETHING works in shell but not in Magit383181
Node: Expanding a file to show the diff causes it to disappear384012
Node: Point is wrong in the COMMIT_EDITMSG buffer384593
Node: The mode-line information isn't always up-to-date385639
Node: A branch and tag sharing the same name breaks SOMETHING386702
Node: My Git hooks work on the command-line but not inside Magit387588
Node: git-commit-mode isn't used when committing from the command-line388434
Node: Point ends up inside invisible text when jumping to a file-visiting buffer390705
Node: Debugging Tools391503
Node: Keystroke Index393682
Node: Command Index427788
Node: Function Index464927
Node: Variable Index481198
Node: Introduction6610
Node: Installation11326
Node: Installing from Melpa11656
Node: Installing from the Git Repository12729
Node: Post-Installation Tasks15461
Node: Getting Started16746
Node: Interface Concepts21986
Node: Modes and Buffers22347
Node: Switching Buffers24058
Node: Naming Buffers28797
Node: Quitting Windows32100
Node: Automatic Refreshing of Magit Buffers33838
Node: Automatic Saving of File-Visiting Buffers36719
Node: Automatic Reverting of File-Visiting Buffers37903
Node: Risk of Reverting Automatically42888
Node: Sections45270
Node: Section Movement46196
Node: Section Visibility51070
Node: Section Hooks57085
Node: Section Types and Values59491
Node: Section Options60906
Node: Transient Commands61377
Node: Transient Arguments and Buffer Variables62609
Node: Completion Confirmation and the Selection69620
Node: Action Confirmation70064
Node: Completion and Confirmation77916
Node: The Selection81101
Node: The hunk-internal region83999
Node: Support for Completion Frameworks85088
Node: Additional Completion Options89991
Node: Running Git90589
Node: Viewing Git Output90862
Node: Git Process Status92956
Node: Running Git Manually93921
Node: Git Executable96354
Node: Global Git Arguments99362
Node: Inspecting100167
Node: Status Buffer101324
Node: Status Sections106334
Node: Status Header Sections111861
Node: Status Module Sections114480
Node: Status Options116977
Node: Repository List118440
Node: Logging121766
Node: Refreshing Logs124292
Node: Log Buffer125713
Node: Log Margin129911
Node: Select from Log133064
Node: Reflog135274
Node: Cherries136911
Node: Diffing138749
Node: Refreshing Diffs141783
Node: Commands Available in Diffs145292
Node: Diff Options147804
Node: Revision Buffer153268
Node: Ediffing156588
Node: References Buffer160183
Node: References Sections170777
Node: Bisecting171634
Node: Visiting Files and Blobs173945
Node: General-Purpose Visit Commands174415
Node: Visiting Files and Blobs from a Diff175368
Node: Blaming178812
Node: Manipulating184949
Node: Creating Repository185291
Node: Cloning Repository185828
Node: Staging and Unstaging191188
Node: Staging from File-Visiting Buffers195169
Node: Applying196275
Node: Committing198348
Node: Initiating a Commit198931
Node: Editing Commit Messages204120
Node: Using the Revision Stack206893
Node: Commit Pseudo Headers209938
Node: Commit Mode and Hooks211233
Node: Commit Message Conventions214161
Node: Branching216284
Node: The Two Remotes216510
Node: Branch Commands219163
Node: Branch Git Variables231708
Node: Auxiliary Branch Commands237081
Node: Merging238197
Node: Resolving Conflicts242155
Node: Rebasing247526
Node: Editing Rebase Sequences252315
Node: Information About In-Progress Rebase256529
Ref: Information About In-Progress Rebase-Footnote-1265411
Node: Cherry Picking266007
Node: Reverting270341
Node: Resetting271760
Node: Stashing273586
Node: Transferring278197
Node: Remotes278419
Node: Remote Commands278571
Node: Remote Git Variables282610
Node: Fetching283884
Node: Pulling286330
Node: Pushing287356
Node: Plain Patches291647
Node: Maildir Patches293118
Node: Miscellaneous294597
Node: Tagging294922
Node: Notes296815
Node: Submodules299150
Node: Listing Submodules299368
Node: Submodule Transient301526
Node: Subtree304003
Node: Worktree305934
Node: Bundle307000
Node: Common Commands307367
Node: Wip Modes309995
Node: Wip Graph314886
Node: Legacy Wip Modes317199
Node: Commands for Buffers Visiting Files320086
Node: Minor Mode for Buffers Visiting Blobs325642
Node: Customizing326440
Node: Per-Repository Configuration328036
Node: Essential Settings330290
Node: Safety330635
Node: Performance332396
Ref: Log Performance335425
Ref: Diff Performance336735
Ref: Refs Buffer Performance338076
Ref: Committing Performance338651
Node: Microsoft Windows Performance339564
Node: MacOS Performance340755
Ref: MacOS Performance-Footnote-1341460
Node: Default Bindings341542
Node: Plumbing343783
Node: Calling Git344612
Node: Getting a Value from Git346137
Node: Calling Git for Effect349865
Node: Section Plumbing355759
Node: Creating Sections355987
Node: Section Selection359883
Node: Matching Sections361679
Node: Refreshing Buffers367600
Node: Conventions370744
Node: Theming Faces370936
Node: FAQ379041
Node: FAQ - How to ...?379483
Node: How to pronounce Magit?379896
Node: How to show git's output?380698
Node: How to install the gitman info manual?381484
Node: How to show diffs for gpg-encrypted files?382454
Node: How does branching and pushing work?383050
Node: Can Magit be used as ediff-version-control-package?383413
Node: Should I disable VC?385431
Node: FAQ - Issues and Errors386049
Node: Magit is slow387050
Node: I changed several thousand files at once and now Magit is unusable387264
Node: I am having problems committing387993
Node: I am using MS Windows and cannot push with Magit388474
Node: I am using OS X and SOMETHING works in shell but not in Magit389091
Node: Expanding a file to show the diff causes it to disappear389922
Node: Point is wrong in the COMMIT_EDITMSG buffer390503
Node: The mode-line information isn't always up-to-date391549
Node: A branch and tag sharing the same name breaks SOMETHING392612
Node: My Git hooks work on the command-line but not inside Magit393498
Node: git-commit-mode isn't used when committing from the command-line394344
Node: Point ends up inside invisible text when jumping to a file-visiting buffer396615
Node: I am unable to stage when using Tramp from MS Windows397475
Node: I am no longer able to save popup defaults398382
Node: Debugging Tools399342
Node: Keystroke Index401346
Node: Function and Command Index434443
Node: Variable Index485169

End Tag Table

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff