update of packages

This commit is contained in:
2023-11-04 19:26:41 +01:00
parent e162a12b58
commit 3b54a3236d
726 changed files with 297673 additions and 34585 deletions

View File

@@ -1,7 +1,4 @@
The following people have contributed to Magit, including the
libraries `git-commit.el`, `magit-popup.el`, and `with-editor.el`
which are distributed as separate Elpa packages.
The following people have contributed to Magit.
For statistics see https://magit.vc/stats/magit/authors.html.
Authors
@@ -48,6 +45,7 @@ All Contributors
- Alex Dunn
- Alexey Voinov
- Alex Kost
- Alex Kreisher
- Alex Ott
- Allen Li
- Andreas Fuchs
@@ -96,7 +94,9 @@ All Contributors
- Chris Shoemaker
- Christian Dietrich
- Christian Kluge
- Christian Tietze
- Christophe Junke
- Christopher Carlile
- Christopher Monsanto
- Clément Pit-Claudel
- Cornelius Mika
@@ -114,6 +114,7 @@ All Contributors
- Daniel Kraus
- Daniel Mai
- Daniel Martín
- Daniel Mendler
- Daniel Nagy
- Dan Kessler
- Dan LaManna
@@ -136,9 +137,11 @@ All Contributors
- Eric Prud'hommeaux
- Eric Schulte
- Erik Anderson
- Eugene Mikhaylov
- Evan Torrie
- Evgkeni Sampelnikof
- Eyal Lotem
- Eyal Soha
- Fabian Wiget
- Felix Geller
- Felix Yan
@@ -216,6 +219,7 @@ All Contributors
- Laverne Schrock
- Leandro Facchinetti
- Lele Gaifax
- Lénaïc Huard
- Leo Liu
- Leonardo Etcheverry
- Leo Vivier
@@ -243,6 +247,7 @@ All Contributors
- Mark Hepburn
- Mark Karpov
- Mark Oteiza
- Markus Beppler
- Martin Joerg
- Martin Polden
- Matthew Fluet
@@ -264,6 +269,7 @@ All Contributors
- Natalie Weizenbaum
- Nguyễn Tuấn Anh
- Nic Ferier
- Nicholas Vollmer
- Nick Alcock
- Nick Alexander
- Nick Dimiduk
@@ -302,6 +308,7 @@ All Contributors
- rabio
- Radon Rosborough
- Rafael Laboissiere
- Rahul Rameshbabu
- Raimon Grau
- Ramkumar Ramachandra
- Remco van 't Veer
@@ -333,6 +340,7 @@ All Contributors
- Sergey Pashinin
- Sergey Vinokurov
- Servilio Afre Puentes
- shoefone
- Shuguang Sun
- Siavash Askari Nasr
- Silent Sphere
@@ -370,6 +378,7 @@ All Contributors
- Troy Hinckley
- Tsuyoshi Kitamoto
- Tunc Uzlu
- Ulrich Müller
- Vineet Naik
- Vitaly Ostashov
- Vladimir Ivanov
@@ -392,4 +401,5 @@ All Contributors
- Zach Latta
- zakora
- Zhu Zihao
- ziggy
- zilongshanren

View File

@@ -1,6 +1,6 @@
;;; git-rebase.el --- Edit Git rebase files -*- lexical-binding:t -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Author: Phil Jackson <phil@shellarchive.co.uk>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
@@ -25,7 +25,7 @@
;; This package assists the user in editing the list of commits to be
;; rewritten during an interactive rebase.
;; When the user initiates an interactive rebase, e.g. using "r e" in
;; When the user initiates an interactive rebase, e.g., using "r e" in
;; a Magit buffer or on the command line using "git rebase -i REV",
;; Git invokes the `$GIT_SEQUENCE_EDITOR' (or if that is undefined
;; `$GIT_EDITOR' or even `$EDITOR') letting the user rearrange, drop,
@@ -36,7 +36,7 @@
;; providing the following commands:
;;
;; C-c C-c Tell Git to make it happen.
;; C-c C-k Tell Git that you changed your mind, i.e. abort.
;; C-c C-k Tell Git that you changed your mind, i.e., abort.
;;
;; p Move point to previous line.
;; n Move point to next line.
@@ -143,42 +143,39 @@
;;; Keymaps
(defvar git-rebase-mode-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map special-mode-map)
(define-key map (kbd "C-m") #'git-rebase-show-commit)
(define-key map (kbd "p") #'git-rebase-backward-line)
(define-key map (kbd "n") #'forward-line)
(define-key map (kbd "M-p") #'git-rebase-move-line-up)
(define-key map (kbd "M-n") #'git-rebase-move-line-down)
(define-key map (kbd "c") #'git-rebase-pick)
(define-key map (kbd "k") #'git-rebase-kill-line)
(define-key map (kbd "C-k") #'git-rebase-kill-line)
(define-key map (kbd "b") #'git-rebase-break)
(define-key map (kbd "e") #'git-rebase-edit)
(define-key map (kbd "l") #'git-rebase-label)
(define-key map (kbd "M M") #'git-rebase-merge)
(define-key map (kbd "M t") #'git-rebase-merge-toggle-editmsg)
(define-key map (kbd "m") #'git-rebase-edit)
(define-key map (kbd "f") #'git-rebase-fixup)
(define-key map (kbd "q") #'undefined)
(define-key map (kbd "r") #'git-rebase-reword)
(define-key map (kbd "w") #'git-rebase-reword)
(define-key map (kbd "s") #'git-rebase-squash)
(define-key map (kbd "t") #'git-rebase-reset)
(define-key map (kbd "u") #'git-rebase-update-ref)
(define-key map (kbd "x") #'git-rebase-exec)
(define-key map (kbd "y") #'git-rebase-insert)
(define-key map (kbd "z") #'git-rebase-noop)
(define-key map (kbd "SPC") #'git-rebase-show-or-scroll-up)
(define-key map (kbd "DEL") #'git-rebase-show-or-scroll-down)
(define-key map (kbd "C-x C-t") #'git-rebase-move-line-up)
(define-key map [M-up] #'git-rebase-move-line-up)
(define-key map [M-down] #'git-rebase-move-line-down)
(define-key map [remap undo] #'git-rebase-undo)
map)
"Keymap for Git-Rebase mode.")
(defvar-keymap git-rebase-mode-map
:doc "Keymap for Git-Rebase mode."
:parent special-mode-map
"C-m" #'git-rebase-show-commit
"p" #'git-rebase-backward-line
"n" #'forward-line
"M-p" #'git-rebase-move-line-up
"M-n" #'git-rebase-move-line-down
"c" #'git-rebase-pick
"k" #'git-rebase-kill-line
"C-k" #'git-rebase-kill-line
"b" #'git-rebase-break
"e" #'git-rebase-edit
"l" #'git-rebase-label
"M M" #'git-rebase-merge
"M t" #'git-rebase-merge-toggle-editmsg
"m" #'git-rebase-edit
"f" #'git-rebase-fixup
"q" #'undefined
"r" #'git-rebase-reword
"w" #'git-rebase-reword
"s" #'git-rebase-squash
"t" #'git-rebase-reset
"u" #'git-rebase-update-ref
"x" #'git-rebase-exec
"y" #'git-rebase-insert
"z" #'git-rebase-noop
"SPC" #'git-rebase-show-or-scroll-up
"DEL" #'git-rebase-show-or-scroll-down
"C-x C-t" #'git-rebase-move-line-up
"M-<up>" #'git-rebase-move-line-up
"M-<down>" #'git-rebase-move-line-down
"<remap> <undo>" #'git-rebase-undo)
(put 'git-rebase-reword :advertised-binding (kbd "r"))
(put 'git-rebase-move-line-up :advertised-binding (kbd "M-p"))
(put 'git-rebase-kill-line :advertised-binding (kbd "k"))
@@ -202,7 +199,7 @@
(defvar git-rebase-command-descriptions
'((with-editor-finish . "tell Git to make it happen")
(with-editor-cancel . "tell Git that you changed your mind, i.e. abort")
(with-editor-cancel . "tell Git that you changed your mind, i.e., abort")
(git-rebase-backward-line . "move point to previous line")
(forward-line . "move point to next line")
(git-rebase-move-line-up . "move the commit at point up")
@@ -467,9 +464,9 @@ If the region is active, act on all lines touched by the region."
"Read an arbitrary commit and insert it below current line."
(interactive (list (magit-read-branch-or-commit "Insert revision")))
(forward-line)
(--if-let (magit-rev-format "%h %s" rev)
(if-let ((info (magit-rev-format "%h %s" rev)))
(let ((inhibit-read-only t))
(insert "pick " it ?\n))
(insert "pick " info ?\n))
(user-error "Unknown revision")))
(defun git-rebase-set-noncommit-action (action value-fn arg)
@@ -656,13 +653,14 @@ Like `undo' but works in read-only buffers."
(let ((magit--disable-save-buffers t))
(save-excursion
(goto-char (line-beginning-position))
(--if-let (with-slots (action-type target) (git-rebase-current-line)
(and (eq action-type 'commit)
target))
(if-let ((rev (with-slots (action-type target)
(git-rebase-current-line)
(and (eq action-type 'commit)
target))))
(pcase scroll
('up (magit-diff-show-or-scroll-up))
('down (magit-diff-show-or-scroll-down))
(_ (apply #'magit-show-commit it
(_ (apply #'magit-show-commit rev
(magit-diff-arguments 'magit-revision-mode))))
(ding)))))
@@ -737,12 +735,13 @@ running \"man git-rebase\" at the command line) for details."
(magit-confirm 'abort-rebase "Abort this rebase" nil 'noabort)))
(defun git-rebase-autostash-save ()
(--when-let (magit-file-line (magit-git-dir "rebase-merge/autostash"))
(push (cons 'stash it) with-editor-cancel-alist)))
(when-let ((rev (magit-file-line
(expand-file-name "rebase-merge/autostash" (magit-gitdir)))))
(push (cons 'stash rev) with-editor-cancel-alist)))
(defun git-rebase-autostash-apply ()
(--when-let (cdr (assq 'stash with-editor-cancel-alist))
(magit-stash-apply it)))
(when-let ((rev (cdr (assq 'stash with-editor-cancel-alist))))
(magit-stash-apply rev)))
(defun git-rebase-match-comment-line (limit)
(re-search-forward (concat git-rebase-comment-re ".*") limit t))
@@ -831,7 +830,7 @@ By default, this is the same except for the \"pick\" command."
(add-hook 'git-rebase-mode-hook #'git-rebase-mode-show-keybindings t)
(defun git-rebase-mode-disable-before-save-hook ()
(set (make-local-variable 'before-save-hook) nil))
(setq-local before-save-hook nil))
(add-hook 'git-rebase-mode-hook #'git-rebase-mode-disable-before-save-hook)

View File

@@ -1,6 +1,6 @@
;;; magit-apply.el --- Apply Git diffs -*- lexical-binding:t -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
@@ -119,19 +119,19 @@ is a member of `magit-post-unstage-hook-commands'."
With a prefix argument fallback to a 3-way merge. Doing
so causes the change to be applied to the index as well."
(interactive (and current-prefix-arg (list "--3way")))
(--when-let (magit-apply--get-selection)
(when-let ((s (magit-apply--get-selection)))
(pcase (list (magit-diff-type) (magit-diff-scope))
(`(,(or 'unstaged 'staged) ,_)
(user-error "Change is already in the working tree"))
(`(untracked ,(or 'file 'files))
(call-interactively #'magit-am))
(`(,_ region) (magit-apply-region it args))
(`(,_ hunk) (magit-apply-hunk it args))
(`(,_ hunks) (magit-apply-hunks it args))
(`(,_ region) (magit-apply-region s args))
(`(,_ hunk) (magit-apply-hunk s args))
(`(,_ hunks) (magit-apply-hunks s args))
(`(rebase-sequence file)
(call-interactively #'magit-patch-apply))
(`(,_ file) (magit-apply-diff it args))
(`(,_ files) (magit-apply-diffs it args)))))
(`(,_ file) (magit-apply-diff s args))
(`(,_ files) (magit-apply-diffs s args)))))
(defun magit-apply--section-content (section)
(buffer-substring-no-properties (if (magit-hunk-section-p section)
@@ -185,38 +185,41 @@ adjusted as \"@@ -10,6 +10,7 @@\" and \"@@ -18,6 +19,7 @@\"."
(defun magit-apply--adjust-hunk-new-start (hunk)
(car (magit-apply--adjust-hunk-new-starts (list hunk))))
(defun magit-apply-hunks (sections &rest args)
(let ((section (oref (car sections) parent)))
(when (string-match "^diff --cc" (oref section value))
(defun magit-apply-hunks (hunks &rest args)
(let ((file (oref (car hunks) parent)))
(when (magit-diff--combined-p file)
(user-error "Cannot un-/stage resolution hunks. Stage the whole file"))
(magit-apply-patch
section args
(concat (oref section header)
file args
(concat (oref file header)
(mapconcat #'identity
(magit-apply--adjust-hunk-new-starts
(mapcar #'magit-apply--section-content sections))
(mapcar #'magit-apply--section-content hunks))
"")))))
(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"))
(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-hunk (hunk &rest args)
(let ((file (oref hunk parent)))
(when (magit-diff--combined-p file)
(user-error "Cannot un-/stage resolution hunks. Stage the whole file"))
(let* ((header (car (oref hunk value)))
(header (and (symbolp header) header))
(content (magit-apply--section-content hunk)))
(magit-apply-patch
file args
(concat (magit-diff-file-header hunk (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))
(user-error "Cannot un-/stage resolution hunks. Stage the whole file"))
(magit-apply-patch (oref section parent) args
(concat (magit-diff-file-header section)
(magit-apply--adjust-hunk-new-start
(magit-diff-hunk-region-patch section args)))))
(defun magit-apply-region (hunk &rest args)
(let ((file (oref hunk parent)))
(when (magit-diff--combined-p file)
(user-error "Cannot un-/stage resolution hunks. Stage the whole file"))
(magit-apply-patch
file args
(concat (magit-diff-file-header hunk)
(magit-apply--adjust-hunk-new-start
(magit-diff-hunk-region-patch hunk args))))))
(defun magit-apply-patch (section:s args patch)
(let* ((files (if (atom section:s)
@@ -262,14 +265,23 @@ adjusted as \"@@ -10,6 +10,7 @@\" and \"@@ -18,6 +19,7 @@\"."
sections))
(t sections)))
(defun magit-apply--diff-ignores-whitespace-p ()
(and (cl-intersection magit-buffer-diff-args
'("--ignore-space-at-eol"
"--ignore-space-change"
"--ignore-all-space"
"--ignore-blank-lines")
:test #'equal)
t))
(defun magit-apply--ignore-whitespace-p (selection type scope)
"Return t if it is necessary and possible to ignore whitespace.
It is necessary to do so when the diff ignores whitespace changes
and whole files are being applied. It is possible when no binary
files are involved. If it is both necessary and impossible, then
return nil, possibly causing whitespace changes to be applied."
(and (memq type '(unstaged staged))
(memq scope '(file files list))
(cl-find-if (lambda (arg)
(member arg '("--ignore-space-at-eol"
"--ignore-space-change"
"--ignore-all-space"
"--ignore-blank-lines")))
magit-buffer-diff-args)
(not (cl-find-if (lambda (section)
(oref section binary))
(ensure-list selection)))))
;;;; Stage
@@ -278,18 +290,20 @@ adjusted as \"@@ -10,6 +10,7 @@\" and \"@@ -18,6 +19,7 @@\"."
With a prefix argument, INTENT, and an untracked file (or files)
at point, stage the file but not its content."
(interactive "P")
(--if-let (and (derived-mode-p 'magit-mode) (magit-apply--get-selection))
(pcase (list (magit-diff-type)
(magit-diff-scope)
(magit-apply--diff-ignores-whitespace-p))
(if-let ((s (and (derived-mode-p 'magit-mode)
(magit-apply--get-selection)))
(type (magit-diff-type))
(scope (magit-diff-scope)))
(pcase (list type scope
(magit-apply--ignore-whitespace-p s type scope))
(`(untracked ,_ ,_) (magit-stage-untracked intent))
(`(unstaged region ,_) (magit-apply-region it "--cached"))
(`(unstaged hunk ,_) (magit-apply-hunk it "--cached"))
(`(unstaged hunks ,_) (magit-apply-hunks it "--cached"))
('(unstaged file t) (magit-apply-diff it "--cached"))
('(unstaged files t) (magit-apply-diffs it "--cached"))
('(unstaged list t) (magit-apply-diffs it "--cached"))
('(unstaged file nil) (magit-stage-1 "-u" (list (oref it value))))
(`(unstaged region ,_) (magit-apply-region s "--cached"))
(`(unstaged hunk ,_) (magit-apply-hunk s "--cached"))
(`(unstaged hunks ,_) (magit-apply-hunks s "--cached"))
('(unstaged file t) (magit-apply-diff s "--cached"))
('(unstaged files t) (magit-apply-diffs s "--cached"))
('(unstaged list t) (magit-apply-diffs s "--cached"))
('(unstaged file nil) (magit-stage-1 "-u" (list (oref s value))))
('(unstaged files nil) (magit-stage-1 "-u" (magit-region-values nil t)))
('(unstaged list nil) (magit-stage-modified))
(`(staged ,_ ,_) (user-error "Already staged"))
@@ -298,23 +312,39 @@ at point, stage the file but not its content."
(call-interactively #'magit-stage-file)))
;;;###autoload
(defun magit-stage-file (file)
"Stage all changes to FILE.
With a prefix argument or when there is no file at point ask for
the file to be staged. Otherwise stage the file at point without
requiring confirmation."
(interactive
(let* ((atpoint (magit-section-value-if 'file))
(current (magit-file-relative-name))
(choices (nconc (magit-unstaged-files)
(magit-untracked-files)))
(default (car (member (or atpoint current) choices))))
(list (if (or current-prefix-arg (not default))
(magit-completing-read "Stage file" choices
nil t nil nil default)
default))))
(defun magit-stage-buffer-file ()
"Stage all changes to the file being visited in the current buffer."
(interactive)
(unless buffer-file-name
(user-error "Not visiting a file"))
(magit-with-toplevel
(magit-stage-1 nil (list file))))
(magit-stage-1 (and (magit-file-ignored-p buffer-file-name)
(if (y-or-n-p "Visited file is ignored; stage anyway?")
"--force"
(user-error "Abort")))
(list (magit-file-relative-name)))))
;;;###autoload
(defun magit-stage-file (files &optional force)
"Read one or more files and stage all changes in those files.
With prefix argument FORCE, offer ignored files for completion."
(interactive
(let* ((choices (if current-prefix-arg
(magit-ignored-files)
(nconc (magit-unstaged-files)
(magit-untracked-files))))
(default (or (magit-section-value-if 'file)
(magit-file-relative-name)))
(default (car (member default choices))))
(list (magit-completing-read-multiple
(if current-prefix-arg "Stage ignored file,s: " "Stage file,s: ")
choices nil t nil nil default)
current-prefix-arg)))
(magit-with-toplevel
;; For backward compatibility, and because of
;; the function's name, don't require a list.
(magit-stage-1 (and force "--force")
(if (listp files) files (list files)))))
;;;###autoload
(defun magit-stage-modified (&optional all)
@@ -383,7 +413,10 @@ ignored) files."
(magit-wip-commit-after-apply files " after stage")))
(defvar magit-post-stage-hook-commands
'(magit-stage magit-stage-file magit-stage-modified))
'(magit-stage
magit-stage-buffer-file
magit-stage-file
magit-stage-modified))
(defun magit-run-post-stage-hook ()
(when (memq this-command magit-post-stage-hook-commands)
@@ -394,21 +427,22 @@ ignored) files."
(defun magit-unstage ()
"Remove the change at point from the staging area."
(interactive)
(--when-let (magit-apply--get-selection)
(pcase (list (magit-diff-type)
(magit-diff-scope)
(magit-apply--diff-ignores-whitespace-p))
(when-let ((s (magit-apply--get-selection))
(type (magit-diff-type))
(scope (magit-diff-scope)))
(pcase (list type scope
(magit-apply--ignore-whitespace-p s type scope))
(`(untracked ,_ ,_) (user-error "Cannot unstage untracked changes"))
(`(unstaged file ,_) (magit-unstage-intent (list (oref it value))))
(`(unstaged file ,_) (magit-unstage-intent (list (oref s value))))
(`(unstaged files ,_) (magit-unstage-intent (magit-region-values nil t)))
(`(unstaged ,_ ,_) (user-error "Already unstaged"))
(`(staged region ,_) (magit-apply-region it "--reverse" "--cached"))
(`(staged hunk ,_) (magit-apply-hunk it "--reverse" "--cached"))
(`(staged hunks ,_) (magit-apply-hunks it "--reverse" "--cached"))
('(staged file t) (magit-apply-diff it "--reverse" "--cached"))
('(staged files t) (magit-apply-diffs it "--reverse" "--cached"))
('(staged list t) (magit-apply-diffs it "--reverse" "--cached"))
('(staged file nil) (magit-unstage-1 (list (oref it value))))
(`(staged region ,_) (magit-apply-region s "--reverse" "--cached"))
(`(staged hunk ,_) (magit-apply-hunk s "--reverse" "--cached"))
(`(staged hunks ,_) (magit-apply-hunks s "--reverse" "--cached"))
('(staged file t) (magit-apply-diff s "--reverse" "--cached"))
('(staged files t) (magit-apply-diffs s "--reverse" "--cached"))
('(staged list t) (magit-apply-diffs s "--reverse" "--cached"))
('(staged file nil) (magit-unstage-1 (list (oref s value))))
('(staged files nil) (magit-unstage-1 (magit-region-values nil t)))
('(staged list nil) (magit-unstage-all))
(`(committed ,_ ,_) (if magit-unstage-committed
@@ -417,22 +451,28 @@ ignored) files."
(`(undefined ,_ ,_) (user-error "Cannot unstage this change")))))
;;;###autoload
(defun magit-unstage-file (file)
"Unstage all changes to FILE.
With a prefix argument or when there is no file at point ask for
the file to be unstaged. Otherwise unstage the file at point
without requiring confirmation."
(interactive
(let* ((atpoint (magit-section-value-if 'file))
(current (magit-file-relative-name))
(choices (magit-staged-files))
(default (car (member (or atpoint current) choices))))
(list (if (or current-prefix-arg (not default))
(magit-completing-read "Unstage file" choices
nil t nil nil default)
default))))
(defun magit-unstage-buffer-file ()
"Unstage all changes to the file being visited in the current buffer."
(interactive)
(unless buffer-file-name
(user-error "Not visiting a file"))
(magit-with-toplevel
(magit-unstage-1 (list file))))
(magit-unstage-1 (list (magit-file-relative-name)))))
;;;###autoload
(defun magit-unstage-file (files)
"Read one or more files and unstage all changes to those files."
(interactive
(let* ((choices (magit-staged-files))
(default (or (magit-section-value-if 'file)
(magit-file-relative-name)))
(default (car (member default choices))))
(list (magit-completing-read-multiple "Unstage file,s: " choices
nil t nil nil default))))
(magit-with-toplevel
;; For backward compatibility, and because of
;; the function's name, don't require a list.
(magit-unstage-1 (if (listp files) files (list files)))))
(defun magit-unstage-1 (files)
(magit-wip-commit-before-change files " before unstage")
@@ -461,7 +501,10 @@ without requiring confirmation."
(magit-wip-commit-after-apply nil " after unstage"))
(defvar magit-post-unstage-hook-commands
'(magit-unstage magit-unstage-file magit-unstage-all))
'(magit-unstage
magit-unstage-buffer-file
magit-unstage-file
magit-unstage-all))
(defun magit-run-post-unstage-hook ()
(when (memq this-command magit-post-unstage-hook-commands)
@@ -476,16 +519,16 @@ 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)
(when-let ((s (magit-apply--get-selection)))
(pcase (list (magit-diff-type) (magit-diff-scope))
(`(committed ,_) (user-error "Cannot discard committed changes"))
(`(undefined ,_) (user-error "Cannot discard this change"))
(`(,_ region) (magit-discard-region it))
(`(,_ hunk) (magit-discard-hunk it))
(`(,_ hunks) (magit-discard-hunks it))
(`(,_ file) (magit-discard-file it))
(`(,_ files) (magit-discard-files it))
(`(,_ list) (magit-discard-files it)))))
(`(,_ region) (magit-discard-region s))
(`(,_ hunk) (magit-discard-hunk s))
(`(,_ hunks) (magit-discard-hunks s))
(`(,_ file) (magit-discard-file s))
(`(,_ files) (magit-discard-files s))
(`(,_ list) (magit-discard-files s)))))
(defun magit-discard-region (section)
(magit-confirm 'discard "Discard region")
@@ -583,7 +626,7 @@ of a side, then keep that side without prompting."
(defun magit-discard-files--resolve (files)
(if-let ((arg (and (cdr files)
(magit-read-char-case
(format "For these %i files\n%s\ncheckout:\n"
(format "For these %d files\n%s\ncheckout:\n"
(length files)
(mapconcat (lambda (file)
(concat " " file))
@@ -630,7 +673,7 @@ of a side, then keep that side without prompting."
(magit-call-git "rm" "--cached" "--force" "--" file))))))
(defun magit-discard-files--rename (files status)
(magit-confirm 'rename "Undo rename %s" "Undo %i renames" nil
(magit-confirm 'rename "Undo rename %s" "Undo %d renames" nil
(mapcar (lambda (file)
(setq file (assoc file status))
(format "%s -> %s" (cadr file) (car file)))
@@ -639,8 +682,8 @@ of a side, then keep that side without prompting."
(let ((orig (cadr (assoc file status))))
(if (file-exists-p file)
(progn
(--when-let (file-name-directory orig)
(make-directory it t))
(when-let ((path (file-name-directory orig)))
(make-directory path t))
(magit-call-git "mv" file orig))
(magit-call-git "rm" "--cached" "--" file)
(magit-call-git "reset" "--" orig)))))
@@ -681,16 +724,16 @@ of a side, then keep that side without prompting."
With a prefix argument fallback to a 3-way merge. Doing
so causes the change to be applied to the index as well."
(interactive (and current-prefix-arg (list "--3way")))
(--when-let (magit-apply--get-selection)
(when-let ((s (magit-apply--get-selection)))
(pcase (list (magit-diff-type) (magit-diff-scope))
(`(untracked ,_) (user-error "Cannot reverse untracked changes"))
(`(unstaged ,_) (user-error "Cannot reverse unstaged changes"))
(`(,_ region) (magit-reverse-region it args))
(`(,_ hunk) (magit-reverse-hunk it args))
(`(,_ hunks) (magit-reverse-hunks it args))
(`(,_ file) (magit-reverse-file it args))
(`(,_ files) (magit-reverse-files it args))
(`(,_ list) (magit-reverse-files it args)))))
(`(,_ region) (magit-reverse-region s args))
(`(,_ hunk) (magit-reverse-hunk s args))
(`(,_ hunks) (magit-reverse-hunks s args))
(`(,_ file) (magit-reverse-file s args))
(`(,_ files) (magit-reverse-files s args))
(`(,_ list) (magit-reverse-files s args)))))
(defun magit-reverse-region (section args)
(magit-confirm 'reverse "Reverse region")

View File

@@ -1,6 +1,6 @@
;;; magit-autorevert.el --- Revert buffers when files in repository change -*- lexical-binding:t -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
@@ -99,14 +99,14 @@ seconds of user inactivity. That is not desirable."
(defun magit-turn-on-auto-revert-mode-if-desired (&optional file)
(if file
(--when-let (find-buffer-visiting file)
(with-current-buffer it
(when-let ((buffer (find-buffer-visiting file)))
(with-current-buffer buffer
(magit-turn-on-auto-revert-mode-if-desired)))
(when (and (not auto-revert-mode) ; see #3014
(not global-auto-revert-mode) ; see #3460
buffer-file-name
(file-readable-p buffer-file-name)
(compat-executable-find (magit-git-executable) t)
(compat-call executable-find (magit-git-executable) t)
(magit-toplevel)
(or (not magit-auto-revert-tracked-only)
(magit-file-tracked-p buffer-file-name)))
@@ -133,26 +133,30 @@ seconds of user inactivity. That is not desirable."
;; - If the user has set the variable `magit-auto-revert-mode' to nil
;; after loading magit (instead of doing so before loading magit or
;; by using the function), then we should still respect that setting.
;; - If the user sets one of these variables after loading magit and
;; after `after-init-hook' has run, then that won't have an effect
;; and there is nothing we can do about it.
;; - If the user enables `global-auto-revert-mode' after loading magit
;; and after `after-init-hook' has run, then `magit-auto-revert-mode'
;; remains enabled; and there is nothing we can do about it.
;; - However if the init file causes `magit-autorevert' to be loaded
;; and only later it enables `global-auto-revert-mode', then we can
;; and should leave `magit-auto-revert-mode' disabled.
(defun magit-auto-revert-mode--init-kludge ()
"This is an internal kludge to be used on `after-init-hook'.
Do not use this function elsewhere, and don't remove it from
the `after-init-hook'. For more information see the comments
and code surrounding the definition of this function."
(if magit-auto-revert-mode
(let ((start (current-time)))
(magit-message "Turning on magit-auto-revert-mode...")
(magit-auto-revert-mode 1)
(magit-message
"Turning on magit-auto-revert-mode...done%s"
(let ((elapsed (float-time (time-subtract nil start))))
(if (> elapsed 0.2)
(format " (%.3fs, %s buffers checked)" elapsed
(length (buffer-list)))
""))))
(magit-auto-revert-mode -1)))
(if (or (not magit-auto-revert-mode)
(and global-auto-revert-mode (not after-init-time)))
(magit-auto-revert-mode -1)
(let ((start (current-time)))
(magit-message "Turning on magit-auto-revert-mode...")
(magit-auto-revert-mode 1)
(magit-message
"Turning on magit-auto-revert-mode...done%s"
(let ((elapsed (float-time (time-subtract nil start))))
(if (> elapsed 0.2)
(format " (%.3fs, %s buffers checked)" elapsed
(length (buffer-list)))
""))))))
(if after-init-time
;; Since `after-init-hook' has already been
;; run, turn the mode on or off right now.
@@ -247,8 +251,8 @@ defaults to nil) for any BUFFER."
(not auto-revert-buffer-list-filter))
(funcall fn)
(let ((auto-revert-buffer-list
(-filter auto-revert-buffer-list-filter
auto-revert-buffer-list)))
(seq-filter auto-revert-buffer-list-filter
auto-revert-buffer-list)))
(funcall fn))
(unless auto-revert-timer
(auto-revert-set-timer))))

View File

@@ -1,6 +1,6 @@
;;; magit-base.el --- Early birds -*- lexical-binding:t; coding:utf-8 -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
@@ -21,7 +21,7 @@
;; along with Magit. If not, see <https://www.gnu.org/licenses/>.
;; This file contains code taken from GNU Emacs, which is
;; Copyright (C) 1976-2022 Free Software Foundation, Inc.
;; Copyright (C) 1976-2023 Free Software Foundation, Inc.
;;; Commentary:
@@ -37,13 +37,19 @@
(require 'cl-lib)
(require 'compat)
(require 'compat-26)
(require 'compat-27)
(require 'dash)
(require 'eieio)
(require 'seq)
(require 'subr-x)
;; For older Emacs releases we depend on an updated `seq' release from
;; GNU ELPA, for `seq-keep'. Unfortunately something else may already
;; have required `seq', before `package' had a chance to put the more
;; recent version earlier on the `load-path'.
(when (and (featurep' seq)
(not (fboundp 'seq-keep)))
(unload-feature 'seq 'force))
(require 'seq)
(require 'crm)
(require 'magit-section)
@@ -89,26 +95,7 @@ alphabetical order, depending on your version of Ivy."
(magit-stash-branch-here nil t)
(magit-stash-format-patch nil t)
(magit-stash-drop nil ask)
(magit-stash-pop nil ask)
(forge-browse-dwim nil t)
(forge-browse-commit nil t)
(forge-browse-branch nil t)
(forge-browse-remote nil t)
(forge-browse-issue nil t)
(forge-browse-pullreq nil t)
(forge-edit-topic-title nil t)
(forge-edit-topic-state nil t)
(forge-edit-topic-draft nil t)
(forge-edit-topic-milestone nil t)
(forge-edit-topic-labels nil t)
(forge-edit-topic-marks nil t)
(forge-edit-topic-assignees nil t)
(forge-edit-topic-review-requests nil t)
(forge-edit-topic-note nil t)
(forge-pull-pullreq nil t)
(forge-visit-issue nil t)
(forge-visit-pullreq nil t)
(forge-visit-topic nil t))
(magit-stash-pop nil ask))
"When not to offer alternatives and ask for confirmation.
Many commands by default ask the user to select from a list of
@@ -171,6 +158,7 @@ The value has the form ((COMMAND nil|PROMPT DEFAULT)...).
(const remove-modules)
(const remove-dirty-modules)
(const trash-module-gitdirs)
(const stash-apply-3way)
(const kill-process)
(const safe-with-wip)))
@@ -186,7 +174,7 @@ so we don't use the command names but more generic symbols.
Applying changes:
`discard' Discarding one or more changes (i.e. hunks or the
`discard' Discarding one or more changes (i.e., hunks or the
complete diff for a file) loses that change, obviously.
`reverse' Reverting one or more changes can usually be undone
@@ -320,6 +308,11 @@ Removing modules:
Various:
`stash-apply-3way' When a stash cannot be applied using \"git
stash apply\", then Magit uses \"git apply\" instead, possibly
using the \"--3way\" argument, which isn't always perfectly
safe. See also `magit-stash-apply'.
`kill-process' There seldom is a reason to kill a process.
Global settings:
@@ -387,21 +380,50 @@ Messages which can currently be suppressed using this option are:
:group 'magit-miscellaneous
:type '(repeat string))
(defcustom magit-ellipsis (if (char-displayable-p ?…) "" "...")
"String used to abbreviate text in process buffers.
(defcustom magit-verbose-messages nil
"Whether to make certain prompts and messages more verbose.
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:
Occasionally a user suggests that a certain prompt or message
should be more verbose, but I would prefer to keep it as-is
because I don't think that the fact that that one user did not
understand the existing prompt/message means that a large number
of users would have the same difficulty, and that making it more
verbose would actually do a disservice to users who understand
the shorter prompt well enough.
- 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")
Going forward I will start offering both messages when I feel the
suggested longer message is reasonable enough, and the value of
this option decides which will be used. Note that changing the
value of this option affects all such messages and that I do not
intend to add an option per prompt."
:package-version '(magit . "4.0.0")
:group 'magit-miscellaneous
:type 'string)
:type 'boolean)
(defcustom magit-ellipsis
'((margin (?… . ">"))
(t (?… . "...")))
"Characters or strings used to abbreviate text in some buffers.
Each element has the form (WHERE (FANCY . UNIVERSAL)).
FANCY is a single character or nil whereas UNIVERSAL is a string
of any length. The ellipsis produced by `magit--ellipsis' will
be FANCY if it's a non-nil character that can be displayed with
the available fonts, otherwise UNIVERSAL will be used. FANCY is
meant to be a rich character like a horizontal ellipsis symbol or
an emoji whereas UNIVERSAL something simpler available in a less
rich environment like the CLI. WHERE determines the use-case for
the ellipsis definition. Currently the only acceptable values
for WHERE are `margin' or t (representing the default).
Whether collapsed sections are indicated using ellipsis is
controlled by `magit-section-visibility-indicator'."
:package-version '(magit . "4.0.0")
:group 'magit-miscellaneous
:type '(repeat (list (symbol :tag "Where")
(cons (choice :tag "Fancy" character (const nil))
(string :tag "Universal")))))
(defcustom magit-update-other-window-delay 0.2
"Delay before automatically updating the other window.
@@ -449,7 +471,8 @@ and delay of your graphical environment or operating system."
(defclass magit-file-section (magit-diff-section)
((keymap :initform 'magit-file-section-map)
(source :initform nil)
(header :initform nil)))
(header :initform nil)
(binary :initform nil)))
(defclass magit-module-section (magit-file-section)
((keymap :initform 'magit-module-section-map)
@@ -486,9 +509,9 @@ and delay of your graphical environment or operating system."
(defvar magit-completing-read--silent-default nil)
(defun magit-completing-read (prompt collection &optional
predicate require-match initial-input
hist def fallback)
(defun magit-completing-read ( prompt collection &optional
predicate require-match initial-input
hist def fallback)
"Read a choice in the minibuffer, or use the default choice.
This is the function that Magit commands use when they need the
@@ -534,11 +557,11 @@ acts similarly to `completing-read', except for the following:
`magit-builtin-completing-read'."
(setq magit-completing-read--silent-default nil)
(if-let ((dwim (and def
(nth 2 (-first (pcase-lambda (`(,cmd ,re ,_))
(and (eq this-command cmd)
(or (not re)
(string-match-p re prompt))))
magit-dwim-selection)))))
(nth 2 (seq-find (pcase-lambda (`(,cmd ,re ,_))
(and (eq this-command cmd)
(or (not re)
(string-match-p re prompt))))
magit-dwim-selection)))))
(if (eq dwim 'ask)
(if (y-or-n-p (format "%s %s? " prompt def))
def
@@ -589,48 +612,13 @@ acts similarly to `completing-read', except for the following:
predicate require-match
initial-input hist def))))
(define-obsolete-function-alias 'magit-completing-read-multiple*
'magit-completing-read-multiple "Magit-Section 4.0.0")
(defun magit-completing-read-multiple
(prompt choices &optional sep default hist keymap)
"Read multiple items from CHOICES, separated by SEP.
Set up the `crm' variables needed to read multiple values with
`read-from-minibuffer'.
SEP is a regexp matching characters that can separate choices.
When SEP is nil, it defaults to `crm-separator'. DEFAULT, HIST,
and KEYMAP are passed to `read-from-minibuffer'. When KEYMAP is
nil, it defaults to `crm-local-completion-map'.
Unlike `completing-read-multiple', the return value is not split
into a list."
(declare (obsolete magit-completing-read-multiple* "Magit 3.1.0"))
(let* ((crm-separator (or sep crm-separator))
(crm-completion-table (magit--completion-table choices))
(choose-completion-string-functions
'(crm--choose-completion-string))
(minibuffer-completion-table #'crm--collection-fn)
(minibuffer-completion-confirm t)
(helm-completion-in-region-default-sort-fn nil)
(helm-crm-default-separator nil)
(ivy-sort-matches-functions-alist nil)
(input
(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)
nil hist default))))
(when (string-equal input "")
(or (setq input default)
(user-error "Nothing selected")))
input))
(defun magit-completing-read-multiple*
(prompt table &optional predicate require-match initial-input
hist def inherit-input-method
no-split)
( prompt table &optional predicate require-match initial-input
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 and take an additional argument NO-SPLIT, which causes
@@ -703,12 +691,10 @@ back to built-in `completing-read' for now." :error)
(format "%s (default %s): " (substring prompt 0 -2) def)
prompt))
(defvar magit-minibuffer-local-ns-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map minibuffer-local-map)
(define-key map "\s" #'magit-whitespace-disallowed)
(define-key map "\t" #'magit-whitespace-disallowed)
map))
(defvar-keymap magit-minibuffer-local-ns-map
:parent minibuffer-local-map
"SPC" #'magit-whitespace-disallowed
"TAB" #'magit-whitespace-disallowed)
(defun magit-whitespace-disallowed ()
"Beep to tell the user that whitespace is not allowed."
@@ -718,8 +704,8 @@ back to built-in `completing-read' for now." :error)
(setq defining-kbd-macro nil)
(force-mode-line-update))
(defun magit-read-string (prompt &optional initial-input history default-value
inherit-input-method no-whitespace)
(defun magit-read-string ( prompt &optional initial-input history default-value
inherit-input-method no-whitespace)
"Read a string from the minibuffer, prompting with string PROMPT.
This is similar to `read-string', but
@@ -755,8 +741,8 @@ This is similar to `read-string', but
(user-error "Input contains whitespace"))
(t val))))
(defun magit-read-string-ns (prompt &optional initial-input history
default-value inherit-input-method)
(defun magit-read-string-ns ( prompt &optional initial-input history
default-value inherit-input-method)
"Call `magit-read-string' with non-nil NO-WHITESPACE."
(magit-read-string prompt initial-input history default-value
inherit-input-method t))
@@ -765,11 +751,11 @@ This is similar to `read-string', but
(declare (indent 2)
(debug (form form &rest (characterp form body))))
`(prog1 (pcase (read-char-choice
(concat ,prompt
(mapconcat #'identity
(list ,@(mapcar #'cadr clauses))
", ")
,(if verbose ", or [C-g] to abort " " "))
(let ((parts (nconc (list ,@(mapcar #'cadr clauses))
,(and verbose '(list "[C-g] to abort")))))
(concat ,prompt
(mapconcat #'identity (butlast parts) ", ")
", or " (car (last parts)) " "))
',(mapcar #'car clauses))
,@(--map `(,(car it) ,@(cddr it)) clauses))
(message "")))
@@ -787,13 +773,15 @@ ACTION is a member of option `magit-slow-confirm'."
'((safe-with-wip magit-wip-before-change-mode
discard reverse stage-all-changes unstage-all-changes)))
(cl-defun magit-confirm (action &optional prompt prompt-n noabort
(items nil sitems))
(cl-defun magit-confirm ( action &optional prompt prompt-n noabort
(items nil sitems) prompt-suffix)
(declare (indent defun))
(setq prompt-n (format (concat (or prompt-n prompt) "? ") (length items)))
(setq prompt (format (concat (or prompt (magit-confirm-make-prompt action))
"? ")
(car items)))
(when prompt-suffix
(setq prompt (concat prompt prompt-suffix)))
(or (cond ((and (not (eq action t))
(or (eq magit-no-confirm t)
(memq action magit-no-confirm)
@@ -816,14 +804,14 @@ ACTION is a member of option `magit-slow-confirm'."
items)))
(if noabort nil (user-error "Abort"))))
(defun magit-confirm-files (action files &optional prompt)
(defun magit-confirm-files (action files &optional prompt prompt-suffix noabort)
(when files
(unless prompt
(setq prompt (magit-confirm-make-prompt action)))
(magit-confirm action
(concat prompt " %s")
(concat prompt " %i files")
nil files)))
(concat prompt " \"%s\"")
(concat prompt " %d files")
noabort files prompt-suffix)))
(defun magit-confirm-make-prompt (action)
(let ((prompt (symbol-name action)))
@@ -985,7 +973,7 @@ with the text area."
This combines the benefits of `buffer-string', `buffer-substring'
and `buffer-substring-no-properties' into one function that is
not as painful to use as the latter. I.e. you can write
not as painful to use as the latter. I.e., you can write
(magit--buffer-string)
instead of
(buffer-substring-no-properties (point-min)
@@ -1255,6 +1243,22 @@ Like `message', except that `message-log-max' is bound to nil."
(goto-char (or ,pos 1))
,@body))))
(defun magit--ellipsis (&optional where)
"Build an ellipsis always as string, depending on WHERE."
(if (stringp magit-ellipsis)
magit-ellipsis
(if-let ((pair (car (or
(alist-get (or where t) magit-ellipsis)
(alist-get t magit-ellipsis)))))
(pcase-let ((`(,fancy . ,universal) pair))
(let ((ellipsis (if (and fancy (char-displayable-p fancy))
fancy
universal)))
(if (characterp ellipsis)
(char-to-string ellipsis)
ellipsis)))
(user-error "Variable magit-ellipsis is invalid"))))
;;; _
(provide 'magit-base)
;;; magit-base.el ends here

View File

@@ -1,6 +1,6 @@
;;; magit-bisect.el --- Bisect support for Magit -*- lexical-binding:t -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
@@ -113,6 +113,8 @@ other actions from the bisect transient command (\
bad))
(when (magit-anything-modified-p)
(user-error "Cannot bisect with uncommitted changes"))
(magit-repository-local-set 'bisect--first-parent
(transient-arg-value "--first-parent" args))
(magit-git-bisect "start" (list args bad good) t))
(defun magit-bisect-start-read-args ()
@@ -134,7 +136,9 @@ other actions from the bisect transient command (\
(interactive)
(magit-confirm 'reset-bisect)
(magit-run-git "bisect" "reset")
(ignore-errors (delete-file (magit-git-dir "BISECT_CMD_OUTPUT"))))
(magit-repository-local-delete 'bisect--first-parent)
(ignore-errors
(delete-file (expand-file-name "BISECT_CMD_OUTPUT" (magit-gitdir)))))
;;;###autoload
(defun magit-bisect-good ()
@@ -197,7 +201,7 @@ bisect run'."
;; 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"))
(list :file (expand-file-name "BISECT_CMD_OUTPUT" (magit-gitdir)))
(magit-process-git-arguments
(list "bisect" "start" bad good args)))
(magit-refresh)))
@@ -225,7 +229,8 @@ bisect run'."
(output (buffer-substring-no-properties
(oref section content)
(oref section end))))
(with-temp-file (magit-git-dir "BISECT_CMD_OUTPUT")
(with-temp-file
(expand-file-name "BISECT_CMD_OUTPUT" (magit-gitdir))
(insert output)))))
(magit-refresh))
(message "Bisecting...done")))))
@@ -233,16 +238,17 @@ bisect run'."
;;; Sections
(defun magit-bisect-in-progress-p ()
(file-exists-p (magit-git-dir "BISECT_LOG")))
(file-exists-p (expand-file-name "BISECT_LOG" (magit-gitdir))))
(defun magit-bisect-terms ()
(magit-file-lines (magit-git-dir "BISECT_TERMS")))
(magit-file-lines (expand-file-name "BISECT_TERMS" (magit-gitdir))))
(defun magit-insert-bisect-output ()
"While bisecting, insert section with output from `git bisect'."
(when (magit-bisect-in-progress-p)
(let* ((lines
(or (magit-file-lines (magit-git-dir "BISECT_CMD_OUTPUT"))
(or (magit-file-lines
(expand-file-name "BISECT_CMD_OUTPUT" (magit-gitdir)))
(list "Bisecting: (no saved bisect output)"
"It appears you have invoked `git bisect' from a shell."
"There is nothing wrong with that, we just cannot display"
@@ -268,7 +274,9 @@ bisect run'."
(magit-git-wash (apply-partially #'magit-log-wash-log 'bisect-vis)
"bisect" "visualize" "git" "log"
"--format=%h%x00%D%x00%s" "--decorate=full"
(and magit-bisect-show-graph "--graph")))))
(and magit-bisect-show-graph "--graph")
(and (magit-repository-local-get 'bisect--first-parent)
"--first-parent")))))
(defun magit-insert-bisect-log ()
"While bisecting, insert section logging bisect progress."
@@ -281,20 +289,23 @@ bisect run'."
(defun magit-wash-bisect-log (_args)
(let (beg)
(while (progn (setq beg (point-marker))
(re-search-forward "^\\(git bisect [^\n]+\n\\)" nil t))
(magit-bind-match-strings (heading) nil
(magit-delete-match)
(save-restriction
(narrow-to-region beg (point))
(goto-char (point-min))
(magit-insert-section (bisect-item heading t)
(insert (propertize heading 'font-lock-face
'magit-section-secondary-heading))
(magit-insert-heading)
(magit-wash-sequence
(apply-partially #'magit-log-wash-rev 'bisect-log
(magit-abbrev-length)))
(insert ?\n)))))
(re-search-forward
"^\\(\\(?:git bisect\\|# status:\\) [^\n]+\n\\)" nil t))
(if (string-prefix-p "# status:" (match-string 1))
(magit-delete-match)
(magit-bind-match-strings (heading) nil
(magit-delete-match)
(save-restriction
(narrow-to-region beg (point))
(goto-char (point-min))
(magit-insert-section (bisect-item heading t)
(insert (propertize heading 'font-lock-face
'magit-section-secondary-heading))
(magit-insert-heading)
(magit-wash-sequence
(apply-partially #'magit-log-wash-rev 'bisect-log
(magit-abbrev-length)))
(insert ?\n))))))
(when (re-search-forward
"# first bad commit: \\[\\([a-z0-9]\\{40,\\}\\)\\] [^\n]+\n" nil t)
(magit-bind-match-strings (hash) nil

View File

@@ -1,6 +1,6 @@
;;; magit-blame.el --- Blame support for Magit -*- lexical-binding:t -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
@@ -259,7 +259,7 @@ Also see option `magit-blame-styles'."
(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))))
(line (format "%d,+1" (line-number-at-pos))))
(cond (file (with-temp-buffer
(magit-with-toplevel
(magit-git-insert
@@ -289,33 +289,29 @@ Also see option `magit-blame-styles'."
;;; Keymaps
(defvar magit-blame-mode-map
(let ((map (make-sparse-keymap)))
(define-key map (kbd "C-c C-q") 'magit-blame-quit)
map)
"Keymap for `magit-blame-mode'.
(defvar-keymap magit-blame-mode-map
:doc "Keymap for `magit-blame-mode'.
Note that most blaming key bindings are defined
in `magit-blame-read-only-mode-map' instead.")
in `magit-blame-read-only-mode-map' instead."
"C-c C-q" #'magit-blame-quit)
(defvar magit-blame-read-only-mode-map
(let ((map (make-sparse-keymap)))
(define-key map (kbd "C-m") #'magit-show-commit)
(define-key map (kbd "p") #'magit-blame-previous-chunk)
(define-key map (kbd "P") #'magit-blame-previous-chunk-same-commit)
(define-key map (kbd "n") #'magit-blame-next-chunk)
(define-key map (kbd "N") #'magit-blame-next-chunk-same-commit)
(define-key map (kbd "b") #'magit-blame-addition)
(define-key map (kbd "r") #'magit-blame-removal)
(define-key map (kbd "f") #'magit-blame-reverse)
(define-key map (kbd "B") #'magit-blame)
(define-key map (kbd "c") #'magit-blame-cycle-style)
(define-key map (kbd "q") #'magit-blame-quit)
(define-key map (kbd "M-w") #'magit-blame-copy-hash)
(define-key map (kbd "SPC") #'magit-diff-show-or-scroll-up)
(define-key map (kbd "S-SPC") #'magit-diff-show-or-scroll-down)
(define-key map (kbd "DEL") #'magit-diff-show-or-scroll-down)
map)
"Keymap for `magit-blame-read-only-mode'.")
(defvar-keymap magit-blame-read-only-mode-map
:doc "Keymap for `magit-blame-read-only-mode'."
"C-m" #'magit-show-commit
"p" #'magit-blame-previous-chunk
"P" #'magit-blame-previous-chunk-same-commit
"n" #'magit-blame-next-chunk
"N" #'magit-blame-next-chunk-same-commit
"b" #'magit-blame-addition
"r" #'magit-blame-removal
"f" #'magit-blame-reverse
"B" #'magit-blame
"c" #'magit-blame-cycle-style
"q" #'magit-blame-quit
"M-w" #'magit-blame-copy-hash
"SPC" #'magit-diff-show-or-scroll-up
"S-SPC" #'magit-diff-show-or-scroll-down
"DEL" #'magit-diff-show-or-scroll-down)
;;; Modes
;;;; Base Mode
@@ -323,8 +319,10 @@ in `magit-blame-read-only-mode-map' instead.")
(define-minor-mode magit-blame-mode
"Display blame information inline."
:lighter magit-blame-mode-lighter
:interactive nil
(cond (magit-blame-mode
(when (called-interactively-p 'any)
(unless arg
;; Emacs < 28.1 doesn't support `:interactive'.
(setq magit-blame-mode nil)
(user-error
(concat "Don't call `magit-blame-mode' directly; "
@@ -402,10 +400,12 @@ modes is toggled, then this mode also gets toggled automatically.
(defun magit-blame-put-keymap-before-view-mode ()
"Put `magit-blame-read-only-mode' ahead of `view-mode' in `minor-mode-map-alist'."
(--when-let (assq 'magit-blame-read-only-mode
(cl-member 'view-mode minor-mode-map-alist :key #'car))
(when-let ((entry (assq 'magit-blame-read-only-mode
(cl-member 'view-mode minor-mode-map-alist
:key #'car))))
(setq minor-mode-map-alist
(cons it (delq it minor-mode-map-alist))))
(cons entry
(delq entry minor-mode-map-alist))))
(remove-hook 'view-mode-hook #'magit-blame-put-keymap-before-view-mode))
(add-hook 'view-mode-hook #'magit-blame-put-keymap-before-view-mode)
@@ -511,7 +511,8 @@ modes is toggled, then this mode also gets toggled automatically.
(setf prev-file (magit-decode-git-path (match-string 2))))
((looking-at "^\\([^ ]+\\) \\(.+\\)")
(push (cons (match-string 1)
(match-string 2)) revinfo)))
(match-string 2))
revinfo)))
(forward-line)))
(when (and (eq type 'removal) prev-rev)
(cl-rotatef orig-rev prev-rev)
@@ -641,8 +642,8 @@ modes is toggled, then this mode also gets toggled automatically.
(defun magit-blame--update-heading-overlay (ov)
(overlay-put
ov 'before-string
(--if-let (magit-blame--style-get 'heading-format)
(magit-blame--format-string ov it 'magit-blame-heading)
(if-let ((format (magit-blame--style-get 'heading-format)))
(magit-blame--format-string ov format 'magit-blame-heading)
(and (magit-blame--style-get 'show-lines)
(or (not (magit-blame--style-get 'margin-format))
(save-excursion
@@ -863,15 +864,17 @@ then also kill the buffer."
(defun magit-blame-next-chunk ()
"Move to the next chunk."
(interactive)
(--if-let (next-single-char-property-change (point) 'magit-blame-chunk)
(goto-char it)
(if-let ((next (next-single-char-property-change
(point) 'magit-blame-chunk)))
(goto-char next)
(user-error "No more chunks")))
(defun magit-blame-previous-chunk ()
"Move to the previous chunk."
(interactive)
(--if-let (previous-single-char-property-change (point) 'magit-blame-chunk)
(goto-char it)
(if-let ((prev (previous-single-char-property-change
(point) 'magit-blame-chunk)))
(goto-char prev)
(user-error "No more chunks")))
(defun magit-blame-next-chunk-same-commit (&optional previous)
@@ -887,9 +890,9 @@ then also kill the buffer."
#'previous-single-char-property-change
#'next-single-char-property-change)
pos 'magit-blame-chunk)))
(--when-let (magit-blame--overlay-at pos)
(when-let ((o (magit-blame--overlay-at pos)))
(when (equal (oref (magit-blame-chunk-at pos) orig-rev) rev)
(setq ov it)))))
(setq ov o)))))
(if ov
(goto-char (overlay-start ov))
(user-error "No more chunks from same commit")))

View File

@@ -1,6 +1,6 @@
;;; magit-bookmark.el --- Bookmark support for Magit -*- lexical-binding:t -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Inspired by an earlier implementation by Yuri Khan.

View File

@@ -1,6 +1,6 @@
;;; magit-branch.el --- Branch support -*- lexical-binding:t -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
@@ -77,7 +77,7 @@ have to match exactly unless they contain a character that makes
them invalid as a branch name. Recommended characters to use
to trigger interpretation as a regexp are \"*\" and \"^\". Some
other characters which you might expect to be invalid, actually
are not, e.g. \".+$\" are all perfectly valid. More precisely,
are not, e.g., \".+$\" are all perfectly valid. More precisely,
if `git check-ref-format --branch STRING' exits with a non-zero
status, then treat STRING as a regexp.
@@ -101,7 +101,7 @@ prefer the former, then you should add branches such as \"master\",
"Alist of upstreams to be used when branching from remote branches.
When creating a local branch from an ephemeral branch located
on a remote, e.g. a feature or hotfix branch, then that remote
on a remote, e.g., a feature or hotfix branch, then that remote
branch should usually not be used as the upstream branch, since
the push-remote already allows accessing it and having both the
upstream and the push-remote reference the same related branch
@@ -178,10 +178,7 @@ When t, then rename the branch named OLD on the remote specified
When `forge-only' and the `forge' package is available, then
behave like `t' if the remote points to a repository on a forge
(currently Github or Gitlab), otherwise like `local-only'.
Another supported but obsolete value is `github-only'. It is a
misnomer because it now treated as an alias for `forge-only'."
(currently Github or Gitlab), otherwise like `local-only'."
:package-version '(magit . "2.90.0")
:group 'magit-commands
:type '(choice
@@ -257,30 +254,46 @@ 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)."
(declare (interactive-only magit--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" args revision))
(magit-run-git-async "checkout" args revision))
(defun magit--checkout (revision &optional args)
(when (string-match "\\`heads/\\(.+\\)" revision)
(setq revision (match-string 1 revision)))
(magit-call-git "checkout" args revision))
;;;###autoload
(defun magit-branch-create (branch start-point)
"Create BRANCH at branch or revision START-POINT."
(declare (interactive-only magit-call-git))
(interactive (magit-branch-read-args "Create branch"))
(magit-call-git "branch" branch start-point)
(magit-branch-maybe-adjust-upstream branch start-point)
(magit-refresh))
(magit-run-git-async "branch" branch start-point)
(set-process-sentinel
magit-this-process
(lambda (process event)
(when (memq (process-status process) '(exit signal))
(magit-branch-maybe-adjust-upstream branch start-point)
(magit-process-sentinel process event)))))
;;;###autoload
(defun magit-branch-and-checkout (branch start-point &optional args)
"Create and checkout BRANCH at branch or revision START-POINT."
(declare (interactive-only magit-call-git))
(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" args "-b" branch start-point)
(magit-branch-maybe-adjust-upstream branch start-point)
(magit-refresh)))
(magit-run-git-async "checkout" args "-b" branch start-point)
(set-process-sentinel
magit-this-process
(lambda (process event)
(when (memq (process-status process) '(exit signal))
(magit-branch-maybe-adjust-upstream branch start-point)
(magit-process-sentinel process event))))))
;;;###autoload
(defun magit-branch-or-checkout (arg &optional start-point)
@@ -294,6 +307,7 @@ Otherwise create and checkout a new branch using the input as
its name. Before doing so read the starting-point for the new
branch. This is similar to what `magit-branch-and-checkout'
does."
(declare (interactive-only magit-call-git))
(interactive
(let ((arg (magit-read-other-branch-or-commit "Checkout")))
(list arg
@@ -302,8 +316,10 @@ does."
(when (string-match "\\`heads/\\(.+\\)" arg)
(setq arg (match-string 1 arg)))
(if start-point
(magit-branch-and-checkout arg start-point)
(magit-checkout arg)))
(with-suppressed-warnings ((interactive-only magit-branch-and-checkout))
(magit-branch-and-checkout arg start-point))
(magit--checkout arg)
(magit-refresh)))
;;;###autoload
(defun magit-branch-checkout (branch &optional start-point)
@@ -329,6 +345,7 @@ In the latter two cases the upstream is also set. Whether it is
set to the chosen START-POINT or something else depends on the
value of `magit-branch-adjust-remote-upstream-alist', just like
when using `magit-branch-and-checkout'."
(declare (interactive-only magit-call-git))
(interactive
(let* ((current (magit-get-current-branch))
(local (magit-list-local-branch-names))
@@ -354,34 +371,43 @@ when using `magit-branch-and-checkout'."
(list choice))
(t
(list choice (magit-read-starting-point "Create" choice))))))
(if (not start-point)
(magit-checkout branch (magit-branch-arguments))
(cond
((not start-point)
(magit--checkout branch (magit-branch-arguments))
(magit-refresh))
(t
(when (magit-anything-modified-p t)
(user-error "Cannot checkout when there are uncommitted changes"))
(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-refresh)))
(magit-run-git-async "checkout" (magit-branch-arguments)
"-b" branch start-point)
(set-process-sentinel
magit-this-process
(lambda (process event)
(when (memq (process-status process) '(exit signal))
(magit-branch-maybe-adjust-upstream 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-process-sentinel process event)))))))
(defun magit-branch-maybe-adjust-upstream (branch start-point)
(--when-let
(or (and (magit-get-upstream-branch branch)
(magit-get-indirect-upstream-branch start-point))
(and (magit-remote-branch-p start-point)
(let ((name (cdr (magit-split-branch-name start-point))))
(-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)))
(when-let ((upstream
(or (and (magit-get-upstream-branch branch)
(magit-get-indirect-upstream-branch start-point))
(and (magit-remote-branch-p start-point)
(let ((name (cdr (magit-split-branch-name start-point))))
(seq-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=" upstream) branch)))
;;;###autoload
(defun magit-branch-orphan (branch start-point)
@@ -409,7 +435,11 @@ when using `magit-branch-and-checkout'."
(magit-read-starting-point prompt choice default-start))
(user-error "Not a valid starting-point: %s" choice))))
(let ((branch (magit-read-string-ns (concat prompt " named"))))
(list branch (magit-read-starting-point prompt branch default-start)))))
(if (magit-branch-p branch)
(magit-branch-read-args
(format "Branch `%s' already exists; pick another name" branch)
default-start)
(list branch (magit-read-starting-point prompt branch default-start))))))
;;;###autoload
(defun magit-branch-spinout (branch &optional from)
@@ -477,8 +507,8 @@ from the source branch's upstream, then an error is raised."
(if checkout
(magit-call-git "checkout" "-b" branch current)
(magit-call-git "branch" branch current)))
(--when-let (magit-get-indirect-upstream-branch current)
(magit-call-git "branch" "--set-upstream-to" it branch))
(when-let ((upstream (magit-get-indirect-upstream-branch current)))
(magit-call-git "branch" "--set-upstream-to" upstream branch))
(when (and tracked
(setq base
(if from
@@ -511,7 +541,8 @@ then also set the target branch as the upstream of the branch
that is being reset."
(interactive
(let* ((atpoint (magit-local-branch-at-point))
(branch (magit-read-local-branch "Reset branch" atpoint)))
(branch (magit-read-local-branch "Reset branch" atpoint))
(minibuffer-default-add-function (magit--minibuf-default-add-commit)))
(list branch
(magit-completing-read (format "Reset %s to" branch)
(delete branch (magit-list-branch-names))
@@ -542,9 +573,16 @@ that is being reset."
;;;###autoload
(defun magit-branch-delete (branches &optional force)
"Delete one or multiple branches.
If the region marks multiple branches, then offer to delete
those, otherwise prompt for a single branch to be deleted,
defaulting to the branch at point."
defaulting to the branch at point.
Require confirmation when deleting branches is dangerous in some
way. Option `magit-no-confirm' can be customized to not require
confirmation in certain cases. See its docstring to learn why
confirmation is required by default in certain cases or if a
prompt is confusing."
;; One would expect this to be a command as simple as, for example,
;; `magit-branch-rename'; but it turns out everyone wants to squeeze
;; a bit of extra functionality into this one, including myself.
@@ -552,18 +590,19 @@ defaulting to the branch at point."
(let ((branches (magit-region-values 'branch t))
(force current-prefix-arg))
(if (length> branches 1)
(magit-confirm t nil "Delete %i branches" nil branches)
(magit-confirm t nil "Delete %d branches" nil branches)
(setq branches
(list (magit-read-branch-prefer-other
(if force "Force delete branch" "Delete branch")))))
(unless force
(when-let ((unmerged (-remove #'magit-branch-merged-p branches)))
(when-let ((unmerged (seq-remove #'magit-branch-merged-p branches)))
(if (magit-confirm 'delete-unmerged-branch
"Delete unmerged branch %s"
"Delete %i unmerged branches"
"Delete %d unmerged branches"
'noabort unmerged)
(setq force branches)
(or (setq branches (-difference branches unmerged))
(or (setq branches
(cl-set-difference branches unmerged :test #'equal))
(user-error "Abort")))))
(list branches force)))
(let* ((refs (mapcar #'magit-ref-fullname branches))
@@ -574,7 +613,7 @@ defaulting to the branch at point."
(let ((len (length ambiguous)))
(cond
((= len 1)
(format "%s is" (-first #'magit-ref-ambiguous-p branches)))
(format "%s is" (seq-find #'magit-ref-ambiguous-p branches)))
((= len (length refs))
(format "These %s names are" len))
(t
@@ -585,9 +624,13 @@ defaulting to the branch at point."
(offset (1+ (length remote))))
(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)
(format "Deleting local %s. Also delete on %s"
(magit-ref-fullname (car branches))
remote)
(format "Deleting %d local refs. Also delete on %s"
(length refs)
remote)
'noabort refs)
;; The ref may actually point at another rev on the remote,
;; but this is better than nothing.
(dolist (ref refs)
@@ -739,8 +782,7 @@ the remote."
(when (and (equal (magit-get-push-remote new) remote)
;; ...and if it does not, then we must abort.
(not (eq magit-branch-rename-push-target 'local-only))
(or (not (memq magit-branch-rename-push-target
'(forge-only github-only)))
(or (not (eq magit-branch-rename-push-target 'forge-only))
(and (require (quote forge) nil t)
(fboundp 'forge--forge-remote-p)
(forge--forge-remote-p remote))))
@@ -751,11 +793,11 @@ the remote."
(not new-target)
(magit-y-or-n-p (format "Also rename %S to %S on \"%s\""
old new remote)))
;; Rename on (i.e. within) the remote, but only if the
;; Rename on (i.e., within) the remote, but only if the
;; destination ref doesn't exist yet. If that ref already
;; exists, then it probably is of some value and we better
;; not touch it. Ignore what the local ref points at,
;; i.e. if the local and the remote ref didn't point at
;; i.e., if the local and the remote ref didn't point at
;; the same commit before the rename then keep it that way.
(magit-call-git "push" "-v" remote
(format "%s:refs/heads/%s" old-target new)
@@ -794,8 +836,9 @@ and also rename the respective reflog file."
(magit-run-git "update-ref" "-d" old)))
(defun magit--rename-reflog-file (old new)
(let ((old (magit-git-dir (concat "logs/" old)))
(new (magit-git-dir (concat "logs/" new))))
(let* ((dir (magit-gitdir))
(old (expand-file-name (concat "logs/" old) dir))
(new (expand-file-name (concat "logs/" new) dir)))
(when (file-exists-p old)
(make-directory (file-name-directory new) t)
(rename-file old new t))))
@@ -817,7 +860,9 @@ and also rename the respective reflog file."
("p" magit-branch.<branch>.pushRemote)]
["Configure repository defaults"
("R" magit-pull.rebase)
("P" magit-remote.pushDefault)]
("P" magit-remote.pushDefault)
("b" "Update default branch" magit-update-default-branch
:inapt-if-not magit-get-some-remote)]
["Configure branch creation"
("a m" magit-branch.autoSetupMerge)
("a r" magit-branch.autoSetupRebase)]
@@ -844,12 +889,6 @@ and also rename the respective reflog file."
(interactive (list (oref transient-current-prefix scope)))
(magit-run-git-with-editor "branch" "--edit-description" branch))
(add-hook 'find-file-hook #'magit-branch-description-check-buffers)
(defun magit-branch-description-check-buffers ()
(and buffer-file-name
(string-match-p "/\\(BRANCH\\|EDIT\\)_DESCRIPTION\\'" buffer-file-name)))
(defclass magit--git-branch:upstream (magit--git-variable)
((format :initform " %k %m %M\n %r %R")))

View File

@@ -1,6 +1,6 @@
;;; magit-bundle.el --- Bundle support for Magit -*- lexical-binding:t -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
@@ -59,8 +59,8 @@
(concat (file-name-nondirectory
(directory-file-name (magit-toplevel)))
".bundle"))
(magit-completing-read-multiple* "Refnames (zero or more): "
(magit-list-refnames))
(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)
@@ -72,7 +72,7 @@
(interactive
(let ((tag (magit-read-tag "Track bundle using tag"))
(branch (magit-read-branch "Bundle branch"))
(refs (magit-completing-read-multiple*
(refs (magit-completing-read-multiple
"Additional refnames (zero or more): "
(magit-list-refnames))))
(list (read-file-name "File: " nil nil nil (concat tag ".bundle"))

View File

@@ -1,6 +1,6 @@
;;; magit-clone.el --- Clone a repository -*- lexical-binding:t -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
@@ -87,7 +87,7 @@ default user specified in the matched entry is used.
If USER contains a dot, then it is treated as a Git variable and
the value of that is used as the username. Otherwise it is used
as the username itself."
:package-version '(magit . "3.4.0")
:package-version '(magit . "4.0.0")
:group 'magit-commands
:type '(repeat (list regexp
(string :tag "Hostname")
@@ -105,13 +105,22 @@ The value can be a string (representing a single static format)
or an alist with elements (HOSTNAME . FORMAT) mapping hostnames
to formats. When an alist is used, the t key represents the
default. Also see `magit-clone-name-alist'."
:package-version '(magit . "3.4.0")
:package-version '(magit . "4.0.0")
:group 'magit-commands
:type '(choice (string :tag "Format")
(alist :key-type (choice (string :tag "Host")
(const :tag "Default" t))
:value-type (string :tag "Format"))))
(defcustom magit-post-clone-hook nil
"Hook run after the repository has been successfully cloned.
When the hook is called, `default-directory' is let-bound to the
directory where the repository has been cloned."
:package-version '(magit . "4.0.0")
:group 'magit-commands
:type 'hook)
;;; Commands
;;;###autoload (autoload 'magit-clone "magit-clone" nil t)
@@ -228,8 +237,8 @@ Then show the status buffer for the new repository."
'sparse))
(defun magit-clone-internal (repository directory args &optional sparse)
(let* ((checkout (not (memq (car args) '("--bare" "--mirror"))))
(remote (or (transient-arg-value "--origin" args)
(let* ((checkout (not (member (car args) '("--bare" "--mirror"))))
(remote (or (transient-arg-value "--origin=" args)
(magit-get "clone.defaultRemote")
"origin"))
(set-push-default
@@ -275,6 +284,8 @@ Then show the status buffer for the new repository."
(let ((default-directory directory))
(magit-call-git "sparse-checkout" "init" "--cone")
(magit-call-git "checkout" (magit-get-current-branch))))
(let ((default-directory directory))
(run-hooks 'magit-post-clone-hook))
(with-current-buffer (process-get process 'command-buf)
(magit-status-setup-buffer directory)))))))

View File

@@ -1,6 +1,6 @@
;;; magit-commit.el --- Create Git commits -*- lexical-binding:t -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
@@ -180,8 +180,10 @@ With a prefix argument, amend to the commit at `HEAD' instead.
(interactive (if current-prefix-arg
(list (cons "--amend" (magit-commit-arguments)))
(list (magit-commit-arguments))))
(when (member "--all" args)
(setq this-command 'magit-commit--all))
(cond ((member "--all" args)
(setq this-command 'magit-commit--all))
((member "--allow-empty" args)
(setq this-command 'magit-commit--allow-empty)))
(when (setq args (magit-commit-assert args))
(let ((default-directory (magit-toplevel)))
(magit-run-git-with-editor "commit" args))))
@@ -312,9 +314,8 @@ depending on the value of option `magit-commit-squash-confirm'."
(magit-with-editor
(magit-call-git
"commit" "--no-gpg-sign"
(-remove-first
(apply-partially #'string-prefix-p "--gpg-sign=")
args)))
(seq-remove (apply-partially #'string-prefix-p "--gpg-sign=")
args)))
(magit-run-git-with-editor "commit" args))
t) ; The commit was created; used by below lambda.
(let ((winconf (and magit-commit-show-diff
@@ -338,13 +339,13 @@ depending on the value of option `magit-commit-squash-confirm'."
(apply #'magit-diff-staged nil (magit-diff-arguments)))))))
(defun magit-commit-amend-assert (&optional commit)
(--when-let (magit-list-publishing-branches commit)
(when-let ((branches (magit-list-publishing-branches commit)))
(let ((m1 "This commit has already been published to ")
(m2 ".\nDo you really want to modify it"))
(magit-confirm 'amend-published
(concat m1 "%s" m2)
(concat m1 "%i public branches" m2)
nil it))))
(concat m1 "%d public branches" m2)
nil branches))))
(defun magit-commit-assert (args &optional strict)
(cond
@@ -367,9 +368,14 @@ depending on the value of option `magit-commit-squash-confirm'."
(setq this-command #'magit-rebase-continue)
(magit-run-git-sequencer "rebase" "--continue")
nil)
((and (file-exists-p (magit-git-dir "MERGE_MSG"))
(not (magit-anything-unstaged-p)))
(or args (list "--")))
((file-exists-p (expand-file-name "MERGE_MSG" (magit-gitdir)))
(cond ((magit-anything-unmerged-p)
(user-error "Unresolved conflicts"))
((and (magit-anything-unstaged-p)
(not (y-or-n-p
"Proceed with merge despite unstaged changes? ")))
(user-error "Abort"))
((or args (list "--")))))
((not (magit-anything-unstaged-p))
(user-error "Nothing staged (or unstaged)"))
(magit-commit-ask-to-stage
@@ -396,7 +402,7 @@ 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
Both the author and the committer dates are changed, 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.
@@ -576,7 +582,8 @@ See `magit-commit-absorb' for an alternative implementation."
;; requires a working tree.
(magit-with-toplevel
(magit-anything-unstaged-p)))
(squash (let ((f (magit-git-dir "rebase-merge/rewritten-pending")))
(squash (let ((f (expand-file-name "rebase-merge/rewritten-pending"
(magit-gitdir))))
(and (file-exists-p f) (length (magit-file-lines f)))))
(noalt nil))
(pcase (list staged unstaged command)
@@ -585,6 +592,9 @@ See `magit-commit-absorb' for an alternative implementation."
(setq rev (format "HEAD~%s" squash)))
(`(,_ ,_ magit-commit-amend)
(setq rev "HEAD^"))
(`(nil nil magit-commit--allow-empty)
(setq rev "HEAD")
(setq arg nil))
((or `(,_ ,_ magit-commit-reword)
`(nil nil ,_))
(setq rev "HEAD^..HEAD")
@@ -605,7 +615,8 @@ See `magit-commit-absorb' for an alternative implementation."
(equal arg (buffer-local-value 'magit-buffer-typearg buf)))))))
((eq command 'magit-commit-amend)
(setq rev nil))
((or squash (file-exists-p (magit-git-dir "rebase-merge/amend")))
((or squash
(file-exists-p (expand-file-name "rebase-merge/amend" (magit-gitdir))))
(setq rev "HEAD^"))
(t
(message "No alternative diff while committing")
@@ -618,7 +629,10 @@ See `magit-commit-absorb' for an alternative implementation."
(when magit-commit-diff-inhibit-same-window
(setq display-buffer-overriding-action
'(nil (inhibit-same-window . t))))
(magit-diff-setup-buffer rev arg (car (magit-diff-arguments)) nil)))))
(magit-diff-setup-buffer rev arg (car (magit-diff-arguments)) nil
(cond ((equal rev "HEAD") 'staged)
((equal rev "HEAD^..HEAD") 'committed)
('undefined)))))))
(add-hook 'server-switch-hook #'magit-commit-diff)
(add-hook 'with-editor-filter-visit-hook #'magit-commit-diff)

View File

@@ -1,6 +1,6 @@
;;; magit-core.el --- Core functionality -*- lexical-binding:t -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
@@ -37,7 +37,8 @@
(require 'magit-transient)
(require 'magit-autorevert)
(when (magit--libgit-available-p)
(when (and (not magit-inhibit-libgit)
(magit--libgit-available-p))
(condition-case err
(require 'magit-libgit)
(error

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
;;; magit-ediff.el --- Ediff extension for Magit -*- lexical-binding:t -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
@@ -58,7 +58,7 @@ invoked using Magit."
(defcustom magit-ediff-dwim-resolve-function #'magit-ediff-resolve-rest
"The function `magit-ediff-dwim' uses to resolve conflicts."
:package-version '(magit . "3.4.0")
:package-version '(magit . "4.0.0")
:group 'magit-ediff
:type '(choice (const magit-ediff-resolve-rest)
(const magit-ediff-resolve-all)
@@ -221,9 +221,11 @@ See info node `(magit) Ediffing' for more information about this
and alternative commands."
(interactive (list (magit-read-unmerged-file)))
(magit-with-toplevel
(let* ((revA (or (magit-name-branch "HEAD")
(let* ((dir (magit-gitdir))
(revA (or (magit-name-branch "HEAD")
(magit-commit-p "HEAD")))
(revB (cl-find-if (lambda (head) (file-exists-p (magit-git-dir head)))
(revB (cl-find-if (lambda (head)
(file-exists-p (expand-file-name head dir)))
'("MERGE_HEAD" "CHERRY_PICK_HEAD" "REVERT_HEAD")))
(revB (or (magit-name-branch revB)
(magit-commit-p revB)))
@@ -380,8 +382,8 @@ range)."
(let ((input (or arg (magit-diff-read-range-or-commit
"Compare range or commit"
nil mbase))))
(--if-let (magit-split-range input)
(-cons-to-list it)
(if-let ((range (magit-split-range input)))
(list (car range) (cdr range))
(list input nil))))
(defun magit-ediff-read-files (revA revB &optional fileB)

View File

@@ -1,6 +1,6 @@
;;; magit-extras.el --- Additional functionality for Magit -*- lexical-binding:t -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
@@ -137,8 +137,9 @@ blame to center around the line point is on."
(interactive
(let (revision filename)
(when (or current-prefix-arg
(not (setq revision "HEAD"
filename (magit-file-relative-name nil 'tracked))))
(progn
(setq revision "HEAD")
(not (setq filename (magit-file-relative-name nil 'tracked)))))
(setq revision (magit-read-branch-or-commit "Blame from revision"))
(setq filename (magit-read-file-from-rev revision "Blame file")))
(list revision filename
@@ -204,15 +205,15 @@ To make this command available use something like:
(add-hook \\='ido-setup-hook
(lambda ()
(define-key ido-completion-map
(kbd \"C-x g\") \\='ido-enter-magit-status)))
(keymap-set ido-completion-map
\"C-x g\" \\='ido-enter-magit-status)))
Starting with Emacs 25.1 the Ido keymaps are defined just once
instead of every time Ido is invoked, so now you can modify it
like pretty much every other keymap:
(define-key ido-common-completion-map
(kbd \"C-x g\") \\='ido-enter-magit-status)"
(keymap-set ido-common-completion-map
\"C-x g\" \\='ido-enter-magit-status)"
(interactive)
(setq ido-exit 'fallback)
(setq ido-fallback #'magit-status) ; for Emacs >= 26.2
@@ -242,7 +243,7 @@ to nil before loading Magit to prevent \"m\" from being bound.")
(equal project-switch-commands
(eval (car (get 'project-switch-commands 'standard-value))
t)))
(define-key project-prefix-map "m" #'magit-project-status)
(keymap-set project-prefix-map "m" #'magit-project-status)
(add-to-list 'project-switch-commands '(magit-project-status "Magit") t)))
;;;###autoload
@@ -263,9 +264,9 @@ is no file at point, then instead visit `default-directory'."
(interactive "P")
(if-let ((topdir (magit-toplevel default-directory)))
(let ((args (car (magit-log-arguments)))
(files (compat-dired-get-marked-files
nil nil #'magit-file-tracked-p nil
"No marked file is being tracked by Git")))
(files (dired-get-marked-files nil nil #'magit-file-tracked-p)))
(unless files
(user-error "No marked file is being tracked by Git"))
(when (and follow
(not (member "--follow" args))
(not (cdr files)))
@@ -286,7 +287,10 @@ for a repository."
(interactive (list (or (magit-toplevel)
(magit-read-repository t))
current-prefix-arg))
(let ((files (compat-dired-get-marked-files nil arg nil nil t)))
;; 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)))
@@ -295,8 +299,7 @@ for a repository."
"Open FILE with `dired-do-async-shell-command'.
Interactively, open the file at point."
(interactive (list (or (magit-file-at-point)
(completing-read "Act on file: "
(magit-list-files)))))
(magit-read-file "Act on file"))))
(require 'dired-aux)
(dired-do-async-shell-command
(dired-read-shell-command "& on %s: " current-prefix-arg (list file))
@@ -465,7 +468,7 @@ points at it) otherwise."
(if rebase
(let ((magit--rebase-published-symbol 'edit-published))
(magit-rebase-edit-commit rev (magit-rebase-arguments)))
(magit-checkout (or (magit-rev-branch rev) rev)))
(magit--checkout (or (magit-rev-branch rev) rev)))
(unless (and buffer-file-name
(file-equal-p file buffer-file-name))
(let ((blame-type (and magit-blame-mode magit-blame-type)))
@@ -503,7 +506,7 @@ to be visited.
Neither the blob nor the file buffer are killed when finishing
the rebase. If that is undesirable, then it might be better to
use `magit-rebase-edit-command' instead of this command."
use `magit-rebase-edit-commit' instead of this command."
(interactive (list (magit-file-at-point t t)))
(let ((magit-diff-visit-previous-blob nil))
(with-current-buffer
@@ -681,8 +684,8 @@ stack.
When reading the revision from the minibuffer, then it might not
be possible to guess the correct repository. When this command
is called inside a repository (e.g. while composing a commit
message), then that repository is used. Otherwise (e.g. while
is called inside a repository (e.g., while composing a commit
message), then that repository is used. Otherwise (e.g., while
composing an email) then the repository recorded for the top
element of the stack is used (even though we insert another
revision). If not called inside a repository and with an empty
@@ -721,14 +724,14 @@ the minibuffer too."
(setq pnt-format
(string-replace "%N" idx pnt-format)))
(magit-rev-insert-format pnt-format rev pnt-args)
(backward-delete-char 1))
(delete-char -1))
(when eob-format
(when idx-format
(setq eob-format
(string-replace "%N" idx eob-format)))
(save-excursion
(goto-char (point-max))
(skip-syntax-backward ">s-")
(skip-syntax-backward ">-")
(beginning-of-line)
(if (and comment-start (looking-at comment-start))
(while (looking-at comment-start)
@@ -738,11 +741,10 @@ the minibuffer too."
(insert ?\n)))
(insert ?\n)
(magit-rev-insert-format eob-format rev eob-args)
(backward-delete-char 1)))))
(delete-char -1)))))
(user-error "Revision stack is empty")))
(define-key git-commit-mode-map
(kbd "C-c C-w") #'magit-pop-revision-stack)
(keymap-set git-commit-mode-map "C-c C-w" #'magit-pop-revision-stack)
;;;###autoload
(defun magit-copy-section-value (arg)
@@ -779,7 +781,7 @@ argument."
(replace-regexp-in-string
(format "^\\%c.*\n?" (if (< (prefix-numeric-value arg) 0) ?+ ?-))
"")
(replace-regexp-in-string "^[ \\+\\-]" "")))
(replace-regexp-in-string "^[ +-]" "")))
(deactivate-mark))
((use-region-p)
(call-interactively #'copy-region-as-kill))
@@ -857,7 +859,7 @@ abbreviated revision to the `kill-ring' and the
The buffer is displayed using `magit-display-buffer', which see."
(interactive (list (magit--read-repository-buffer
"Display magit buffer: ")))
(magit-display-buffer buffer))
(magit-display-buffer (get-buffer buffer)))
;;;###autoload
(defun magit-switch-to-repository-buffer (buffer)

View File

@@ -1,6 +1,6 @@
;;; magit-fetch.el --- Download objects and refs -*- lexical-binding:t -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
@@ -28,12 +28,6 @@
(require 'magit)
(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
;;;###autoload (autoload 'magit-fetch "magit-fetch" nil t)
@@ -163,7 +157,7 @@ removed on the respective remote."
;;;###autoload (autoload 'magit-fetch-modules "magit-fetch" nil t)
(transient-define-prefix magit-fetch-modules (&optional transient args)
"Fetch all submodules.
"Fetch all populated submodules.
Fetching is done using \"git fetch --recurse-submodules\", which
means that the super-repository and recursively all submodules
@@ -172,10 +166,7 @@ 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")))
:value (list "--verbose" "--jobs=4")
["Arguments"
("-v" "verbose" "--verbose")
("-j" "number of jobs" "--jobs=" :reader transient-read-number-N+)]

View File

@@ -1,6 +1,6 @@
;;; magit-files.el --- Finding files -*- lexical-binding:t -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
@@ -179,12 +179,19 @@ then only after asking. A non-nil value for REVERT is ignored if REV is
(after-change-major-mode-hook
(remq 'global-diff-hl-mode-enable-in-buffers
after-change-major-mode-hook)))
(delay-mode-hooks
(normal-mode t)))
(normal-mode t))
(setq buffer-read-only t)
(set-buffer-modified-p nil)
(goto-char (point-min))))
(defun magit--lsp--disable-when-visiting-blob (fn &rest args)
"Do nothing when visiting blob using `magit-find-file' and similar.
See also https://github.com/doomemacs/doomemacs/pull/6309."
(unless magit-buffer-revision
(apply fn args)))
(advice-add 'lsp :around #'magit--lsp--disable-when-visiting-blob)
;;; Find Index
(defvar magit-find-index-hook nil)
@@ -203,7 +210,8 @@ 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-name (magit-git-dir "magit-update-index-")))
(let ((index (make-temp-name
(expand-file-name "magit-update-index-" (magit-gitdir))))
(buffer (current-buffer)))
(when magit-wip-before-change-mode
(magit-wip-commit-before-change (list file) " before un-/stage"))
@@ -226,8 +234,9 @@ is done using `magit-find-index-noselect'."
(when magit-wip-after-apply-mode
(magit-wip-commit-after-apply (list file) " after un-/stage")))
(message "Abort")))
(--when-let (magit-get-mode-buffer 'magit-status-mode)
(with-current-buffer it (magit-refresh)))
(when-let ((buffer (magit-get-mode-buffer 'magit-status-mode)))
(with-current-buffer buffer
(magit-refresh)))
t)
;;; Find Config File
@@ -243,7 +252,7 @@ This command is like `find-file', except that it temporarily
binds `default-directory' to the actual git directory, while
reading the FILENAME."
(interactive
(let ((default-directory (magit-git-dir)))
(let ((default-directory (magit-gitdir)))
(find-file-read-args "Find file: "
(confirm-nonexistent-file-or-buffer))))
(find-file filename wildcards))
@@ -259,7 +268,7 @@ This command is like `find-file-other-window', except that it
temporarily binds `default-directory' to the actual git
directory, while reading the FILENAME."
(interactive
(let ((default-directory (magit-git-dir)))
(let ((default-directory (magit-gitdir)))
(find-file-read-args "Find file in other window: "
(confirm-nonexistent-file-or-buffer))))
(find-file-other-window filename wildcards))
@@ -275,7 +284,7 @@ This command is like `find-file-other-frame', except that it
temporarily binds `default-directory' to the actual git
directory, while reading the FILENAME."
(interactive
(let ((default-directory (magit-git-dir)))
(let ((default-directory (magit-gitdir)))
(find-file-read-args "Find file in other frame: "
(confirm-nonexistent-file-or-buffer))))
(find-file-other-frame filename wildcards))
@@ -288,50 +297,61 @@ directory, while reading the FILENAME."
When invoked outside a file-visiting buffer, then fall back
to `magit-dispatch'."
:info-manual "(magit) Minor Mode for Buffers Visiting Files"
["Actions"
[("s" "Stage" magit-stage-file)
("u" "Unstage" magit-unstage-file)
("c" "Commit" magit-commit)
("e" "Edit line" magit-edit-line-commit)]
[("D" "Diff..." magit-diff)
("d" "Diff" magit-diff-buffer-file)
("g" "Status" magit-status-here)]
[("L" "Log..." magit-log)
[:if magit-file-relative-name
["File actions"
(" s" "Stage" magit-stage-buffer-file)
(" u" "Unstage" magit-unstage-buffer-file)
(", x" "Untrack" magit-file-untrack)
(", r" "Rename" magit-file-rename)
(", k" "Delete" magit-file-delete)
(", c" "Checkout" magit-file-checkout)]
["Inspect"
("D" "Diff..." magit-diff)
("d" "Diff" magit-diff-buffer-file)]
[""
("L" "Log..." magit-log)
("l" "Log" magit-log-buffer-file)
("t" "Trace" magit-log-trace-definition)
(7 "M" "Merged" magit-log-merged)]
[("B" "Blame..." magit-blame)
[""
("B" "Blame..." magit-blame)
("b" "Blame" magit-blame-addition)
("r" "...removal" magit-blame-removal)
("f" "...reverse" magit-blame-reverse)
("m" "Blame echo" magit-blame-echo)
("q" "Quit blame" magit-blame-quit)]
[("p" "Prev blob" magit-blob-previous)
("n" "Next blob" magit-blob-next)
("v" "Goto blob" magit-find-file)
("V" "Goto file" magit-blob-visit-file)]
[(5 "C-c r" "Rename file" magit-file-rename)
(5 "C-c d" "Delete file" magit-file-delete)
(5 "C-c u" "Untrack file" magit-file-untrack)
(5 "C-c c" "Checkout file" magit-file-checkout)]]
(interactive)
(transient-setup
(if (magit-file-relative-name)
'magit-file-dispatch
'magit-dispatch)))
["Navigate"
("p" "Prev blob" magit-blob-previous)
("n" "Next blob" magit-blob-next)
("v" "Goto blob" magit-find-file)
("V" "Goto file" magit-blob-visit-file)
("g" "Goto status" magit-status-here)
("G" "Goto magit" magit-display-repository-buffer)]
["More actions"
("c" "Commit" magit-commit)
("e" "Edit line" magit-edit-line-commit)]]
[:if-not magit-file-relative-name
["File actions"
("s" "Stage" magit-stage-file)
("u" "Unstage" magit-unstage-file)
("x" "Untrack" magit-file-untrack)
("r" "Rename" magit-file-rename)
("k" "Delete" magit-file-delete)
("c" "Checkout" magit-file-checkout)]
["Navigate"
("g" "Goto status" magit-status-here :if-not-mode magit-status-mode)
("G" "Goto magit" magit-display-repository-buffer)]])
;;; Blob Mode
(defvar magit-blob-mode-map
(let ((map (make-sparse-keymap)))
(define-key map "p" #'magit-blob-previous)
(define-key map "n" #'magit-blob-next)
(define-key map "b" #'magit-blame-addition)
(define-key map "r" #'magit-blame-removal)
(define-key map "f" #'magit-blame-reverse)
(define-key map "q" #'magit-kill-this-buffer)
map)
"Keymap for `magit-blob-mode'.")
(defvar-keymap magit-blob-mode-map
:doc "Keymap for `magit-blob-mode'."
"p" #'magit-blob-previous
"n" #'magit-blob-next
"b" #'magit-blame-addition
"r" #'magit-blame-removal
"f" #'magit-blame-reverse
"q" #'magit-kill-this-buffer)
(define-minor-mode magit-blob-mode
"Enable some Magit features in blob-visiting buffers.
@@ -356,8 +376,8 @@ Currently this only adds the following key bindings.
(interactive)
(if-let ((file (or magit-buffer-file-name
(buffer-file-name (buffer-base-buffer)))))
(--if-let (magit-blob-ancestor magit-buffer-revision file)
(magit-blob-visit it)
(if-let ((ancestor (magit-blob-ancestor magit-buffer-revision file)))
(magit-blob-visit ancestor)
(user-error "You have reached the beginning of time"))
(user-error "Buffer isn't visiting a file or blob")))
@@ -419,7 +439,7 @@ Git, fallback to using `rename-file'."
(user-error "%s already exists" dstfile))
(unless (file-exists-p dstdir)
(user-error "Destination directory %s does not exist" dstdir))
(if (magit-file-tracked-p (magit-convert-filename-for-git file))
(if (magit-file-tracked-p file)
(magit-call-git "mv"
(magit-convert-filename-for-git file)
(magit-convert-filename-for-git newname))
@@ -439,11 +459,10 @@ Git, fallback to using `rename-file'."
With a prefix argument FORCE do so even when the files have
staged as well as unstaged changes."
(interactive (list (or (--if-let (magit-region-values 'file t)
(progn
(unless (magit-file-tracked-p (car it))
(user-error "Already untracked"))
(magit-confirm-files 'untrack it "Untrack"))
(interactive (list (or (if-let ((files (magit-region-values 'file t)))
(if (magit-file-tracked-p (car files))
(magit-confirm-files 'untrack files "Untrack")
(user-error "Already untracked"))
(list (magit-read-tracked-file "Untrack file"))))
current-prefix-arg))
(magit-with-toplevel
@@ -455,8 +474,8 @@ staged as well as unstaged changes."
With a prefix argument FORCE do so even when the files have
uncommitted changes. When the files aren't being tracked in
Git, then fallback to using `delete-file'."
(interactive (list (--if-let (magit-region-values 'file t)
(magit-confirm-files 'delete it "Delete")
(interactive (list (if-let ((files (magit-region-values 'file t)))
(magit-confirm-files 'delete files "Delete")
(list (magit-read-file "Delete file")))
current-prefix-arg))
(if (magit-file-tracked-p (car files))
@@ -487,13 +506,15 @@ Git, then fallback to using `delete-file'."
(car (member (or default (magit-current-file)) files)))))
(defun magit-read-file (prompt &optional tracked-only)
(let ((choices (nconc (magit-list-files)
(unless tracked-only (magit-untracked-files)))))
(magit-completing-read
prompt choices nil t nil nil
(car (member (or (magit-section-value-if '(file submodule))
(magit-file-relative-name nil tracked-only))
choices)))))
(magit-with-toplevel
(let ((choices (nconc (magit-list-files)
(and (not tracked-only)
(magit-untracked-files)))))
(magit-completing-read
prompt choices nil t nil nil
(car (member (or (magit-section-value-if '(file submodule))
(magit-file-relative-name nil tracked-only))
choices))))))
(defun magit-read-tracked-file (prompt)
(magit-read-file prompt t))

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
;;; magit-gitignore.el --- Intentionally untracked files -*- lexical-binding:t -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
@@ -84,7 +84,7 @@ Also stage the file."
"Add the Git ignore RULE to \"$GIT_DIR/info/exclude\".
Rules in that file only affects this clone of the repository."
(interactive (list (magit-gitignore-read-pattern)))
(magit--gitignore rule (magit-git-dir "info/exclude"))
(magit--gitignore rule (expand-file-name "info/exclude" (magit-gitdir)))
(magit-refresh))
;;;###autoload
@@ -126,10 +126,10 @@ Rules that are defined in that file affect all local repositories."
;; The untracked section of the status buffer lists
;; directories containing only untracked files.
;; Add those as candidates.
(-filter #'directory-name-p
(magit-list-files
"--other" "--exclude-standard" "--directory"
"--no-empty-directory" "--" base)))
(seq-filter #'directory-name-p
(magit-list-files
"--other" "--exclude-standard" "--directory"
"--no-empty-directory" "--" base)))
#'string-lessp)))))
(when default
(setq default (concat "/" default))

View File

@@ -1,6 +1,6 @@
;;; magit-log.el --- Inspect Git history -*- lexical-binding:t; coding:utf-8 -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
@@ -70,7 +70,14 @@
:type 'hook)
(defcustom magit-log-remove-graph-args '("--follow" "--grep" "-G" "-S" "-L")
"The log arguments that cause the `--graph' argument to be dropped."
"The log arguments that cause the `--graph' argument to be dropped.
The default value lists the arguments that are incompatible with
`--graph' and therefore must be dropped when that is used. You
can add additional arguments that are available in `magit-log',
but I recommend that you don't do that. Nowadays I would define
this as a constant, but I am preserving it as an option, in case
someone actually customized it."
:package-version '(magit . "2.3.0")
:group 'magit-log
:type '(repeat (string :tag "Argument"))
@@ -162,6 +169,26 @@ because the latter may make use of Imenu's outdated cache."
(function-item add-log-current-defun)
function))
(defcustom magit-log-color-graph-limit 256
"Number of commits over which log graphs are not colored.
When showing more commits than specified, then the `--color'
argument is silently dropped. This is necessary because the
`ansi-color' library, which is used to turn control sequences
into faces, is just too slow."
:package-version '(magit . "4.0.0")
:group 'magit-log
:type 'number)
(defcustom magit-log-show-signatures-limit 256
"Number of commits over which signatures are not verified.
When showing more commits than specified by this option, then the
`--show-signature' argument, if specified, is silently dropped.
This is necessary because checking the signature of a large
number of commits is just too slow."
:package-version '(magit . "4.0.0")
:group 'magit-log
:type 'number)
(defface magit-log-graph
'((((class color) (background light)) :foreground "grey30")
(((class color) (background dark)) :foreground "grey80"))
@@ -348,9 +375,7 @@ commits before and half after."
(defun magit-log-arguments (&optional mode)
"Return the current log arguments."
(if (memq transient-current-command '(magit-log magit-log-refresh))
(pcase-let ((`(,args ,alist)
(-separate #'atom (transient-get-value))))
(list args (cdr (assoc "--" alist))))
(magit--transient-args-and-files)
(magit-log--get-value (or mode 'magit-log-mode))))
(defun magit-log--get-value (mode &optional use-buffer-args)
@@ -383,9 +408,7 @@ commits before and half after."
(pcase-let* ((obj (oref obj prototype))
(mode (or (oref obj major-mode) major-mode))
(key (intern (format "magit-log:%s" mode)))
(`(,args ,alist)
(-separate #'atom (transient-get-value)))
(files (cdr (assoc "--" alist))))
(`(,args ,files) (magit--transient-args-and-files)))
(put mode 'magit-log-current-arguments args)
(when save
(setf (alist-get key transient-values) args)
@@ -514,13 +537,13 @@ commits before and half after."
("-d" "Show refnames" "--decorate")]
[["Refresh"
("g" "buffer" magit-log-refresh)
("s" "buffer and set defaults" transient-set :transient nil)
("w" "buffer and save defaults" transient-save :transient nil)]
("s" "buffer and set defaults" transient-set-and-exit)
("w" "buffer and save defaults" transient-save-and-exit)]
["Margin"
("L" "toggle visibility" magit-toggle-margin :transient t)
("l" "cycle style" magit-cycle-margin-style :transient t)
("d" "toggle details" magit-toggle-margin-details)
("x" "toggle shortstat" magit-toggle-log-margin-style)]
("L" "toggle visibility" magit-toggle-margin :transient t)
("l" "cycle style" magit-cycle-margin-style :transient t)
("d" "toggle details" magit-toggle-margin-details :transient t)
("x" "toggle shortstat" magit-toggle-log-margin-style :transient t)]
[:if-mode magit-log-mode
:description "Toggle"
("b" "buffer lock" magit-toggle-buffer-lock)]]
@@ -610,23 +633,21 @@ commits before and half after."
;;;; Setup Commands
(defvar magit-log-read-revs-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map crm-local-completion-map)
(define-key map "\s" #'self-insert-command)
map))
(defvar-keymap magit-log-read-revs-map
:parent crm-local-completion-map
"SPC" #'self-insert-command)
(defun magit-log-read-revs (&optional use-current)
(or (and use-current (and-let* ((buf (magit-get-current-branch))) (list buf)))
(let ((crm-separator "\\(\\.\\.\\.?\\|[, ]\\)")
(crm-local-completion-map magit-log-read-revs-map))
(split-string (magit-completing-read-multiple*
(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)))
(and (not use-current)
(magit-get-previous-branch)))
nil t)
"[, ]" t))))
@@ -845,7 +866,7 @@ https://github.com/mhagger/git-when-merged."
(if (equal m "Commit is directly on this branch.")
(let* ((from (format "%s~%d" commit
(/ magit-log-merged-commit-count 2)))
(to (- (car (magit-rev-diff-count branch commit))
(to (- (car (magit-rev-diff-count branch commit t))
(/ magit-log-merged-commit-count 2)))
(to (if (<= to 0)
branch
@@ -883,16 +904,16 @@ limit. Otherwise set it to 256."
(arg (--first (string-match "^-n\\([0-9]+\\)?$" it) val))
(num (and arg (string-to-number (match-string 1 arg))))
(num (if num (funcall fn num 2) 256)))
(setq val (delete arg val))
(setq val (remove arg val))
(setq magit-buffer-log-args
(if (and num (> num 0))
(cons (format "-n%i" num) val)
(cons (format "-n%d" num) val)
val)))
(magit-refresh))
(defun magit-log-get-commit-limit ()
(defun magit-log-get-commit-limit (&optional args)
(and-let* ((str (--first (string-match "^-n\\([0-9]+\\)?$" it)
magit-buffer-log-args)))
(or args magit-buffer-log-args))))
(string-to-number (match-string 1 str))))
;;;; Mode Commands
@@ -1004,19 +1025,17 @@ of the current repository first; creating it if necessary."
'("-G" "--grep" "--author")
"Arguments which disable the graph speedup hack.")
(defvar magit-log-mode-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map magit-mode-map)
(define-key map (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)
(define-key map "q" #'magit-log-bury-buffer)
map)
"Keymap for `magit-log-mode'.")
(defvar-keymap magit-log-mode-map
:doc "Keymap for `magit-log-mode'."
:parent magit-mode-map
"C-c C-b" #'magit-go-backward
"C-c C-f" #'magit-go-forward
"C-c C-n" #'magit-log-move-to-parent
"j" #'magit-log-move-to-revision
"=" #'magit-log-toggle-commit-limit
"+" #'magit-log-double-commit-limit
"-" #'magit-log-half-commit-limit
"q" #'magit-log-bury-buffer)
(define-derived-mode magit-log-mode magit-mode "Magit Log"
"Mode for looking at Git log.
@@ -1057,7 +1076,8 @@ Type \\[magit-reset] to reset `HEAD' to the commit at point.
(defun magit-log-refresh-buffer ()
(let ((revs magit-buffer-revisions)
(args magit-buffer-log-args)
(files magit-buffer-log-files))
(files magit-buffer-log-files)
(limit (magit-log-get-commit-limit)))
(magit-set-header-line-format
(funcall magit-log-header-line-function revs args files))
(unless (length= files 1)
@@ -1067,27 +1087,49 @@ Type \\[magit-reset] to reset `HEAD' to the commit at point.
(concat "^" (regexp-opt magit-log-remove-graph-args)) it)
args))
(setq args (remove "--graph" args)))
(unless (member "--graph" args)
(setq args (remove "--color" args)))
(when-let* ((limit (magit-log-get-commit-limit))
(setq args (magit-log--maybe-drop-color-graph args limit))
(when-let* ((limit limit)
(limit (* 2 limit)) ; increase odds for complete graph
(count (and (length= revs 1)
(> limit 1024) ; otherwise it's fast enough
(setq revs (car revs))
(not (string-search ".." revs))
(not (member revs '("--all" "--branches")))
(-none-p (lambda (arg)
(--any-p
(string-prefix-p it arg)
magit-log-disable-graph-hack-args))
args)
(not (seq-some
(lambda (arg)
(--any-p (string-prefix-p it arg)
magit-log-disable-graph-hack-args))
args))
(magit-git-string "rev-list" "--count"
"--first-parent" args revs))))
(setq revs (if (< (string-to-number count) limit)
revs
(format "%s~%s..%s" revs limit revs))))
(let ((delay (cl-find-if (lambda (arg)
(member arg '("++header" "--patch" "--stat")))
args)))
(setq magit-section-inhibit-markers (if delay 'delay t))
(setq magit-section-insert-in-reverse (not delay)))
(magit-insert-section (logbuf)
(magit-insert-log revs args files))))
(magit--insert-log t revs args files))))
(defvar-local magit-log--color-graph nil)
(defun magit-log--maybe-drop-color-graph (args limit)
(if (member "--color" args)
(if (cond ((not (member "--graph" args)))
((not magit-log-color-graph-limit) nil)
((not limit)
(message "Dropping --color because -n isn't set (see %s)"
'magit-log-color-graph-limit))
((> limit magit-log-color-graph-limit)
(message "Dropping --color because -n is larger than %s"
'magit-log-color-graph-limit)))
(progn (setq args (remove "--color" args))
(setq magit-log--color-graph nil))
(setq magit-log--color-graph t))
(setq magit-log--color-graph nil))
args)
(cl-defmethod magit-buffer-value (&context (major-mode magit-log-mode))
(append magit-buffer-revisions
@@ -1117,11 +1159,17 @@ Type \\[magit-reset] to reset `HEAD' to the commit at point.
args)))
(defun magit-insert-log (revs &optional args files)
(declare (obsolete magit--insert-log "Magit 4.0.0"))
(magit--insert-log nil revs args files))
(defun magit--insert-log (keep-error revs &optional args files)
"Insert a log section.
Do not add this to a hook variable."
(declare (indent defun))
(setq magit-section-preserve-visibility t) ; TODO do it here?
(let ((magit-git-global-arguments
(remove "--literal-pathspecs" magit-git-global-arguments)))
(magit-git-wash (apply-partially #'magit-log-wash-log 'log)
(magit--git-wash (apply-partially #'magit-log-wash-log 'log) keep-error
"log"
(format "--format=%s%%h%%x0c%s%%x0c%s%%x0c%%aN%%x0c%s%%x0c%%s%s"
(if (and (member "--left-right" args)
@@ -1129,9 +1177,22 @@ Do not add this to a hook variable."
"%m "
"")
(if (member "--decorate" args) "%D" "")
(if (member "--show-signature" args)
(progn (setq args (remove "--show-signature" args)) "%G?")
"")
(if (not (member "--show-signature" args))
""
(setq args (remove "--show-signature" args))
(let ((limit (magit-log-get-commit-limit args)))
(cond
((not limit)
(message
"Dropping --show-signature because -n isn't set (see %s)"
'magit-log-show-signatures-limit)
"")
((> limit magit-log-show-signatures-limit)
(message
"Dropping --show-signature because -n is larger than %s"
'magit-log-show-signatures-limit)
"")
("%G?"))))
(if magit-log-margin-show-committer-date "%ct" "%at")
(if (member "++header" args)
(if (member "--graph" (setq args (remove "++header" args)))
@@ -1139,9 +1200,10 @@ Do not add this to a hook variable."
(concat "\n" magit-log-revision-headers-format "\n"))
""))
(progn
(--when-let (--first (string-match "^\\+\\+order=\\(.+\\)$" it) args)
(setq args (cons (format "--%s-order" (match-string 1 it))
(remove it args))))
(when-let ((order (--first (string-match "^\\+\\+order=\\(.+\\)$" it)
args)))
(setq args (cons (format "--%s-order" (match-string 1 order))
(remove order args))))
(when (member "--decorate" args)
(setq args (cons "--decorate=full" (remove "--decorate" args))))
(when (member "--reverse" args)
@@ -1154,26 +1216,18 @@ Do not add this to a hook variable."
(or (magit-diff--region-range)
(oref (magit-current-section) value)))
(defvar magit-commit-section-map
(let ((map (make-sparse-keymap)))
;; The second remapping overrides the first but we still get two menu
;; items, though only one of them will be available at any given time.
(magit-menu-set map [magit-visit-thing]
#'magit-diff-range "Diff %x"
'(:visible (region-active-p)))
(magit-menu-set map [magit-visit-thing]
#'magit-show-commit "Show commit %x"
'(:visible (not (region-active-p))))
(magit-menu-set map [magit-cherry-apply]
#'magit-cherry-apply "Apply %x")
map)
"Keymap for `commit' sections.")
(defvar-keymap magit-commit-section-map
:doc "Keymap for `commit' sections."
"<remap> <magit-visit-thing>" #'magit-show-commit
"<3>" (magit-menu-item "Apply %x" #'magit-cherry-apply)
"<2>" (magit-menu-item "Show commit %x" #'magit-show-commit
'(:visible (not (region-active-p))))
"<1>" (magit-menu-item "Diff %x" #'magit-diff-range
'(:visible (region-active-p))))
(defvar magit-module-commit-section-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map magit-commit-section-map)
map)
"Keymap for `module-commit' sections.")
(defvar-keymap magit-module-commit-section-map
:doc "Keymap for `module-commit' sections."
:parent magit-commit-section-map)
(defconst magit-log-heading-re
;; Note: A form feed instead of a null byte is used as the delimiter
@@ -1222,7 +1276,7 @@ Do not add this to a hook variable."
"\\(?:\\(?:[^@\n]+@{\\(?6:[^}\n]+\\)}\0" ; date
;;; refsub
"\\(?10:merge \\|autosave \\|restart \\|rewritten \\|[^:\n]+: \\)?"
"\\(?2:.*\\)?\\)\\|\0\\)$")) ; msg
"\\(?2:.*\\)\\)\\|\0\\)$")) ; msg
(defconst magit-reflog-subject-re
(concat "\\(?1:[^ ]+\\) ?" ; command
@@ -1242,8 +1296,10 @@ Do not add this to a hook variable."
(defun magit-log-wash-log (style args)
(setq args (flatten-tree args))
(when (and (member "--graph" args)
(member "--color" args))
(when (if (derived-mode-p 'magit-log-mode)
magit-log--color-graph
(and (member "--graph" args)
(member "--color" args)))
(let ((ansi-color-apply-face-function
(lambda (beg end face)
(put-text-property beg end 'font-lock-face
@@ -1342,8 +1398,7 @@ Do not add this to a hook variable."
(insert (magit-reflog-format-subject
(substring refsub 0
(if (string-search ":" refsub) -2 -1))))))
(when msg
(insert (funcall magit-log-format-message-function hash msg)))
(insert (funcall magit-log-format-message-function hash msg))
(when (and refs magit-log-show-refname-after-summary)
(insert ?\s)
(insert (magit-format-ref-labels refs)))
@@ -1374,7 +1429,7 @@ Do not add this to a hook variable."
(forward-line)
(magit-insert-heading)
(re-search-forward "")
(backward-delete-char 1)
(delete-char -1)
(forward-char)
(insert ?\n))
(delete-char 1))
@@ -1414,7 +1469,7 @@ Do not add this to a hook variable."
(magit--put-face (match-beginning 0) (1- boundary)
'magit-keyword-squash msg))
(when magit-log-highlight-keywords
(while (string-match "\\[[^[]*?]" msg boundary)
(while (string-match "\\[[^][]*]" msg boundary)
(setq boundary (match-end 0))
(magit--put-face (match-beginning 0) boundary
'magit-keyword msg))))
@@ -1537,7 +1592,7 @@ The shortstat style is experimental and rather slow."
(or author "")
details-width
nil ?\s
(if (char-displayable-p ?…) "" ">"))
(magit--ellipsis 'margin))
'magit-log-author)
" "))
(magit--propertize-face
@@ -1547,7 +1602,7 @@ The shortstat style is experimental and rather slow."
(seconds-to-time (string-to-number date)))
(pcase-let* ((abbr (eq style 'age-abbreviated))
(`(,cnt ,unit) (magit--age date abbr)))
(format (format (if abbr "%%2i%%-%ic" "%%2i %%-%is")
(format (format (if abbr "%%2d%%-%dc" "%%2d %%-%ds")
(- width (if details (1+ details-width) 0)))
cnt unit)))
'magit-log-date))
@@ -1593,19 +1648,16 @@ The shortstat style is experimental and rather slow."
;;; Select Mode
(defvar magit-log-select-mode-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map magit-log-mode-map)
(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'.")
(defvar-keymap magit-log-select-mode-map
:doc "Keymap for `magit-log-select-mode'."
:parent magit-log-mode-map
"C-c C-b" #'undefined
"C-c C-f" #'undefined
"." #'magit-log-select-pick
"e" #'magit-log-select-pick
"C-c C-c" #'magit-log-select-pick
"q" #'magit-log-select-quit
"C-c C-k" #'magit-log-select-quit)
(put 'magit-log-select-pick :advertised-binding [?\C-c ?\C-c])
(put 'magit-log-select-quit :advertised-binding [?\C-c ?\C-k])
@@ -1634,9 +1686,13 @@ Type \\[magit-log-select-quit] to abort without selecting a commit."
(magit-buffer-log-args args)))
(defun magit-log-select-refresh-buffer ()
(setq magit-section-inhibit-markers t)
(setq magit-section-insert-in-reverse t)
(magit-insert-section (logbuf)
(magit-insert-log magit-buffer-revisions
magit-buffer-log-args)))
(magit--insert-log t magit-buffer-revisions
(magit-log--maybe-drop-color-graph
magit-buffer-log-args
(magit-log-get-commit-limit)))))
(cl-defmethod magit-buffer-value (&context (major-mode magit-log-select-mode))
magit-buffer-revisions)
@@ -1701,13 +1757,11 @@ Call `magit-log-select-quit-function' if set."
;;; Cherry Mode
(defvar magit-cherry-mode-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map magit-mode-map)
(define-key map "q" #'magit-log-bury-buffer)
(define-key map "L" #'magit-margin-settings)
map)
"Keymap for `magit-cherry-mode'.")
(defvar-keymap magit-cherry-mode-map
:doc "Keymap for `magit-cherry-mode'."
:parent magit-mode-map
"q" #'magit-log-bury-buffer
"L" #'magit-margin-settings)
(define-derived-mode magit-cherry-mode magit-mode "Magit Cherry"
"Mode for looking at commits not merged upstream.
@@ -1731,6 +1785,8 @@ Type \\[magit-cherry-pick] to apply the commit at point.
(magit-buffer-range (concat upstream ".." head))))
(defun magit-cherry-refresh-buffer ()
(setq magit-section-inhibit-markers t)
(setq magit-section-insert-in-reverse t)
(magit-insert-section (cherry)
(magit-run-section-hook 'magit-cherry-sections-hook)))
@@ -1771,20 +1827,17 @@ Type \\[magit-cherry-pick] to apply the commit at point.
;;; Log Sections
;;;; Standard Log Sections
(defvar magit-log-section-map
(let ((map (make-sparse-keymap)))
(magit-menu-set map [magit-visit-thing] #'magit-diff-dwim "Visit diff")
map)
"Keymap for log sections.
(defvar-keymap magit-log-section-map
:doc "Keymap for log sections.
The classes `magit-{unpulled,unpushed,unmerged}-section' derive
from the abstract `magit-log-section' class. Accordingly this
keymap is the parent of their keymaps.")
keymap is the parent of their keymaps."
"<remap> <magit-visit-thing>" #'magit-diff-dwim
"<1>" (magit-menu-item "Visit diff" #'magit-diff-dwim))
(defvar magit-unpulled-section-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map magit-log-section-map)
map)
"Keymap for `unpulled' sections.")
(defvar-keymap magit-unpulled-section-map
:doc "Keymap for `unpulled' sections."
:parent magit-log-section-map)
(cl-defmethod magit-section-ident-value ((section magit-unpulled-section))
"\"..@{push}\" cannot be used as the value because that is
@@ -1806,30 +1859,28 @@ in the pushremote case."
(format (propertize "Unpulled from %s."
'font-lock-face 'magit-section-heading)
upstream))
(magit-insert-log "..@{upstream}" magit-buffer-log-args)
(magit--insert-log nil "..@{upstream}" magit-buffer-log-args)
(magit-log-insert-child-count))))
(magit-define-section-jumper magit-jump-to-unpulled-from-pushremote
"Unpulled from <push-remote>" unpulled
(concat ".." (magit-get-push-branch)))
"Unpulled from <push-remote>" unpulled "..@{push}")
(defun magit-insert-unpulled-from-pushremote ()
"Insert commits that haven't been pulled from the push-remote yet."
(--when-let (magit-get-push-branch)
(when-let* ((target (magit-get-push-branch))
(range (concat ".." target)))
(when (magit--insert-pushremote-log-p)
(magit-insert-section (unpulled (concat ".." it) t)
(magit-insert-section (unpulled range t)
(magit-insert-heading
(format (propertize "Unpulled from %s."
'font-lock-face 'magit-section-heading)
(propertize it 'font-lock-face 'magit-branch-remote)))
(magit-insert-log (concat ".." it) magit-buffer-log-args)
(propertize target 'font-lock-face 'magit-branch-remote)))
(magit--insert-log nil range magit-buffer-log-args)
(magit-log-insert-child-count)))))
(defvar magit-unpushed-section-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map magit-log-section-map)
map)
"Keymap for `unpushed' sections.")
(defvar-keymap magit-unpushed-section-map
:doc "Keymap for `unpushed' sections."
:parent magit-log-section-map)
(cl-defmethod magit-section-ident-value ((section magit-unpushed-section))
"\"..@{push}\" cannot be used as the value because that is
@@ -1864,7 +1915,7 @@ then show the last `magit-log-section-commit-count' commits."
(format (propertize "Unmerged into %s."
'font-lock-face 'magit-section-heading)
(magit-get-upstream-branch)))
(magit-insert-log "@{upstream}.." magit-buffer-log-args)
(magit--insert-log nil "@{upstream}.." magit-buffer-log-args)
(magit-log-insert-child-count))))
(defun magit-insert-recent-commits (&optional type value)
@@ -1877,25 +1928,25 @@ Show the last `magit-log-section-commit-count' commits."
(or value range)
t)
(magit-insert-heading "Recent commits")
(magit-insert-log range
(cons (format "-n%d" magit-log-section-commit-count)
(--remove (string-prefix-p "-n" it)
magit-buffer-log-args))))))
(magit--insert-log nil range
(cons (format "-n%d" magit-log-section-commit-count)
(--remove (string-prefix-p "-n" it)
magit-buffer-log-args))))))
(magit-define-section-jumper magit-jump-to-unpushed-to-pushremote
"Unpushed to <push-remote>" unpushed
(concat (magit-get-push-branch) ".."))
"Unpushed to <push-remote>" unpushed "@{push}..")
(defun magit-insert-unpushed-to-pushremote ()
"Insert commits that haven't been pushed to the push-remote yet."
(--when-let (magit-get-push-branch)
(when-let* ((target (magit-get-push-branch))
(range (concat target "..")))
(when (magit--insert-pushremote-log-p)
(magit-insert-section (unpushed (concat it "..") t)
(magit-insert-section (unpushed range t)
(magit-insert-heading
(format (propertize "Unpushed to %s."
'font-lock-face 'magit-section-heading)
(propertize it 'font-lock-face 'magit-branch-remote)))
(magit-insert-log (concat it "..") magit-buffer-log-args)
(propertize target 'font-lock-face 'magit-branch-remote)))
(magit--insert-log nil range magit-buffer-log-args)
(magit-log-insert-child-count)))))
(defun magit--insert-pushremote-log-p ()
@@ -1924,7 +1975,7 @@ Show the last `magit-log-section-commit-count' commits."
(defun magit-insert-unpulled-cherries ()
"Insert section showing unpulled commits.
Like `magit-insert-unpulled-from-upstream' but prefix each commit
which has not been applied yet (i.e. a commit with a patch-id
which has not been applied yet (i.e., a commit with a patch-id
not shared with any local commit) with \"+\", and all others with
\"-\"."
(when (magit-git-success "rev-parse" "@{upstream}")
@@ -1937,7 +1988,7 @@ not shared with any local commit) with \"+\", and all others with
(defun magit-insert-unpushed-cherries ()
"Insert section showing unpushed commits.
Like `magit-insert-unpushed-to-upstream' but prefix each commit
which has not been applied to upstream yet (i.e. a commit with
which has not been applied to upstream yet (i.e., a commit with
a patch-id not shared with any upstream commit) with \"+\", and
all others with \"-\"."
(when (magit-git-success "rev-parse" "@{upstream}")

View File

@@ -1,6 +1,6 @@
;;; magit-margin.el --- Margins in Magit buffers -*- lexical-binding:t -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
@@ -44,7 +44,7 @@ options to the same values by customizing `magit-log-margin'
values for the other options will default to what you have set
for that variable. Likewise if you set `magit-log-margin's INIT
to nil, then that is used in the default of all other options. But
setting it to t, i.e. re-enforcing the default for that option,
setting it to t, i.e., re-enforcing the default for that option,
does not carry to other options."
:link '(info-link "(magit)Log Margin")
:group 'magit-log)
@@ -165,14 +165,15 @@ does not carry to other options."
(list (list 'margin 'right-margin)
(or string " ")))))))
(defvar magit-margin-overlay-conditions
'( unpulled unpushed recent stashes local cherries
[remote branchbuf]
[tags branchbuf]
topics issues pullreqs))
(defun magit-maybe-make-margin-overlay ()
(when (or (magit-section-match
'(unpulled unpushed recent stashes local cherries)
magit-insert-section--current)
(and (eq major-mode 'magit-refs-mode)
(magit-section-match
'(remote commit tags)
magit-insert-section--current)))
(when (magit-section-match magit-margin-overlay-conditions
magit-insert-section--current)
(magit-make-margin-overlay nil t)))
;;; Custom Support

View File

@@ -1,6 +1,6 @@
;;; magit-merge.el --- Merge functionality -*- lexical-binding:t -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
@@ -232,7 +232,7 @@ then also remove the respective remote branch."
"Abort the current merge operation.
\n(git merge --abort)"
(interactive)
(unless (file-exists-p (magit-git-dir "MERGE_HEAD"))
(unless (file-exists-p (expand-file-name "MERGE_HEAD" (magit-gitdir)))
(user-error "No merge in progress"))
(magit-confirm 'abort-merge)
(magit-run-git-async "merge" "--abort"))
@@ -266,12 +266,13 @@ then also remove the respective remote branch."
;;; Utilities
(defun magit-merge-in-progress-p ()
(file-exists-p (magit-git-dir "MERGE_HEAD")))
(file-exists-p (expand-file-name "MERGE_HEAD" (magit-gitdir))))
(defun magit--merge-range (&optional head)
(unless head
(setq head (magit-get-shortname
(car (magit-file-lines (magit-git-dir "MERGE_HEAD"))))))
(car (magit-file-lines
(expand-file-name "MERGE_HEAD" (magit-gitdir)))))))
(and head
(concat (magit-git-string "merge-base" "--octopus" "HEAD" head)
".." head)))
@@ -285,15 +286,14 @@ then also remove the respective remote branch."
(magit-read-char-case (format "For %s checkout: " file) t
(?o "[o]ur stage" "--ours")
(?t "[t]heir stage" "--theirs")
(?c "[c]onflict" "--merge")))
(?c (if magit-verbose-messages "restore [c]onflict" "[c]onflict")
"--merge")))
;;; Sections
(defvar magit-unmerged-section-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map magit-log-section-map)
map)
"Keymap for `unmerged' sections.")
(defvar-keymap magit-unmerged-section-map
:doc "Keymap for `unmerged' sections."
:parent magit-log-section-map)
(defun magit-insert-merge-log ()
"Insert section for the on-going merge.
@@ -301,17 +301,18 @@ Display the heads that are being merged.
If no merge is in progress, do nothing."
(when (magit-merge-in-progress-p)
(let* ((heads (mapcar #'magit-get-shortname
(magit-file-lines (magit-git-dir "MERGE_HEAD"))))
(magit-file-lines
(expand-file-name "MERGE_HEAD" (magit-gitdir)))))
(range (magit--merge-range (car heads))))
(magit-insert-section (unmerged range)
(magit-insert-heading
(format "Merging %s:" (mapconcat #'identity heads ", ")))
(magit-insert-log
range
(let ((args magit-buffer-log-args))
(unless (member "--decorate=full" magit-buffer-log-args)
(push "--decorate=full" args))
args))))))
(magit--insert-log nil
range
(let ((args magit-buffer-log-args))
(unless (member "--decorate=full" magit-buffer-log-args)
(push "--decorate=full" args))
args))))))
;;; _
(provide 'magit-merge)

View File

@@ -1,6 +1,6 @@
;;; magit-mode.el --- Create and refresh Magit buffers -*- lexical-binding:t -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
@@ -35,6 +35,12 @@
(require 'help-mode)
(require 'transient)
(defvar bookmark-make-record-function)
(defvar magit--wip-inhibit-autosave)
(defvar magit-wip-after-save-local-mode)
(declare-function magit-wip-get-ref "magit-wip" ())
(declare-function magit-wip-commit-worktree "magit-wip" (ref files msg))
;;; Options
(defcustom magit-mode-hook
@@ -161,15 +167,9 @@ The following %-sequences are supported:
empty string. Due to limitations of the `uniquify' package,
buffer names must end with the path.
`%T' Obsolete, use \"%t%x\" instead. Like \"%t\", but append an
asterisk if and only if `magit-uniquify-buffer-names' is nil.
The value should always contain \"%m\" or \"%M\", \"%v\" or
\"%V\", and \"%t\" (or the obsolete \"%T\").
If `magit-uniquify-buffer-names' is non-nil, then the value must
end with \"%t\" or \"%t%x\" (or the obsolete \"%T\"). See issue
#2841.
The value should always contain \"%m\" or \"%M\", \"%v\" or \"%V\", and
\"%t\". If `magit-uniquify-buffer-names' is non-nil, then the
value must end with \"%t\" or \"%t%x\". See issue #2841.
This is used by `magit-generate-buffer-name-default-function'.
If another `magit-generate-buffer-name-function' is used, then
@@ -231,7 +231,7 @@ and Buffer Variables'."
This affects certain commands such as `magit-show-commit' that
are suffixes of the diff or log transient prefix commands, but
only if they are invoked directly, i.e. *not* as a suffix.
only if they are invoked directly, i.e., *not* as a suffix.
Valid values are:
@@ -321,123 +321,130 @@ recommended value."
;;; Key Bindings
(defvar magit-mode-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map magit-section-mode-map)
;; Don't function-quote but make sure all commands are autoloaded.
(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 "a" 'magit-cherry-apply)
(define-key map "A" 'magit-cherry-pick)
(define-key map "b" 'magit-branch)
(define-key map "B" 'magit-bisect)
(define-key map "c" 'magit-commit)
(define-key map "C" 'magit-clone)
(define-key map "d" 'magit-diff)
(define-key map "D" 'magit-diff-refresh)
(define-key map "e" 'magit-ediff-dwim)
(define-key map "E" 'magit-ediff)
(define-key map "f" 'magit-fetch)
(define-key map "F" 'magit-pull)
(define-key map "g" 'magit-refresh)
(define-key map "G" 'magit-refresh-all)
(define-key map "h" 'magit-dispatch)
(define-key map "?" 'magit-dispatch)
(define-key map "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)
(define-key map "S" 'magit-stage-modified)
(define-key map "t" 'magit-tag)
(define-key map "T" 'magit-notes)
(define-key map "u" 'magit-unstage-file)
(define-key map "U" 'magit-unstage-all)
(define-key map "v" 'magit-revert-no-commit)
(define-key map "V" 'magit-revert)
(define-key map "w" 'magit-am)
(define-key map "W" 'magit-patch)
(define-key map "x" 'magit-reset-quickly)
(define-key map "X" 'magit-reset)
(define-key map "y" 'magit-show-refs)
(define-key map "Y" 'magit-cherry)
(define-key map "z" 'magit-stash)
(define-key map "Z" 'magit-worktree)
(define-key map "%" 'magit-worktree)
(define-key map "$" 'magit-process-buffer)
(define-key map "!" 'magit-run)
(define-key map ">" 'magit-sparse-checkout)
(define-key map (kbd "C-c C-c") 'magit-dispatch)
(define-key map (kbd "C-c C-e") 'magit-edit-thing)
(define-key map (kbd "C-c C-o") 'magit-browse-thing)
(define-key map (kbd "C-c C-w") 'magit-browse-thing)
(define-key map (kbd "C-w") 'magit-copy-section-value)
(define-key map (kbd "M-w") 'magit-copy-buffer-revision)
(define-key map [remap previous-line] 'magit-previous-line)
(define-key map [remap next-line] 'magit-next-line)
(define-key map [remap evil-previous-line] 'evil-previous-visual-line)
(define-key map [remap evil-next-line] 'evil-next-visual-line)
map)
"Parent keymap for all keymaps of modes derived from `magit-mode'.")
(defvar-keymap magit-mode-map
:doc "Parent keymap for all keymaps of modes derived from `magit-mode'."
:parent magit-section-mode-map
;; Don't function-quote but make sure all commands are autoloaded.
"C-<return>" 'magit-visit-thing
"RET" 'magit-visit-thing
"M-TAB" 'magit-dired-jump
"M-<tab>" 'magit-section-cycle-diffs
"SPC" 'magit-diff-show-or-scroll-up
"S-SPC" 'magit-diff-show-or-scroll-down
"DEL" 'magit-diff-show-or-scroll-down
"+" 'magit-diff-more-context
"-" 'magit-diff-less-context
"0" 'magit-diff-default-context
"a" 'magit-cherry-apply
"A" 'magit-cherry-pick
"b" 'magit-branch
"B" 'magit-bisect
"c" 'magit-commit
"C" 'magit-clone
"d" 'magit-diff
"D" 'magit-diff-refresh
"e" 'magit-ediff-dwim
"E" 'magit-ediff
"f" 'magit-fetch
"F" 'magit-pull
"g" 'magit-refresh
"G" 'magit-refresh-all
"h" 'magit-dispatch
"?" 'magit-dispatch
"H" 'magit-describe-section
"i" 'magit-gitignore
"I" 'magit-init
"j" 'magit-status-quick
"J" 'magit-display-repository-buffer
"k" 'magit-delete-thing
"K" 'magit-file-untrack
"l" 'magit-log
"L" 'magit-log-refresh
"m" 'magit-merge
"M" 'magit-remote
;; "n" magit-section-forward in magit-section-mode-map
;; "N" forge-dispatch, added by forge package
"o" 'magit-submodule
"O" 'magit-subtree
;; "p" magit-section-backward in magit-section-mode-map
"P" 'magit-push
"q" 'magit-mode-bury-buffer
"Q" 'magit-git-command
":" 'magit-git-command
"r" 'magit-rebase
"R" 'magit-file-rename
"s" 'magit-stage-file
"S" 'magit-stage-modified
"t" 'magit-tag
"T" 'magit-notes
"u" 'magit-unstage-file
"U" 'magit-unstage-all
"v" 'magit-revert-no-commit
"V" 'magit-revert
"w" 'magit-am
"W" 'magit-patch
"x" 'magit-reset-quickly
"X" 'magit-reset
"y" 'magit-show-refs
"Y" 'magit-cherry
"z" 'magit-stash
"Z" 'magit-worktree
"%" 'magit-worktree
"$" 'magit-process-buffer
"!" 'magit-run
">" 'magit-sparse-checkout
"C-c C-c" 'magit-dispatch
"C-c C-e" 'magit-edit-thing
"C-c C-o" 'magit-browse-thing
"C-c C-w" 'magit-copy-thing
"C-w" 'magit-copy-section-value
"M-w" 'magit-copy-buffer-revision
"<remap> <previous-line>" 'magit-previous-line
"<remap> <next-line>" 'magit-next-line
"<remap> <evil-previous-line>" 'evil-previous-visual-line
"<remap> <evil-next-line>" 'evil-next-visual-line)
(defun magit-delete-thing ()
"This is a placeholder command.
Where applicable, section-specific keymaps bind another command
which deletes the thing at point."
"This is a placeholder command, which signals an error if called.
Where applicable, other keymaps remap this command to another,
which actually deletes the thing at point."
(interactive)
(user-error "There is no thing at point that could be deleted"))
(defun magit-visit-thing ()
"This is a placeholder command.
Where applicable, section-specific keymaps bind another command
which visits the thing at point."
"This is a placeholder command, which may signal an error if called.
Where applicable, other keymaps remap this command to another,
which actually visits the thing at point."
(interactive)
(if (eq transient-current-command 'magit-dispatch)
(call-interactively (key-binding (this-command-keys)))
(user-error "There is no thing at point that could be visited")))
(defun magit-edit-thing ()
"This is a placeholder command.
Where applicable, section-specific keymaps bind another command
which lets you edit the thing at point, likely in another buffer."
"This is a placeholder command, which may signal an error if called.
Where applicable, other keymaps remap this command to another,
which actually lets you edit the thing at point, likely in another
buffer."
(interactive)
(if (eq transient-current-command 'magit-dispatch)
(call-interactively (key-binding (this-command-keys)))
(user-error "There is no thing at point that could be edited")))
(defun magit-browse-thing ()
"This is a placeholder command.
Where applicable, section-specific keymaps bind another command
which visits the thing at point using `browse-url'."
"This is a placeholder command, which signals an error if called.
Where applicable, other keymaps remap this command to another,
which actually visits thing at point using `browse-url'."
(interactive)
(user-error "There is no thing at point that could be browsed"))
(defun magit-copy-thing ()
"This is a placeholder command, which signals an error if called.
Where applicable, other keymaps remap this command to another,
which actually copies some representation of the thing at point
to the kill ring."
(interactive)
(user-error "There is no thing at point that we know how to copy"))
;;;###autoload
(defun magit-info ()
"Visit the Magit manual."
@@ -446,8 +453,8 @@ which visits the thing at point using `browse-url'."
(defvar bug-reference-map)
(with-eval-after-load 'bug-reference
(define-key bug-reference-map [remap magit-visit-thing]
'bug-reference-push-button))
(keymap-set bug-reference-map "<remap> <magit-visit-thing>"
'bug-reference-push-button))
(easy-menu-define magit-mode-menu magit-mode-map
"Magit menu"
@@ -528,11 +535,13 @@ Magit is documented in info node `(magit)'."
(setq-local revert-buffer-function #'magit-refresh-buffer)
(setq-local bookmark-make-record-function #'magit--make-bookmark)
(setq-local imenu-create-index-function #'magit--imenu-create-index)
(setq-local imenu-default-goto-function #'magit--imenu-goto-function)
(setq-local isearch-filter-predicate #'magit-section--open-temporarily))
;;; Local Variables
(defvar-local magit-buffer-arguments nil)
(defvar-local magit-buffer-diff-type nil)
(defvar-local magit-buffer-diff-args nil)
(defvar-local magit-buffer-diff-files nil)
(defvar-local magit-buffer-diff-files-suspended nil)
@@ -561,21 +570,11 @@ Magit is documented in info node `(magit)'."
;; function does not reinstate this.
(put 'magit-buffer-diff-files-suspended 'permanent-local t)
(defvar-local magit-refresh-args nil
"Obsolete. Possibly the arguments used to refresh the current buffer.
Some third-party packages might still use this, but Magit does not.")
(put 'magit-refresh-args 'permanent-local t)
(make-obsolete-variable 'magit-refresh-args nil "Magit 3.0.0")
(defvar magit-buffer-lock-functions nil
"Obsolete buffer-locking support for third-party modes.
Implement the generic function `magit-buffer-value' for
your mode instead of adding an entry to this variable.")
(make-obsolete-variable 'magit-buffer-lock-functions nil "Magit 3.0.0")
(cl-defgeneric magit-buffer-value ()
(and-let* ((fn (cdr (assq major-mode magit-buffer-lock-functions))))
(funcall fn (with-no-warnings magit-refresh-args))))
"Return the value of the current buffer.
The \"value\" identifies what is being displayed in the buffer.
The buffer's major-mode should derive from `magit-section-mode'."
nil)
(defvar-local magit-previous-section nil)
(put 'magit-previous-section 'permanent-local t)
@@ -619,41 +618,6 @@ your mode instead of adding an entry to this variable.")
(magit-refresh-buffer))
buffer))
(defun magit-mode-setup (mode &rest args)
"Setup up a MODE buffer using ARGS to generate its content."
(declare (obsolete magit-setup-buffer "Magit 3.0.0"))
(with-no-warnings
(magit-mode-setup-internal mode args)))
(defun magit-mode-setup-internal (mode args &optional locked)
"Setup up a MODE buffer using ARGS to generate its content.
When optional LOCKED is non-nil, then create a buffer that is
locked to its value, which is derived from MODE and ARGS."
(declare (obsolete magit-setup-buffer "Magit 3.0.0"))
(let* ((value (and locked
(with-temp-buffer
(with-no-warnings
(setq magit-refresh-args args))
(let ((major-mode mode))
(magit-buffer-value)))))
(buffer (magit-get-mode-buffer mode value))
(section (and buffer (magit-current-section)))
(created (not buffer)))
(unless buffer
(setq buffer (magit-generate-new-buffer mode value)))
(with-current-buffer buffer
(setq magit-previous-section section)
(with-no-warnings
(setq magit-refresh-args args))
(funcall mode)
(magit-xref-setup 'magit-mode-setup-internal args)
(when created
(run-hooks 'magit-create-buffer-hook)))
(magit-display-buffer buffer)
(with-current-buffer buffer
(run-hooks 'magit-mode-setup-hook)
(magit-refresh-buffer))))
;;; Display Buffer
(defvar magit-display-buffer-noselect nil
@@ -868,23 +832,6 @@ If a frame, then only consider buffers on that frame."
((or 'selected 't) (seq-some #'w (window-list (selected-frame))))
((guard (framep frame)) (seq-some #'w (window-list frame)))))))
(defun magit-mode-get-buffer (mode &optional create frame value)
(declare (obsolete magit-get-mode-buffer "Magit 3.0.0"))
(when create
(error "`magit-mode-get-buffer's CREATE argument is obsolete"))
(let ((topdir (magit--toplevel-safe)))
(--first (with-current-buffer it
(and (eq major-mode mode)
(equal magit--default-directory topdir)
(if value
(and magit-buffer-locked-p
(equal (magit-buffer-value) value))
(not magit-buffer-locked-p))))
(if frame
(mapcar #'window-buffer
(window-list (unless (eq frame t) frame)))
(buffer-list)))))
(defun magit-generate-new-buffer (mode &optional value directory)
(let* ((default-directory (or directory (magit--toplevel-safe)))
(name (funcall magit-generate-buffer-name-function mode value))
@@ -924,8 +871,7 @@ account."
(?v . ,(or v ""))
(?V . ,(if v (concat " " v) ""))
(?t . ,n)
(?x . ,(if magit-uniquify-buffer-names "" "*"))
(?T . ,(if magit-uniquify-buffer-names n (concat n "*")))))))
(?x . ,(if magit-uniquify-buffer-names "" "*"))))))
;;; Buffer Lock
@@ -967,19 +913,18 @@ latter is displayed in its place."
;;; Bury Buffer
(defun magit-mode-bury-buffer (&optional kill-buffer)
"Bury the current buffer.
With a prefix argument, kill the buffer instead.
With two prefix arguments, also kill all Magit buffers associated
with this repository.
This is done using `magit-bury-buffer-function'."
"Bury or kill the current buffer.
Use `magit-bury-buffer-function' to bury the buffer when called
without a prefix argument or to kill it when called with a single
prefix argument.
With two prefix arguments, always kill the current and all other
Magit buffers, associated with this repository."
(interactive "P")
;; Kill all associated Magit buffers when a double prefix arg is given.
(when (>= (prefix-numeric-value kill-buffer) 16)
(let ((current (current-buffer)))
(dolist (buf (magit-mode-get-buffers))
(unless (eq buf current)
(kill-buffer buf)))))
(funcall magit-bury-buffer-function kill-buffer))
(if (>= (prefix-numeric-value kill-buffer) 16)
(mapc #'kill-buffer (magit-mode-get-buffers))
(funcall magit-bury-buffer-function kill-buffer)))
(defun magit-mode-quit-window (kill-buffer)
"Quit the selected window and bury its buffer.
@@ -1028,10 +973,10 @@ Run hooks `magit-pre-refresh-hook' and `magit-post-refresh-hook'."
(magit-refresh-buffer))
((derived-mode-p 'tabulated-list-mode)
(revert-buffer)))
(--when-let (and magit-refresh-status-buffer
(not (derived-mode-p 'magit-status-mode))
(magit-get-mode-buffer 'magit-status-mode))
(with-current-buffer it
(when-let ((buffer (and magit-refresh-status-buffer
(not (derived-mode-p 'magit-status-mode))
(magit-get-mode-buffer 'magit-status-mode))))
(with-current-buffer buffer
(magit-refresh-buffer)))
(magit-run-hook-with-benchmark 'magit-post-refresh-hook)
(when magit-refresh-verbose
@@ -1091,7 +1036,7 @@ Run hooks `magit-pre-refresh-hook' and `magit-post-refresh-hook'."
(let ((inhibit-read-only t))
(erase-buffer)
(save-excursion
(apply refresh (with-no-warnings magit-refresh-args))))
(funcall refresh)))
(pcase-dolist (`(,window . ,args) windows)
(if (eq buffer (window-buffer window))
(with-selected-window window
@@ -1140,8 +1085,9 @@ If you are not satisfied with Magit's performance, then you
should obviously not add this function to that hook."
(when (and (not magit--disable-save-buffers)
(magit-inside-worktree-p t))
(--when-let (ignore-errors (magit-get-mode-buffer 'magit-status-mode))
(add-to-list 'magit-after-save-refresh-buffers it)
(when-let ((buffer (ignore-errors
(magit-get-mode-buffer 'magit-status-mode))))
(add-to-list 'magit-after-save-refresh-buffers buffer)
(add-hook 'post-command-hook #'magit-after-save-refresh-buffers))))
(defun magit-maybe-save-repository-buffers ()
@@ -1185,30 +1131,54 @@ argument (the prefix) non-nil means save all with no questions."
(with-current-buffer buffer
(setq magit-inhibit-refresh-save t)))
"to skip the current buffer and remember choice")
,@save-some-buffers-action-alist)))
(save-some-buffers
arg (lambda ()
(and buffer-file-name
;; If the current file is modified and resides inside
;; a repository, and a let-binding is in effect, which
;; places us in another repository, then the below
;; let-binding is needed to prevent that file from
;; being saved.
(let ((default-directory
(file-name-directory buffer-file-name)))
(and
;; - 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)))))))))
,@save-some-buffers-action-alist))
(topdirs nil)
(unwiped nil)
(magit--wip-inhibit-autosave t))
(unwind-protect
(save-some-buffers
arg
(lambda ()
;; If the current file is modified and resides inside
;; a repository, and a let-binding is in effect, which
;; places us in another repository, then this binding
;; is needed to prevent that file from being saved.
(and-let* ((default-directory
(and buffer-file-name
(file-name-directory buffer-file-name))))
(and
;; Check whether the repository still exists.
(file-exists-p default-directory)
;; 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 (or (cdr (assoc default-directory topdirs))
(let ((top (magit-rev-parse-safe "--show-toplevel")))
(push (cons default-directory top) topdirs)
top))
topdir)
;; Check whether the file is actually writable.
(file-writable-p buffer-file-name)
(prog1 t
;; Schedule for wip commit, if appropriate.
(when magit-wip-after-save-local-mode
(push (expand-file-name buffer-file-name) unwiped)))))))
(when unwiped
(let ((default-directory topdir))
(magit-wip-commit-worktree
(magit-wip-get-ref)
unwiped
(if (cdr unwiped)
(format "autosave %s files after save" (length unwiped))
(format "autosave %s after save"
(file-relative-name (car unwiped)))))))))))
;;; Restore Window Configuration
@@ -1239,7 +1209,9 @@ Later, when the buffer is buried, it may be restored by
(set-window-configuration winconf)
(when (buffer-live-p buffer)
(with-current-buffer buffer
(setq magit-previous-window-configuration nil))))))
(setq magit-previous-window-configuration nil)))
(set-buffer (with-selected-window (selected-window)
(current-buffer))))))
;;; Buffer History
@@ -1295,9 +1267,8 @@ Later, when the buffer is buried, it may be restored by
(when help-xref-stack-item
(push (cons (point) help-xref-stack-item) help-xref-stack)
(setq help-xref-forward-stack nil))
(when (called-interactively-p 'interactive)
(--when-let (nthcdr 10 help-xref-stack)
(setcdr it nil)))
(when-let ((tail (nthcdr 30 help-xref-stack)))
(setcdr tail nil))
(setq help-xref-stack-item
(list 'magit-xref-restore fn default-directory args))))
@@ -1371,7 +1342,7 @@ Unless specified, REPOSITORY is the current buffer's repository."
(when-let ((cache (assoc (or repository
(magit-repository-local-repository))
magit-repository-local-cache)))
(setf cache (compat-assoc-delete-all key cache))))
(setf cache (compat-call assoc-delete-all key cache))))
(defmacro magit--with-repository-local-cache (key &rest body)
(declare (indent 1) (debug (form body)))
@@ -1482,6 +1453,17 @@ mentioned caches completely."
(substring heading 0 (match-beginning 0)))
(t heading)))))
(defun magit--imenu-goto-function (_name position &rest _rest)
"Go to the section at POSITION.
Make sure it is visible, by showing its ancestors where
necessary. For use as `imenu-default-goto-function' in
`magit-mode' buffers."
(goto-char position)
(let ((section (magit-current-section)))
(while (setq section (oref section parent))
(when (oref section hidden)
(magit-section-show section)))))
;;; Bookmark support
(declare-function bookmark-get-filename "bookmark" (bookmark-name-or-record))

View File

@@ -1,6 +1,6 @@
;;; magit-notes.el --- Notes support -*- lexical-binding:t -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
@@ -61,9 +61,9 @@
("a" "Abort merge" magit-notes-merge-abort)])
(defun magit-notes-merging-p ()
(let ((dir (magit-git-dir "NOTES_MERGE_WORKTREE")))
(let ((dir (expand-file-name "NOTES_MERGE_WORKTREE" (magit-gitdir))))
(and (file-directory-p dir)
(directory-files dir nil "^[^.]"))))
(directory-files dir nil "\\`[^.]"))))
(transient-define-infix magit-core.notesRef ()
:class 'magit--git-variable

View File

@@ -1,111 +0,0 @@
;;; magit-obsolete.el --- Obsolete definitions -*- lexical-binding:t -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; 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 of the License, 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 <https://www.gnu.org/licenses/>.
;;; Commentary:
;; This library defines aliases for obsolete variables and functions.
;;; Code:
(require 'magit)
;;; Obsolete since v3.0.0
(define-obsolete-function-alias 'magit-diff-visit-file-worktree
#'magit-diff-visit-worktree-file "Magit 3.0.0")
(define-obsolete-function-alias 'magit-status-internal
#'magit-status-setup-buffer "Magit 3.0.0")
(define-obsolete-variable-alias 'magit-mode-setup-hook
'magit-setup-buffer-hook "Magit 3.0.0")
(define-obsolete-variable-alias 'magit-branch-popup-show-variables
'magit-branch-direct-configure "Magit 3.0.0")
(define-obsolete-function-alias 'magit-dispatch-popup
#'magit-dispatch "Magit 3.0.0")
(define-obsolete-function-alias 'magit-repolist-column-dirty
#'magit-repolist-column-flag "Magit 3.0.0")
(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.
It now uses Transient.
See https://emacsair.me/2019/02/14/transient-0.1.
However your configuration and/or some third-party package that
you use still depends on the `magit-popup' package. But because
`magit' no longer depends on that, `package' has removed it from
your system.
If some package that you use still depends on `magit-popup' but
does not declare it as a dependency, then please contact its
maintainer about that and install `magit-popup' explicitly.
If you yourself use functions that are defined in `magit-popup'
in your configuration, then the next step depends on what you use
that for.
* If you use `magit-popup' to define your own popups but do not
modify any of Magit's old popups, then you have to install
`magit-popup' explicitly. (You can also migrate to Transient,
but there is no need to rush that.)
* If you add additional arguments and/or actions to Magit's popups,
then you have to port that to modify the new \"transients\" instead.
See https://github.com/magit/magit/wiki/\
Converting-popup-modifications-to-transient-modifications
To find installed packages that still use `magit-popup' you can
use e.g. \"M-x rgrep RET magit-popup RET RET ~/.emacs.d/ RET\"."))
(cl-eval-when (eval load)
(unless (require (quote magit-popup) nil t)
(defun magit-define-popup-switch (&rest _)
(magit--magit-popup-warning))
(defun magit-define-popup-option (&rest _)
(magit--magit-popup-warning))
(defun magit-define-popup-variable (&rest _)
(magit--magit-popup-warning))
(defun magit-define-popup-action (&rest _)
(magit--magit-popup-warning))
(defun magit-define-popup-sequence-action (&rest _)
(magit--magit-popup-warning))
(defun magit-define-popup-key (&rest _)
(magit--magit-popup-warning))
(defun magit-define-popup-keys-deferred (&rest _)
(magit--magit-popup-warning))
(defun magit-change-popup-key (&rest _)
(magit--magit-popup-warning))
(defun magit-remove-popup-key (&rest _)
(magit--magit-popup-warning))))
;;; _
(provide 'magit-obsolete)
;;; magit-obsolete.el ends here

View File

@@ -1,6 +1,6 @@
;;; magit-patch.el --- Creating and applying patches -*- lexical-binding:t -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
@@ -102,12 +102,12 @@ which creates patches for all commits that are reachable from
(cons (if-let ((revs (magit-region-values 'commit t)))
(concat (car (last revs)) "^.." (car revs))
(let ((range (magit-read-range-or-commit
"Format range or commit")))
"Create patches for range or commit")))
(if (string-search ".." range)
range
(format "%s~..%s" range range))))
(let ((args (transient-args 'magit-patch-create)))
(list (-filter #'stringp args)
(list (seq-filter #'stringp args)
(cdr (assoc "--" args)))))))
(if (not range)
(transient-setup 'magit-patch-create)
@@ -294,7 +294,9 @@ same differences as those shown in the buffer are always used."
(setq args nil)))
((eq (car-safe magit-patch-save-arguments) 'exclude)
(unless arg
(setq args (-difference args (cdr magit-patch-save-arguments)))))
(setq args
(cl-set-difference args (cdr magit-patch-save-arguments)
:test #'equal))))
((not arg)
(setq args magit-patch-save-arguments)))
(with-temp-file file

View File

@@ -1,12 +1,13 @@
(define-package "magit" "20221208.1848" "A Git porcelain inside Emacs."
(define-package "magit" "20231103.1516" "A Git porcelain inside Emacs."
'((emacs "25.1")
(compat "28.1.1.2")
(dash "20210826")
(git-commit "20221127")
(magit-section "20221127")
(transient "20220325")
(with-editor "20220318"))
:commit "99d9b3008adf72a0c2cdb7df70b5ae03ea9271c8" :authors
(compat "29.1.3.4")
(dash "20221013")
(git-commit "20230101")
(magit-section "20230101")
(seq "2.24")
(transient "20230201")
(with-editor "20230118"))
:commit "2b02bfb0495bf738e006d82f3a233e8f511b90b8" :authors
'(("Marius Vollmer" . "marius.vollmer@gmail.com")
("Jonas Bernoulli" . "jonas@bernoul.li"))
:maintainer

View File

@@ -1,6 +1,6 @@
;;; magit-process.el --- Process functionality -*- lexical-binding:t -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
@@ -37,6 +37,8 @@
(require 'ansi-color)
(require 'with-editor)
(defvar y-or-n-p-map)
;;; Options
(defcustom magit-process-connection-type (not (eq system-type 'cygwin))
@@ -150,13 +152,13 @@ itself from the hook, to avoid further futile attempts."
(const :tag "Don't start a cache daemon" nil)))
(defcustom magit-process-yes-or-no-prompt-regexp
(concat " [\[(]"
(concat " [([]"
"\\([Yy]\\(?:es\\)?\\)"
"[/|]"
"\\([Nn]o?\\)"
;; OpenSSH v8 prints this. See #3969.
"\\(?:/\\[fingerprint\\]\\)?"
"[\])] ?[?:]? ?$")
"[])] ?[?:]? ?$")
"Regexp matching Yes-or-No prompts of Git and its subprocesses."
:package-version '(magit . "2.1.0")
:group 'magit-process
@@ -165,7 +167,8 @@ itself from the hook, to avoid further futile attempts."
(defcustom magit-process-password-prompt-regexps
'("^\\(Enter \\)?[Pp]assphrase\\( for \\(RSA \\)?key '.*'\\)?: ?$"
;; Match-group 99 is used to identify the "user@host" part.
"^\\(Enter \\)?[Pp]assword\\( for '?\\(https?://\\)?\\(?99:[^']*\\)'?\\)?: ?$"
"^\\(Enter \\|([^) ]+) \\)?\
[Pp]assword\\( for '?\\(https?://\\)?\\(?99:[^']*\\)'?\\)?: ?$"
"Please enter the passphrase for the ssh key"
"Please enter the passphrase to unlock the OpenPGP secret key"
"^.*'s password: ?$"
@@ -222,7 +225,7 @@ hook allows users to deal with such questions explicitly.
Each function is called with the process and the output string
as arguments until one of the functions returns non-nil. The
function is responsible for asking the user the appropriate
question using e.g. `read-char-choice' and then forwarding the
question using, e.g., `read-char-choice' and then forwarding the
answer to the process using `process-send-string'.
While functions such as `magit-process-yes-or-no-prompt' may not
@@ -245,6 +248,15 @@ implement such functions."
:group 'magit-process
:type 'boolean)
(defcustom magit-process-timestamp-format nil
"Format of timestamp for each process in the process buffer.
If non-nil, pass this to `format-time-string' when creating a
process section in the process buffer, and insert the returned
string in the heading of its section."
:package-version '(magit . "4.0.0")
:group 'magit-process
:type '(choice (const :tag "none" nil) string))
(defface magit-process-ok
'((t :inherit magit-section-heading :foreground "green"))
"Face for zero exit-status."
@@ -269,11 +281,10 @@ Used when `magit-process-display-mode-line-error' is non-nil."
;;; Process Mode
(defvar magit-process-mode-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map magit-mode-map)
map)
"Keymap for `magit-process-mode'.")
(defvar-keymap magit-process-mode-map
:doc "Keymap for `magit-process-mode'."
:parent magit-mode-map
"<remap> <magit-delete-thing>" #'magit-process-kill)
(define-derived-mode magit-process-mode magit-mode "Magit Process"
"Mode for looking at Git process output."
@@ -427,8 +438,8 @@ conversion."
(cdr (assoc magit-git-executable magit-git-w32-path-hack)))
(and local magit-need-cygwin-noglob
(mapcar (lambda (var)
(concat var "=" (--if-let (getenv var)
(concat it " noglob")
(concat var "=" (if-let ((val (getenv var)))
(concat val " noglob")
"noglob")))
'("CYGWIN" "MSYS")))
process-environment)))
@@ -596,7 +607,12 @@ Magit status buffer."
(when input
(with-current-buffer input
(process-send-region process (point-min) (point-max))
(process-send-eof process)))
;; `process-send-eof' appears to be broken over
;; Tramp from Windows. See #3624 and bug#43226.
(if (and (eq system-type 'windows-nt)
(file-remote-p (process-get process 'default-dir) nil t))
(process-send-string process "")
(process-send-eof process))))
(setq magit-this-process process)
(oset section value process)
(magit-process-display-buffer process)
@@ -641,6 +657,8 @@ Magit status buffer."
(format "%3s " (propertize (number-to-string errcode)
'font-lock-face 'magit-process-ng))
"run "))
(when magit-process-timestamp-format
(insert (format-time-string magit-process-timestamp-format) " "))
(unless (equal (expand-file-name pwd)
(expand-file-name default-directory))
(insert (file-relative-name pwd default-directory) ?\s))
@@ -657,19 +675,17 @@ Magit status buffer."
(defun magit-process--format-arguments (program args)
(cond
((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 (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) " "))
" "
(propertize (mapconcat #'shell-quote-argument (cadr args) " ")
'font-lock-face 'magit-section-heading)))
(let ((global (length magit-git-global-arguments)))
(concat
(propertize (file-name-nondirectory program)
'font-lock-face 'magit-section-heading)
" "
(propertize (magit--ellipsis)
'font-lock-face 'magit-section-heading
'help-echo (mapconcat #'identity (seq-take args global) " "))
" "
(propertize (mapconcat #'shell-quote-argument (seq-drop args global) " ")
'font-lock-face 'magit-section-heading))))
((and args (equal program shell-file-name))
(propertize (cadr args)
'font-lock-face 'magit-section-heading))
@@ -728,16 +744,16 @@ Magit status buffer."
(status-buf (with-current-buffer process-buf
(magit-get-mode-buffer 'magit-status-mode))))
(with-current-buffer status-buf
(--when-let
(magit-get-section
`((commit . ,(magit-rev-parse "HEAD"))
(,(pcase (car (cadr (-split-at
(1+ (length magit-git-global-arguments))
(process-command process))))
((or "rebase" "am") 'rebase-sequence)
((or "cherry-pick" "revert") 'sequence)))
(status)))
(goto-char (oref it start))
(when-let ((section
(magit-get-section
`((commit . ,(magit-rev-parse "HEAD"))
(,(pcase (car (seq-drop
(process-command process)
(1+ (length magit-git-global-arguments))))
((or "rebase" "am") 'rebase-sequence)
((or "cherry-pick" "revert") 'sequence)))
(status)))))
(goto-char (oref section start))
(magit-section-update-highlight))))))
(defun magit-process-filter (proc string)
@@ -750,6 +766,7 @@ Magit status buffer."
(when-let ((ret-pos (cl-position ?\r string :from-end t)))
(cl-callf substring string (1+ ret-pos))
(delete-region (line-beginning-position) (point)))
(setq string (magit-process-remove-bogus-errors string))
(insert (propertize string 'magit-section
(process-get proc 'section)))
(set-marker (process-mark proc) (point))
@@ -760,35 +777,55 @@ Magit status buffer."
(run-hook-with-args-until-success 'magit-process-prompt-functions
proc string))))
(defmacro magit-process-kill-on-abort (proc &rest body)
(declare (indent 1) (debug (form body)))
(let ((map (cl-gensym)))
`(let ((,map (make-sparse-keymap)))
(set-keymap-parent ,map minibuffer-local-map)
;; 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))
(abort-recursive-edit)))
(let ((minibuffer-local-map ,map))
,@body))))
(defun magit-process-make-keymap (process parent)
"Remap `abort-minibuffers' to a command that also kills PROCESS.
PARENT is used as the parent of the returned keymap."
(let ((cmd (lambda ()
(interactive)
(ignore-errors (kill-process process))
(if (fboundp 'abort-minibuffers)
(abort-minibuffers)
(abort-recursive-edit)))))
(define-keymap :parent parent
"C-g" cmd
"<remap> <abort-minibuffers>" cmd
"<remap> <abort-recursive-edit>" cmd)))
(defmacro magit-process-kill-on-abort (process &rest body)
(declare (indent 1)
(debug (form body))
(obsolete magit-process-make-keymap "Magit 4.0.0"))
`(let ((minibuffer-local-map
(magit-process-make-keymap ,process minibuffer-local-map)))
,@body))
(defun magit-process-remove-bogus-errors (str)
(save-match-data
(when (string-match "^\\(\\*ERROR\\*: \\)Canceled by user" str)
(setq str (replace-match "" nil nil str 1)))
(when (string-match "^error: There was a problem with the editor.*\n" str)
(setq str (replace-match "" nil nil str)))
(when (string-match
"^Please supply the message using either -m or -F option\\.\n" str)
(setq str (replace-match "" nil nil str))))
str)
(defun magit-process-yes-or-no-prompt (process string)
"Forward Yes-or-No prompts to the user."
(when-let ((beg (string-match magit-process-yes-or-no-prompt-regexp string)))
(let ((max-mini-window-height 30))
(process-send-string
process
(downcase
(concat
(match-string
(if (save-match-data
(magit-process-kill-on-abort process
(yes-or-no-p (substring string 0 beg)))) 1 2)
string)
"\n"))))))
(process-send-string
process
(if (save-match-data
(let ((max-mini-window-height 30)
(minibuffer-local-map
(magit-process-make-keymap process minibuffer-local-map))
;; In case yes-or-no-p is fset to that, but does
;; not cover use-dialog-box-p and y-or-n-p-read-key.
(y-or-n-p-map
(magit-process-make-keymap process y-or-n-p-map)))
(yes-or-no-p (substring string 0 beg))))
(concat (downcase (match-string 1 string)) "\n")
(concat (downcase (match-string 2 string)) "\n")))))
(defun magit-process-password-auth-source (key)
"Use `auth-source-search' to get a password.
@@ -869,20 +906,24 @@ from the user."
(when-let ((prompt (magit-process-match-prompt
magit-process-password-prompt-regexps string)))
(process-send-string
process (magit-process-kill-on-abort process
(concat (or (and-let* ((key (match-string 99 string)))
(run-hook-with-args-until-success
'magit-process-find-password-functions key))
(read-passwd prompt))
"\n")))))
process
(concat (or (and-let* ((key (match-string 99 string)))
(run-hook-with-args-until-success
'magit-process-find-password-functions key))
(let ((read-passwd-map
(magit-process-make-keymap process read-passwd-map)))
(read-passwd prompt)))
"\n"))))
(defun magit-process-username-prompt (process string)
"Forward username prompts to the user."
(--when-let (magit-process-match-prompt
magit-process-username-prompt-regexps string)
(when-let ((prompt (magit-process-match-prompt
magit-process-username-prompt-regexps string)))
(process-send-string
process (magit-process-kill-on-abort process
(concat (read-string it nil nil (user-login-name)) "\n")))))
process
(let ((minibuffer-local-map
(magit-process-make-keymap process minibuffer-local-map)))
(concat (read-string prompt nil nil (user-login-name)) "\n")))))
(defun magit-process-match-prompt (prompts string)
"Match STRING against PROMPTS and set match data.
@@ -931,7 +972,7 @@ as argument."
(magit-git-executable)
"credential-cache--daemon"
magit-credential-cache-daemon-socket)
;; Some Git implementations (e.g. Windows) won't have
;; Some Git implementations (e.g., Windows) won't have
;; this program; if we fail the first time, stop trying.
((debug error)
(remove-hook 'magit-credential-hook
@@ -962,12 +1003,9 @@ as argument."
(advice-add 'tramp-sh-handle-process-file :around
#'tramp-sh-handle-process-file--magit-tramp-process-environment)
(defvar magit-mode-line-process-map
(let ((map (make-sparse-keymap)))
(define-key map (kbd "<mode-line> <mouse-1>")
'magit-process-buffer)
map)
"Keymap for `mode-line-process'.")
(defvar-keymap magit-mode-line-process-map
:doc "Keymap for `mode-line-process'."
"<mode-line> <mouse-1>" ''magit-process-buffer)
(defun magit-process-set-mode-line (program args)
"Display the git command (sans arguments) in the mode line."
@@ -1142,11 +1180,10 @@ Limited by `magit-process-error-tooltip-max-lines'."
(goto-char (1+ (line-end-position)))
(delete-char -1)
(oset section content nil))
(let ((buf (magit-process-buffer t)))
(when (and (= arg 0)
(not (--any-p (eq (window-buffer it) buf)
(window-list))))
(magit-section-hide section)))))))
(when (and (= arg 0)
(not (--any-p (eq (window-buffer it) process-buf)
(window-list))))
(magit-section-hide section))))))
(if (= arg 0)
;; Unset the `mode-line-process' value upon success.
(magit-process-unset-mode-line default-dir)

View File

@@ -1,6 +1,6 @@
;;; magit-pull.el --- Update local objects and refs -*- lexical-binding:t -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>

View File

@@ -1,6 +1,6 @@
;;; magit-push.el --- Update remote objects and refs -*- lexical-binding:t -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
@@ -130,9 +130,10 @@ the upstream."
(not (or (magit-get-upstream-branch branch)
(magit--unnamed-upstream-p remote merge)
(magit--valid-upstream-p remote merge))))
(let* ((branches (-union (--map (concat it "/" branch)
(magit-list-remotes))
(magit-list-remote-branch-names)))
(let* ((branches (cl-union (--map (concat it "/" branch)
(magit-list-remotes))
(magit-list-remote-branch-names)
:test #'equal))
(upstream (magit-completing-read
(format "Set upstream of %s and push there" branch)
branches nil nil nil 'magit-revision-history
@@ -181,9 +182,9 @@ the upstream."
(defun magit-push-current (target args)
"Push the current branch to a branch read in the minibuffer."
(interactive
(--if-let (magit-get-current-branch)
(list (magit-read-remote-branch (format "Push %s to" it)
nil nil it 'confirm)
(if-let ((current (magit-get-current-branch)))
(list (magit-read-remote-branch (format "Push %s to" current)
nil nil current 'confirm)
(magit-push-arguments))
(user-error "No branch is checked out")))
(magit-git-push (magit-get-current-branch) target args))
@@ -218,7 +219,7 @@ only available for the part before the colon, or when no colon
is used."
(interactive
(list (magit-read-remote "Push to remote")
(magit-completing-read-multiple*
(magit-completing-read-multiple
"Push refspec,s: "
(cons "HEAD" (magit-list-local-branch-names))
nil nil nil 'magit-push-refspecs-history)

View File

@@ -1,6 +1,6 @@
;;; magit-reflog.el --- Inspect ref history -*- lexical-binding:t -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
@@ -130,13 +130,11 @@ If `HEAD' is detached, then show the reflog for that instead."
;;; Mode
(defvar magit-reflog-mode-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map magit-log-mode-map)
(define-key map (kbd "C-c C-n") #'undefined)
(define-key map (kbd "L") #'magit-margin-settings)
map)
"Keymap for `magit-reflog-mode'.")
(defvar-keymap magit-reflog-mode-map
:doc "Keymap for `magit-reflog-mode'."
:parent magit-log-mode-map
"C-c C-n" #'undefined
"L" #'magit-margin-settings)
(define-derived-mode magit-reflog-mode magit-mode "Magit Reflog"
"Mode for looking at Git reflog.

View File

@@ -1,6 +1,6 @@
;;; magit-refs.el --- Listing references -*- lexical-binding:t -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
@@ -64,9 +64,9 @@ To change the value in an existing buffer use the command
:package-version '(magit . "2.1.0")
:group 'magit-refs
:safe (lambda (val) (memq val '(all branch nil)))
:type '(choice (const all :tag "For branches and tags")
(const branch :tag "For branches only")
(const nil :tag "Never")))
:type '(choice (const :tag "For branches and tags" all)
(const :tag "For branches only" branch)
(const :tag "Never" nil)))
(put 'magit-refs-show-commit-count 'safe-local-variable 'symbolp)
(put 'magit-refs-show-commit-count 'permanent-local t)
@@ -271,13 +271,11 @@ the outcome.
;;; Mode
(defvar magit-refs-mode-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map magit-mode-map)
(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'.")
(defvar-keymap magit-refs-mode-map
:doc "Keymap for `magit-refs-mode'."
:parent magit-mode-map
"C-y" #'magit-refs-set-show-commit-count
"L" #'magit-margin-settings)
(define-derived-mode magit-refs-mode magit-mode "Magit Refs"
"Mode which lists and compares references.
@@ -356,11 +354,12 @@ Type \\[magit-reset] to reset `HEAD' to the commit at point.
((eq major-mode 'magit-refs-mode)
(setq args magit-buffer-arguments))
((and (memq use-buffer-args '(always selected))
(when-let* ((buffer (magit-get-mode-buffer ;debbugs#31840
(and-let* ((buffer (magit-get-mode-buffer
'magit-refs-mode nil
(eq use-buffer-args 'selected))))
(setq args (buffer-local-value 'magit-buffer-arguments buffer))
t)))
(progn ; work around debbugs#31840
(setq args (buffer-local-value 'magit-buffer-arguments buffer))
t))))
(t
(setq args (alist-get 'magit-show-refs transient-values))))
args))
@@ -473,27 +472,28 @@ Branch %s already exists.
;;; Sections
(defvar magit-remote-section-map
(let ((map (make-sparse-keymap)))
(magit-menu-set map [magit-delete-thing] #'magit-remote-remove "Remove %m")
(magit-menu-set map [magit-file-rename] #'magit-remote-rename "Rename %s")
map)
"Keymap for `remote' sections.")
(defvar-keymap magit-remote-section-map
:doc "Keymap for `remote' sections."
"<remap> <magit-file-rename>" #'magit-remote-rename
"<remap> <magit-delete-thing>" #'magit-remote-remove
"<2>" (magit-menu-item "Rename %s" #'magit-remote-rename)
"<1>" (magit-menu-item "Remove %m" #'magit-remote-remove))
(defvar magit-branch-section-map
(let ((map (make-sparse-keymap)))
(magit-menu-set map [magit-visit-thing] #'magit-visit-ref "Visit commit")
(magit-menu-set map [magit-delete-thing] #'magit-branch-delete "Delete %m")
(magit-menu-set map [magit-file-rename] #'magit-branch-rename "Rename %s")
map)
"Keymap for `branch' sections.")
(defvar-keymap magit-branch-section-map
:doc "Keymap for `branch' sections."
"<remap> <magit-file-rename>" #'magit-branch-rename
"<remap> <magit-delete-thing>" #'magit-branch-delete
"<remap> <magit-visit-thing>" #'magit-visit-ref
"<3>" (magit-menu-item "Rename %s" #'magit-branch-rename)
"<2>" (magit-menu-item "Delete %m" #'magit-branch-delete)
"<1>" (magit-menu-item "Visit commit" #'magit-visit-ref))
(defvar magit-tag-section-map
(let ((map (make-sparse-keymap)))
(magit-menu-set map [magit-visit-thing] #'magit-visit-ref "Visit %s")
(magit-menu-set map [magit-delete-thing] #'magit-tag-delete "Delete %m")
map)
"Keymap for `tag' sections.")
(defvar-keymap magit-tag-section-map
:doc "Keymap for `tag' sections."
"<remap> <magit-delete-thing>" #'magit-tag-delete
"<remap> <magit-visit-thing>" #'magit-visit-ref
"<2>" (magit-menu-item "Delete %m" #'magit-tag-delete)
"<1>" (magit-menu-item "Visit %s" #'magit-visit-ref))
(defun magit--painted-branch-as-menu-section (section)
(and-let* ((branch (and (magit-section-match 'commit)
@@ -571,9 +571,16 @@ line is inserted at all."
(concat "refs/remotes/" remote)
magit-buffer-arguments))
(pcase-let ((`(,head-branch ,branch ,ref ,msg)
(-replace "" nil (split-string line "\0"))))
(cl-substitute nil ""
(split-string line "\0")
:test #'equal)))
(if head-branch
(progn (cl-assert (equal branch (concat remote "/HEAD")))
;; Note: Use `ref' instead of `branch' for the check
;; below because 'refname:short' shortens the remote
;; HEAD to '<remote>' instead of '<remote>/HEAD' as of
;; Git v2.40.0.
(progn (cl-assert
(equal ref (concat "refs/remotes/" remote "/HEAD")))
(setq head head-branch))
(when (magit-refs--insert-refname-p branch)
(magit-insert-section (branch branch t)
@@ -616,17 +623,17 @@ line is inserted at all."
(magit-make-margin-overlay nil t)))
(defun magit-refs--format-local-branches ()
(let ((lines (-keep #'magit-refs--format-local-branch
(magit-git-lines
"for-each-ref"
(concat "--format=\
(let ((lines (seq-keep #'magit-refs--format-local-branch
(magit-git-lines
"for-each-ref"
(concat "--format=\
%(HEAD)%00%(refname:short)%00%(refname)%00\
%(upstream:short)%00%(upstream)%00%(upstream:track)%00"
(if magit-refs-show-push-remote "\
(if magit-refs-show-push-remote "\
%(push:remotename)%00%(push)%00%(push:track)%00%(subject)"
"%00%00%00%(subject)"))
"refs/heads"
magit-buffer-arguments))))
"refs/heads"
magit-buffer-arguments))))
(unless (magit-get-current-branch)
(push (magit-refs--format-local-branch
(concat "*\0\0\0\0\0\0\0\0" (magit-rev-format "%s")))
@@ -653,7 +660,7 @@ line is inserted at all."
(defun magit-refs--format-local-branch (line)
(pcase-let ((`(,head ,branch ,ref ,upstream ,u:ref ,u:track
,push ,p:ref ,p:track ,msg)
(-replace "" nil (split-string line "\0"))))
(cl-substitute nil "" (split-string line "\0") :test #'equal)))
(when (or (not branch)
(magit-refs--insert-refname-p branch))
(let* ((headp (equal head "*"))
@@ -743,12 +750,12 @@ line is inserted at all."
branch (if head-face (list face head-face) face))))
(defun magit-refs--insert-refname-p (refname)
(--if-let (-first (pcase-lambda (`(,key . ,_))
(if (functionp key)
(funcall key refname)
(string-match-p key refname)))
magit-refs-filter-alist)
(cdr it)
(if-let ((entry (seq-find (pcase-lambda (`(,key . ,_))
(if (functionp key)
(funcall key refname)
(string-match-p key refname)))
magit-refs-filter-alist)))
(cdr entry)
t))
(defun magit-refs--insert-cherry-commits (ref)

View File

@@ -1,6 +1,6 @@
;;; magit-remote.el --- Transfer Git commits -*- lexical-binding:t -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
@@ -85,6 +85,7 @@ has to be used to view and change remote related variables."
[("C" "Configure..." magit-remote-configure)
("p" "Prune stale branches" magit-remote-prune)
("P" "Prune stale refspecs" magit-remote-prune-refspecs)
("b" magit-update-default-branch)
(7 "z" "Unshallow remote" magit-remote-unshallow)]]
(interactive (list (magit-get-current-remote)))
(transient-setup 'magit-remote nil nil :scope remote))
@@ -142,7 +143,7 @@ has to be used to view and change remote related variables."
(when (equal (magit-get "remote.pushDefault") remote)
(magit-set new-name "remote.pushDefault"))
(dolist (var (magit-git-lines "config" "--name-only"
"--get-regexp" "^branch\.[^.]*\.pushRemote"
"--get-regexp" "^branch\\.[^.]*\\.pushRemote"
(format "^%s$" remote)))
(magit-call-git "config" (and (not new-name) "--unset") var new-name))))
@@ -206,10 +207,10 @@ the now stale refspecs. Other stale branches are not removed."
(pcase-let ((`(,refspec . ,refs) (car stale)))
(magit-confirm 'prune-stale-refspecs
(format "Prune stale refspec %s and branch %%s" refspec)
(format "Prune stale refspec %s and %%i branches" refspec)
(format "Prune stale refspec %s and %%d branches" refspec)
nil refs))
(magit-confirm 'prune-stale-refspecs nil
(format "Prune %%i stale refspecs and %i branches"
(format "Prune %%d stale refspecs and %d branches"
(length (cl-mapcan (lambda (s) (copy-sequence (cdr s)))
stale)))
nil
@@ -223,7 +224,7 @@ the now stale refspecs. Other stale branches are not removed."
(regexp-quote refspec))
(magit--log-action
(lambda (refs)
(format "Deleting %i branches" (length refs)))
(format "Deleting %d branches" (length refs)))
(lambda (ref)
(format "Deleting branch %s (was %s)" ref
(magit-rev-parse "--short" ref)))
@@ -255,6 +256,38 @@ 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 (autoload 'magit-update-default-branch "magit-remote" nil t)
(transient-define-suffix magit-update-default-branch ()
"Update name of the default branch after upstream changed it."
:description "Update default branch"
:inapt-if-not #'magit-get-some-remote
(interactive)
(pcase-let ((`(,_remote ,oldname) (magit--get-default-branch))
(`( ,remote ,newname) (magit--get-default-branch t)))
(cond
((equal oldname newname)
(setq oldname
(read-string
(format
"Name of default branch is still `%s', %s\n%s `%s': " oldname
"but the upstreams of some local branches might need updating."
"Name of upstream branches to replace with" newname)))
(magit--set-default-branch newname oldname)
(magit-refresh))
(t
(unless oldname
(setq oldname
(magit-read-other-local-branch
(format "Name of old default branch to be renamed to `%s'"
newname)
newname "master")))
(cond
((y-or-n-p (format "Default branch changed from `%s' to `%s' on %s.%s"
oldname newname remote " Do the same locally? "))
(magit--set-default-branch newname oldname)
(magit-refresh))
((user-error "Abort")))))))
;;;###autoload
(defun magit-remote-unshallow (remote)
"Convert a shallow remote into a full one.

View File

@@ -1,6 +1,6 @@
;;; magit-repos.el --- Listing repositories -*- lexical-binding:t -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
@@ -93,12 +93,12 @@ The `:sort' function has a weird interface described in the
docstring of `tabulated-list--get-sort'. Alternatively `<' and
`magit-repolist-version<' can be used as those functions are
automatically replaced with functions that satisfy the interface.
Set `:sort' to nil to inhibit sorting; if unspecifed, then the
Set `:sort' to nil to inhibit sorting; if unspecified, then the
column is sortable using the default sorter.
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,
which case you should use an appropriate HEADER, set WIDTH to 1,
and set `:pad-right' to 0. \"+\" is substituted for numbers higher
than 9."
:package-version '(magit . "2.12.0")
@@ -149,7 +149,7 @@ non-nil, means to invert the resulting sort."
(defun magit-list-repositories ()
"Display a list of repositories.
Use the options `magit-repository-directories' to control which
Use the option `magit-repository-directories' to control which
repositories are displayed."
(interactive)
(magit-repolist-setup (default-value 'magit-repolist-columns)))
@@ -159,8 +159,8 @@ repositories are displayed."
(defun magit-repolist-status (&optional _button)
"Show the status for the repository at point."
(interactive)
(--if-let (tabulated-list-get-id)
(magit-status-setup-buffer (expand-file-name it))
(if-let ((id (tabulated-list-get-id)))
(magit-status-setup-buffer (expand-file-name id))
(user-error "There is no repository at point")))
(defun magit-repolist-mark ()
@@ -254,21 +254,19 @@ If it contains \"%s\" then the directory is substituted for that."
;;;; Mode
(defvar magit-repolist-mode-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map tabulated-list-mode-map)
(define-key map (kbd "C-m") #'magit-repolist-status)
(define-key map (kbd "m") #'magit-repolist-mark)
(define-key map (kbd "u") #'magit-repolist-unmark)
(define-key map (kbd "f") #'magit-repolist-fetch)
(define-key map (kbd "5") #'magit-repolist-find-file-other-frame)
map)
"Local keymap for Magit-Repolist mode buffers.")
(defvar-keymap magit-repolist-mode-map
:doc "Local keymap for Magit-Repolist mode buffers."
:parent tabulated-list-mode-map
"C-m" #'magit-repolist-status
"m" #'magit-repolist-mark
"u" #'magit-repolist-unmark
"f" #'magit-repolist-fetch
"5" #'magit-repolist-find-file-other-frame)
(define-derived-mode magit-repolist-mode tabulated-list-mode "Repos"
"Major mode for browsing a list of Git repositories."
(setq-local x-stretch-cursor nil)
(setq tabulated-list-padding 0)
(setq-local x-stretch-cursor nil)
(setq tabulated-list-padding 0)
(add-hook 'tabulated-list-revert-hook #'magit-repolist-refresh nil t)
(setq imenu-prev-index-position-function
#'magit-repolist--imenu-prev-index-position)
@@ -293,8 +291,8 @@ If it contains \"%s\" then the directory is substituted for that."
(caar magit-repolist-columns))
flip))))
(setq tabulated-list-format
(vconcat (-map-indexed
(lambda (idx column)
(vconcat (seq-map-indexed
(lambda (column idx)
(pcase-let* ((`(,title ,width ,_fn ,props) column)
(sort-set (assoc :sort props))
(sort-fn (cadr sort-set)))
@@ -344,8 +342,8 @@ If it contains \"%s\" then the directory is substituted for that."
See `tabulated-list--get-sorter'. Given a more reasonable API
this would not be necessary and one could just use SORT-PREDICATE
directly. CONVERT-CELL can be used to turn the cell value, which
is always a string back into e.g. a number. COLUMN-IDX has to be
the index of the column that uses the returned sorter function."
is always a string back into, e.g., a number. COLUMN-IDX has to
be the index of the column that uses the returned sorter function."
(lambda (a b)
(funcall sort-predicate
(funcall convert-cell (aref (cadr a) column-idx))

View File

@@ -1,6 +1,6 @@
;;; magit-reset.el --- Reset functionality -*- lexical-binding:t -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
@@ -34,15 +34,16 @@
(transient-define-prefix magit-reset ()
"Reset the `HEAD', index and/or worktree to a previous state."
:man-page "git-reset"
["Reset"
("m" "mixed (HEAD and index)" magit-reset-mixed)
("s" "soft (HEAD only)" magit-reset-soft)
("h" "hard (HEAD, index and files)" magit-reset-hard)
("k" "keep (HEAD and index, keeping uncommitted)" magit-reset-keep)
("i" "index (only)" magit-reset-index)
("w" "worktree (only)" magit-reset-worktree)
""
("f" "a file" magit-file-checkout)])
[["Reset"
("b" "branch" magit-branch-reset)
("f" "file" magit-file-checkout)]
["Reset this"
("m" "mixed (HEAD and index)" magit-reset-mixed)
("s" "soft (HEAD only)" magit-reset-soft)
("h" "hard (HEAD, index and worktree)" magit-reset-hard)
("k" "keep (HEAD and index, keeping uncommitted)" magit-reset-keep)
("i" "index (only)" magit-reset-index)
("w" "worktree (only)" magit-reset-worktree)]])
;;;###autoload
(defun magit-reset-mixed (commit)

View File

@@ -1,6 +1,6 @@
;;; magit-sequence.el --- History manipulation in Magit -*- lexical-binding:t -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
@@ -281,8 +281,8 @@ the process manually."
(unless (magit-branch-p dst)
(let ((magit-process-raise-error t))
(magit-call-git "branch" dst start-point))
(--when-let (magit-get-indirect-upstream-branch start-point)
(magit-call-git "branch" "--set-upstream-to" it dst)))
(when-let ((upstream (magit-get-indirect-upstream-branch start-point)))
(magit-call-git "branch" "--set-upstream-to" upstream dst)))
(unless (equal dst current)
(let ((magit-process-raise-error t))
(magit-call-git "checkout" dst)))
@@ -335,12 +335,11 @@ the process manually."
(list commits))))
(magit-run-git-sequencer
(if revert "revert" "cherry-pick")
(pcase-let ((`(,merge ,non-merge)
(-separate #'magit-merge-commit-p commits)))
(let ((merges (seq-filter #'magit-merge-commit-p commits)))
(cond
((not merge)
((not merges)
(--remove (string-prefix-p "--mainline=" it) args))
(non-merge
((cl-set-difference commits merges :test #'equal)
(user-error "Cannot %s merge and non-merge commits at once"
command))
((--first (string-prefix-p "--mainline=" it) args)
@@ -353,11 +352,13 @@ the process manually."
(defun magit-cherry-pick-in-progress-p ()
;; .git/sequencer/todo does not exist when there is only one commit left.
(or (file-exists-p (magit-git-dir "CHERRY_PICK_HEAD"))
;; And CHERRY_PICK_HEAD does not exist when a conflict happens
;; while picking a series of commits with --no-commit.
(when-let ((line (magit-file-line (magit-git-dir "sequencer/todo"))))
(string-prefix-p "pick" line))))
(let ((dir (magit-gitdir)))
(or (file-exists-p (expand-file-name "CHERRY_PICK_HEAD" dir))
;; And CHERRY_PICK_HEAD does not exist when a conflict happens
;; while picking a series of commits with --no-commit.
(and-let* ((line (magit-file-line
(expand-file-name "sequencer/todo" dir))))
(string-prefix-p "pick" line)))))
;;; Revert
@@ -409,11 +410,13 @@ without prompting."
(defun magit-revert-in-progress-p ()
;; .git/sequencer/todo does not exist when there is only one commit left.
(or (file-exists-p (magit-git-dir "REVERT_HEAD"))
;; And REVERT_HEAD does not exist when a conflict happens while
;; reverting a series of commits with --no-commit.
(when-let ((line (magit-file-line (magit-git-dir "sequencer/todo"))))
(string-prefix-p "revert" line))))
(let ((dir (magit-gitdir)))
(or (file-exists-p (expand-file-name "REVERT_HEAD" dir))
;; And REVERT_HEAD does not exist when a conflict happens
;; while reverting a series of commits with --no-commit.
(and-let* ((line (magit-file-line
(expand-file-name "sequencer/todo" dir))))
(string-prefix-p "revert" line)))))
;;; Patch
@@ -506,7 +509,7 @@ This discards all changes made since the sequence started."
(user-error "Not applying any patches")))
(defun magit-am-in-progress-p ()
(file-exists-p (magit-git-dir "rebase-apply/applying")))
(file-exists-p (expand-file-name "rebase-apply/applying" (magit-gitdir))))
;;; Rebase
@@ -722,7 +725,7 @@ START has to be selected from a list of recent commits."
(m2 ".\nDo you really want to modify them"))
(magit-confirm (or magit--rebase-published-symbol 'rebase-published)
(concat m1 "%s" m2)
(concat m1 "%i public branches" m2)
(concat m1 "%d public branches" m2)
nil branches))
(push (magit-toplevel) magit--rebase-public-edit-confirmed)))
(if (and (magit-git-lines "rev-list" "--merges" (concat since "..HEAD"))
@@ -814,12 +817,14 @@ edit. With a prefix argument the old message is reused as-is."
(if (magit-rebase-in-progress-p)
(if (magit-anything-unstaged-p t)
(user-error "Cannot continue rebase with unstaged changes")
(when (and (magit-anything-staged-p)
(file-exists-p (magit-git-dir "rebase-merge"))
(not (member (magit-toplevel)
magit--rebase-public-edit-confirmed)))
(magit-commit-amend-assert
(magit-file-line (magit-git-dir "rebase-merge/orig-head"))))
(let ((dir (magit-gitdir)))
(when (and (magit-anything-staged-p)
(file-exists-p (expand-file-name "rebase-merge" dir))
(not (member (magit-toplevel)
magit--rebase-public-edit-confirmed)))
(magit-commit-amend-assert
(magit-file-line
(expand-file-name "rebase-merge/orig-head" dir)))))
(if noedit
(with-environment-variables (("GIT_EDITOR" "true"))
(magit-run-git-async (magit--rebase-resume-command) "--continue")
@@ -856,20 +861,25 @@ edit. With a prefix argument the old message is reused as-is."
(defun magit-rebase-in-progress-p ()
"Return t if a rebase is in progress."
(or (file-exists-p (magit-git-dir "rebase-merge"))
(file-exists-p (magit-git-dir "rebase-apply/onto"))))
(let ((dir (magit-gitdir)))
(or (file-exists-p (expand-file-name "rebase-merge" dir))
(file-exists-p (expand-file-name "rebase-apply/onto" dir)))))
(defun magit--rebase-resume-command ()
(if (file-exists-p (magit-git-dir "rebase-recursive")) "rbr" "rebase"))
(if (file-exists-p (expand-file-name "rebase-recursive" (magit-gitdir)))
"rbr"
"rebase"))
(defun magit-rebase--get-state-lines (file)
(and (magit-rebase-in-progress-p)
(magit-file-line
(magit-git-dir
(concat (if (file-directory-p (magit-git-dir "rebase-merge"))
"rebase-merge/"
"rebase-apply/")
file)))))
(let ((dir (magit-gitdir)))
(magit-file-line
(expand-file-name
(concat (if (file-directory-p (expand-file-name "rebase-merge" dir))
"rebase-merge/"
"rebase-apply/")
file)
dir)))))
;;; Sections
@@ -878,24 +888,25 @@ edit. With a prefix argument the old message is reused as-is."
If no such sequence is in progress, do nothing."
(let ((picking (magit-cherry-pick-in-progress-p)))
(when (or picking (magit-revert-in-progress-p))
(magit-insert-section (sequence)
(magit-insert-heading (if picking "Cherry Picking" "Reverting"))
(when-let ((lines
(cdr (magit-file-lines (magit-git-dir "sequencer/todo")))))
(dolist (line (nreverse lines))
(when (string-match
"^\\(pick\\|revert\\) \\([^ ]+\\) \\(.*\\)$" line)
(magit-bind-match-strings (cmd hash msg) line
(magit-insert-section (commit hash)
(insert (propertize cmd 'font-lock-face 'magit-sequence-pick)
" " (propertize hash 'font-lock-face 'magit-hash)
" " msg "\n"))))))
(magit-sequence-insert-sequence
(magit-file-line (magit-git-dir (if picking
"CHERRY_PICK_HEAD"
"REVERT_HEAD")))
(magit-file-line (magit-git-dir "sequencer/head")))
(insert "\n")))))
(let ((dir (magit-gitdir)))
(magit-insert-section (sequence)
(magit-insert-heading (if picking "Cherry Picking" "Reverting"))
(when-let ((lines (cdr (magit-file-lines
(expand-file-name "sequencer/todo" dir)))))
(dolist (line (nreverse lines))
(when (string-match
"^\\(pick\\|revert\\) \\([^ ]+\\) \\(.*\\)$" line)
(magit-bind-match-strings (cmd hash msg) line
(magit-insert-section (commit hash)
(insert (propertize cmd 'font-lock-face 'magit-sequence-pick)
" " (propertize hash 'font-lock-face 'magit-hash)
" " msg "\n"))))))
(magit-sequence-insert-sequence
(magit-file-line
(expand-file-name (if picking "CHERRY_PICK_HEAD" "REVERT_HEAD")
dir))
(magit-file-line (expand-file-name "sequencer/head" dir)))
(insert "\n"))))))
(defun magit-insert-am-sequence ()
"Insert section for the on-going patch applying sequence.
@@ -903,24 +914,31 @@ If no such sequence is in progress, do nothing."
(when (magit-am-in-progress-p)
(magit-insert-section (rebase-sequence)
(magit-insert-heading "Applying patches")
(let ((patches (nreverse (magit-rebase-patches)))
patch commit)
(while patches
(let* ((patches (nreverse (magit-rebase-patches)))
(dir (expand-file-name "rebase-apply" (magit-gitdir)))
(i (string-to-number
(magit-file-line (expand-file-name "last" dir))))
(cur (string-to-number
(magit-file-line (expand-file-name "next" dir))))
patch commit)
(while (and patches (>= i cur))
(setq patch (pop patches))
(setq commit (magit-commit-p
(cadr (split-string (magit-file-line patch)))))
(cond ((and commit patches)
(cond ((and commit (= i cur))
(magit-sequence-insert-commit
"stop" commit 'magit-sequence-stop))
((= i cur)
(magit-sequence-insert-am-patch
"stop" patch 'magit-sequence-stop))
(commit
(magit-sequence-insert-commit
"pick" commit 'magit-sequence-pick))
(patches
(magit-sequence-insert-am-patch
"pick" patch 'magit-sequence-pick))
(commit
(magit-sequence-insert-sequence commit "ORIG_HEAD"))
(t
(magit-sequence-insert-am-patch
"stop" patch 'magit-sequence-stop)
(magit-sequence-insert-sequence nil "ORIG_HEAD")))))
"pick" patch 'magit-sequence-pick)))
(cl-decf i)))
(magit-sequence-insert-sequence nil "ORIG_HEAD")
(insert ?\n))))
(defun magit-sequence-insert-am-patch (type patch face)
@@ -941,13 +959,15 @@ If no such sequence is in progress, do nothing."
"Insert section for the on-going rebase sequence.
If no such sequence is in progress, do nothing."
(when (magit-rebase-in-progress-p)
(let* ((interactive (file-directory-p (magit-git-dir "rebase-merge")))
(let* ((gitdir (magit-gitdir))
(interactive
(file-directory-p (expand-file-name "rebase-merge" gitdir)))
(dir (if interactive "rebase-merge/" "rebase-apply/"))
(name (thread-first (concat dir "head-name")
magit-git-dir
(expand-file-name gitdir)
magit-file-line))
(onto (thread-first (concat dir "onto")
magit-git-dir
(expand-file-name gitdir)
magit-file-line))
(onto (or (magit-rev-name onto name)
(magit-rev-name onto "refs/heads/*") onto))
@@ -962,11 +982,12 @@ If no such sequence is in progress, do nothing."
(defun magit-rebase--todo ()
"Return `git-rebase-action' instances for remaining rebase actions.
These are ordered in that the same way they'll be sorted in the
status buffer (i.e. the reverse of how they will be applied)."
status buffer (i.e., the reverse of how they will be applied)."
(let ((comment-start (or (magit-get "core.commentChar") "#"))
lines)
(with-temp-buffer
(insert-file-contents (magit-git-dir "rebase-merge/git-rebase-todo"))
(insert-file-contents
(expand-file-name "rebase-merge/git-rebase-todo" (magit-gitdir)))
(while (not (eobp))
(let ((ln (git-rebase-current-line)))
(when (oref ln action-type)
@@ -993,28 +1014,34 @@ status buffer (i.e. the reverse of how they will be applied)."
"\s"
(magit-format-rev-summary hash) "\n"))
(error "failed to parse merge message hash"))))))
(magit-sequence-insert-sequence
(magit-file-line (magit-git-dir "rebase-merge/stopped-sha"))
onto
(and-let* ((lines (magit-file-lines (magit-git-dir "rebase-merge/done"))))
(cadr (split-string (car (last lines)))))))
(let ((dir (magit-gitdir)))
(magit-sequence-insert-sequence
(magit-file-line (expand-file-name "rebase-merge/stopped-sha" dir))
onto
(and-let* ((lines (magit-file-lines
(expand-file-name "rebase-merge/done" dir))))
(cadr (split-string (car (last lines))))))))
(defun magit-rebase-insert-apply-sequence (onto)
(let ((rewritten
(--map (car (split-string it))
(magit-file-lines (magit-git-dir "rebase-apply/rewritten"))))
(stop (magit-file-line (magit-git-dir "rebase-apply/original-commit"))))
(let* ((dir (magit-gitdir))
(rewritten
(--map (car (split-string it))
(magit-file-lines
(expand-file-name "rebase-apply/rewritten" dir))))
(stop (magit-file-line
(expand-file-name "rebase-apply/original-commit" dir))))
(dolist (patch (nreverse (cdr (magit-rebase-patches))))
(let ((hash (cadr (split-string (magit-file-line patch)))))
(unless (or (member hash rewritten)
(equal hash stop))
(magit-sequence-insert-commit "pick" hash 'magit-sequence-pick)))))
(magit-sequence-insert-sequence
(magit-file-line (magit-git-dir "rebase-apply/original-commit"))
onto))
(magit-sequence-insert-commit "pick" hash 'magit-sequence-pick))))
(magit-sequence-insert-sequence
(magit-file-line (expand-file-name "rebase-apply/original-commit" dir))
onto)))
(defun magit-rebase-patches ()
(directory-files (magit-git-dir "rebase-apply") t "^[0-9]\\{4\\}$"))
(directory-files (expand-file-name "rebase-apply" (magit-gitdir))
t "\\`[0-9]\\{4\\}\\'"))
(defun magit-sequence-insert-sequence (stop onto &optional orig)
(let ((head (magit-rev-parse "HEAD")) done)
@@ -1022,8 +1049,8 @@ status buffer (i.e. the reverse of how they will be applied)."
(setq done (magit-git-lines "log" "--format=%H" (concat onto "..HEAD")))
(when (and stop (not (member (magit-rev-parse stop) done)))
(let ((id (magit-patch-id stop)))
(--if-let (--first (equal (magit-patch-id it) id) done)
(setq stop it)
(if-let ((matched (--first (equal (magit-patch-id it) id) done)))
(setq stop matched)
(cond
((--first (magit-rev-equal it stop) done)
;; The commit's testament has been executed.
@@ -1041,10 +1068,12 @@ status buffer (i.e. the reverse of how they will be applied)."
(cond
;; ...but we could end up at the same tree just by committing.
((or (magit-rev-equal staged stop)
(magit-rev-equal unstaged stop)) "goal")
(magit-rev-equal unstaged stop))
"goal")
;; ...but the changes are still there, untainted.
((or (equal (magit-patch-id staged) id)
(equal (magit-patch-id unstaged) id)) "same")
(equal (magit-patch-id unstaged) id))
"same")
;; ...and some changes are gone and/or others were added.
(t "work")))
stop 'magit-sequence-part))

View File

@@ -1,6 +1,6 @@
;;; magit-sparse-checkout.el --- Sparse checkout support for Magit -*- lexical-binding:t -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Author: Kyle Meyer <kyle@kyleam.com>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
@@ -98,7 +98,7 @@ See the `git sparse-checkout' manpage for details about
To extend rather than override the currently configured
directories, call `magit-sparse-checkout-add' instead."
(interactive
(list (magit-completing-read-multiple*
(list (magit-completing-read-multiple
"Include these directories: "
;; Note: Given that the appeal of sparse checkouts is
;; dealing with very large trees, listing all subdirectories
@@ -114,7 +114,7 @@ directories, call `magit-sparse-checkout-add' instead."
To override rather than extend the currently configured
directories, call `magit-sparse-checkout-set' instead."
(interactive
(list (magit-completing-read-multiple*
(list (magit-completing-read-multiple
"Add these directories: "
;; Same performance note as in `magit-sparse-checkout-set',
;; but even more so given the additional processing.

View File

@@ -1,6 +1,6 @@
;;; magit-stash.el --- Stash support for Magit -*- lexical-binding:t -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
@@ -80,6 +80,11 @@ AUTHOR-WIDTH has to be an integer. When the name of the author
:set-after '(magit-log-margin)
:set (apply-partially #'magit-margin-set-variable 'magit-stashes-mode))
;;;; Variables
(defvar magit-stash-read-message-function #'magit-stash-read-message
"Function used to read the message when creating a stash.")
;;; Commands
;;;###autoload (autoload 'magit-stash "magit-stash" nil t)
@@ -160,16 +165,29 @@ while two prefix arguments are equivalent to `--all'."
(magit-stash-save message t t include-untracked t 'index))
(defun magit-stash-read-args ()
(list (magit-stash-read-message)
(list (funcall magit-stash-read-message-function)
(magit-stash-read-untracked)))
(defun magit-stash-read-untracked ()
(let ((prefix (prefix-numeric-value current-prefix-arg))
(args (magit-stash-arguments)))
(cond ((or (= prefix 16) (member "--all" args)) 'all)
((or (= prefix 4) (member "--include-untracked" args)) t))))
(defun magit-stash-read-message ()
"Read a message from the minibuffer, to be used for a stash.
The message that Git would have picked, is available as the
default (used when the user enters the empty string) and as
the next history element (which can be accessed with \
\\<minibuffer-local-map>\\[next-history-element])."
(read-string (format "Stash message (default: On%s:%s): "
(magit--ellipsis) (magit--ellipsis))
nil nil
(format "On %s: %s"
(or (magit-get-current-branch) "(no branch)")
(magit-rev-format "%h %s"))))
(defun magit-stash-read-message-traditional ()
"Read a message from the minibuffer, to be used for a stash.
If the user confirms the initial-input unmodified, then the
abbreviated commit hash and commit summary are appended.
The resulting message is what Git would have used."
(let* ((default (format "On %s: "
(or (magit-get-current-branch) "(no branch)")))
(input (magit-read-string "Stash message" default)))
@@ -177,6 +195,12 @@ while two prefix arguments are equivalent to `--all'."
(concat default (magit-rev-format "%h %s"))
input)))
(defun magit-stash-read-untracked ()
(let ((prefix (prefix-numeric-value current-prefix-arg))
(args (magit-stash-arguments)))
(cond ((or (= prefix 16) (member "--all" args)) 'all)
((or (= prefix 4) (member "--include-untracked" args)) t))))
;;;###autoload
(defun magit-snapshot-both (&optional include-untracked)
"Create a snapshot of the index and working tree.
@@ -237,31 +261,79 @@ specifying a list of files to be stashed."
;;;###autoload
(defun magit-stash-apply (stash)
"Apply a stash to the working tree.
Try to preserve the stash index. If that fails because there
are staged changes, apply without preserving the stash index."
First try \"git stash apply --index\", which tries to preserve
the index stored in the stash, if any. This may fail because
applying the stash could result in conflicts and those have to
be stored in the index, making it impossible to also store the
stash's index there as well.
If the above failed, then try \"git stash apply\". This fails
\(with or without \"--index\") if there are any uncommitted
changes to files that are also modified in the stash.
If both of the above failed, then apply using \"git apply\".
If there are no conflicting files, use \"--3way\". If there are
conflicting files, then using \"--3way\" requires that those
files are staged first, which may be undesirable, so prompt
the user whether to use \"--3way\" or \"--reject\"."
(interactive (list (magit-read-stash "Apply stash")))
(if (= (magit-call-git "stash" "apply" "--index" stash) 0)
(magit-refresh)
(magit-run-git "stash" "apply" stash)))
(magit-stash--apply "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
are staged changes, apply without preserving the stash index
and forgo removing the stash."
"Apply a stash to the working tree, on success remove it from stash list.
First try \"git stash pop --index\", which tries to preserve
the index stored in the stash, if any. This may fail because
applying the stash could result in conflicts and those have to
be stored in the index, making it impossible to also store the
stash's index there as well.
If the above failed, then try \"git stash apply\". This fails
\(with or without \"--index\") if there are any uncommitted
changes to files that are also modified in the stash.
If both of the above failed, then apply using \"git apply\".
If there are no conflicting files, use \"--3way\". If there are
conflicting files, then using \"--3way\" requires that those
files are staged first, which may be undesirable, so prompt
the user whether to use \"--3way\" or \"--reject\"."
(interactive (list (magit-read-stash "Pop stash")))
(if (= (magit-call-git "stash" "apply" "--index" stash) 0)
(magit-stash-drop stash)
(magit-run-git "stash" "apply" stash)))
(magit-stash--apply "pop" stash))
(defun magit-stash--apply (action stash)
(or (= (magit-call-git "stash" action "--index" stash) 0)
;; The stash's index could not be applied, so always keep the stash.
(= (magit-call-git "stash" "apply" stash) 0)
(let* ((range (format "%s^..%s" stash stash))
(stashed (magit-git-items "diff" "-z" "--name-only" range "--"))
(conflicts (cl-sort (cl-union (magit-unstaged-files t stashed)
(magit-untracked-files t stashed)
:test #'equal)
#'string<))
(arg (cond
((not conflicts) "--3way")
((magit-confirm-files
'stash-apply-3way conflicts
"Apply stash using `--3way', which requires first staging"
"(else use `--reject')"
t)
(magit-stage-1 nil conflicts)
"--3way")
("--reject"))))
(with-temp-buffer
(magit-git-insert "diff" range)
(magit-run-git-with-input "apply" arg "-"))))
(magit-refresh))
;;;###autoload
(defun magit-stash-drop (stash)
"Remove a stash from the stash list.
When the region is active offer to drop all contained stashes."
(interactive
(list (--if-let (magit-region-values 'stash)
(magit-confirm 'drop-stashes nil "Drop %i stashes" nil it)
(list (if-let ((values (magit-region-values 'stash)))
(magit-confirm 'drop-stashes nil "Drop %d stashes" nil values)
(magit-read-stash "Drop stash"))))
(dolist (stash (if (listp stash)
(nreverse (prog1 stash (setq stash (car stash))))
@@ -282,20 +354,23 @@ When the region is active offer to drop all contained stashes."
;;;###autoload
(defun magit-stash-branch (stash branch)
"Create and checkout a new BRANCH from STASH."
"Create and checkout a new BRANCH from an existing STASH.
The new branch starts at the commit that was current when the
stash was created. If the stash applies cleanly, then drop it."
(interactive (list (magit-read-stash "Branch stash")
(magit-read-string-ns "Branch name")))
(magit-run-git "stash" "branch" branch stash))
;;;###autoload
(defun magit-stash-branch-here (stash branch)
"Create and checkout a new BRANCH and apply STASH.
The branch is created using `magit-branch-and-checkout', using the
current branch or `HEAD' as the start-point."
"Create and checkout a new BRANCH from an existing STASH.
Use the current branch or `HEAD' as the starting-point of BRANCH.
Then apply STASH, dropping it if it applies cleanly."
(interactive (list (magit-read-stash "Branch stash")
(magit-read-string-ns "Branch name")))
(let ((magit-inhibit-refresh t))
(magit-branch-and-checkout branch (or (magit-get-current-branch) "HEAD")))
(let ((start-point (or (magit-get-current-branch) "HEAD")))
(magit-call-git "checkout" "-b" branch start-point)
(magit-branch-maybe-adjust-upstream branch start-point))
(magit-stash-apply stash))
;;;###autoload
@@ -373,21 +448,23 @@ current branch or `HEAD' as the start-point."
;;; Sections
(defvar magit-stashes-section-map
(let ((map (make-sparse-keymap)))
(magit-menu-set map [magit-visit-thing] #'magit-stash-list "List %t")
(magit-menu-set map [magit-delete-thing] #'magit-stash-clear "Clear %t")
map)
"Keymap for `stashes' section.")
(defvar-keymap magit-stashes-section-map
:doc "Keymap for `stashes' section."
"<remap> <magit-delete-thing>" #'magit-stash-clear
"<remap> <magit-visit-thing>" #'magit-stash-list
"<2>" (magit-menu-item "Clear %t" #'magit-stash-clear)
"<1>" (magit-menu-item "List %t" #'magit-stash-list))
(defvar magit-stash-section-map
(let ((map (make-sparse-keymap)))
(magit-menu-set map [magit-visit-thing] #'magit-stash-show "Visit %v")
(magit-menu-set map [magit-delete-thing] #'magit-stash-drop "Delete %M")
(magit-menu-set map [magit-cherry-apply] #'magit-stash-apply "Apply %M")
(magit-menu-set map [magit-cherry-pick] #'magit-stash-pop "Pop %M")
map)
"Keymap for `stash' sections.")
(defvar-keymap magit-stash-section-map
:doc "Keymap for `stash' sections."
"<remap> <magit-cherry-pick>" #'magit-stash-pop
"<remap> <magit-cherry-apply>" #'magit-stash-apply
"<remap> <magit-delete-thing>" #'magit-stash-drop
"<remap> <magit-visit-thing>" #'magit-stash-show
"<4>" (magit-menu-item "Pop %M" #'magit-stash-pop)
"<3>" (magit-menu-item "Apply %M" #'magit-stash-apply)
"<2>" (magit-menu-item "Delete %M" #'magit-stash-drop)
"<1>" (magit-menu-item "Visit %v" #'magit-stash-show))
(magit-define-section-jumper magit-jump-to-stashes
"Stashes" stashes "refs/stash")
@@ -522,8 +599,9 @@ If there is no stash buffer in the same frame, then do nothing."
(defun magit-stash-insert-section (commit range message &optional files)
(magit-insert-section (commit commit)
(magit-insert-heading message)
(magit--insert-diff "diff" range "-p" "--no-prefix" magit-buffer-diff-args
"--" (or files magit-buffer-diff-files))))
(magit--insert-diff nil
"diff" range "-p" "--no-prefix" magit-buffer-diff-args
"--" (or files magit-buffer-diff-files))))
(defun magit-insert-stash-notes ()
"Insert section showing notes for a stash.

View File

@@ -1,6 +1,6 @@
;;; magit-status.el --- The grand overview -*- lexical-binding:t -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
@@ -290,7 +290,9 @@ prefix arguments:
;;;###autoload
(defalias 'magit #'magit-status
"An alias for `magit-status' for better discoverability.
"Begin using Magit.
This alias for `magit-status' exists for better discoverability.
Instead of invoking this alias for `magit-status' using
\"M-x magit RET\", you should bind a key to `magit-status'
@@ -332,13 +334,11 @@ init file: (global-set-key (kbd \"C-x g\") \\='magit-status-quick)."
;;; Mode
(defvar magit-status-mode-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map magit-mode-map)
(define-key map "j" #'magit-status-jump)
(define-key map [remap dired-jump] #'magit-dired-jump)
map)
"Keymap for `magit-status-mode'.")
(defvar-keymap magit-status-mode-map
:doc "Keymap for `magit-status-mode'."
:parent magit-mode-map
"j" #'magit-status-jump
"<remap> <dired-jump>" #'magit-dired-jump)
(transient-define-prefix magit-status-jump ()
"In a Magit-Status buffer, jump to a section."
@@ -498,12 +498,10 @@ The sections are inserted by running the functions on the hook
(magit-insert-headers 'magit-status-headers-hook)
(insert "In the beginning there was darkness\n\n")))
(defvar magit-error-section-map
(let ((map (make-sparse-keymap)))
(magit-menu-set map [magit-visit-thing]
#'magit-process-buffer "Visit process output")
map)
"Keymap for `error' sections.")
(defvar-keymap magit-error-section-map
:doc "Keymap for `error' sections."
"<remap> <magit-visit-thing>" #'magit-process-buffer
"<1>" (magit-menu-item "Visit process output" #'magit-process-buffer))
(defun magit-insert-error-header ()
"Insert the message about the Git error that just occurred.
@@ -701,12 +699,12 @@ remote in alphabetic order."
;;;; File Sections
(defvar magit-untracked-section-map
(let ((map (make-sparse-keymap)))
(magit-menu-set map [magit-stage-file] #'magit-stage "Stage files")
(magit-menu-set map [magit-delete-thing] #'magit-discard "Discard files")
map)
"Keymap for the `untracked' section.")
(defvar-keymap magit-untracked-section-map
:doc "Keymap for the `untracked' section."
"<remap> <magit-delete-thing>" #'magit-discard
"<remap> <magit-stage-file>" #'magit-stage
"<2>" (magit-menu-item "Discard files" #'magit-discard)
"<1>" (magit-menu-item "Stage files" #'magit-stage))
(magit-define-section-jumper magit-jump-to-untracked "Untracked files" untracked)

View File

@@ -1,6 +1,6 @@
;;; magit-submodule.el --- Submodule support for Magit -*- lexical-binding:t -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
@@ -100,12 +100,12 @@ The `:sort' function has a weird interface described in the
docstring of `tabulated-list--get-sort'. Alternatively `<' and
`magit-repolist-version<' can be used as those functions are
automatically replaced with functions that satisfy the interface.
Set `:sort' to nil to inhibit sorting; if unspecifed, then the
Set `:sort' to nil to inhibit sorting; if unspecified, then the
column is sortable using the default sorter.
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,
which case you should use an appropriate HEADER, set WIDTH to 1,
and set `:pad-right' to 0. \"+\" is substituted for numbers higher
than 9."
:package-version '(magit . "2.8.0")
@@ -172,9 +172,9 @@ and also setting this variable to t will lead to tears."
("s" magit-submodule-synchronize)
("d" magit-submodule-unpopulate)
("k" "Remove" magit-submodule-remove)]
["All modules actions"
("l" "List all modules" magit-list-submodules)
("f" "Fetch all modules" magit-fetch-modules)])
["Populated modules actions"
("l" "List modules" magit-list-submodules)
("f" "Fetch modules" magit-fetch-modules)])
(defun magit-submodule-arguments (&rest filters)
(--filter (and (member it filters) it)
@@ -377,7 +377,7 @@ are additional safety precautions in place, so you might be able
to recover from making a mistake here, but don't count on it."
(interactive
(list (if-let ((modules (magit-region-values 'magit-module-section t)))
(magit-confirm 'remove-modules nil "Remove %i modules" nil modules)
(magit-confirm 'remove-modules nil "Remove %d modules" nil modules)
(list (magit-read-module-path "Remove module")))
(magit-submodule-arguments "--force")
current-prefix-arg))
@@ -388,16 +388,16 @@ to recover from making a mistake here, but don't count on it."
(magit-with-toplevel
(when-let
((modified
(-filter (lambda (module)
(let ((default-directory (file-name-as-directory
(expand-file-name module))))
(and (cddr (directory-files default-directory))
(magit-anything-modified-p))))
modules)))
(seq-filter (lambda (module)
(let ((default-directory (file-name-as-directory
(expand-file-name module))))
(and (cddr (directory-files default-directory))
(magit-anything-modified-p))))
modules)))
(if (member "--force" args)
(if (magit-confirm 'remove-dirty-modules
"Remove dirty module %s"
"Remove %i dirty modules"
"Remove %d dirty modules"
t modified)
(dolist (module modified)
(let ((default-directory (file-name-as-directory
@@ -424,15 +424,16 @@ to recover from making a mistake here, but don't count on it."
(when (and trash-gitdirs
(magit-confirm 'trash-module-gitdirs
"Trash gitdir of module %s"
"Trash gitdirs of %i modules"
"Trash gitdirs of %d modules"
t modules))
(dolist (module modules)
(if-let ((name (cadr (assoc module alist))))
;; Disregard if `magit-delete-by-moving-to-trash'
;; is nil. Not doing so would be too dangerous.
(delete-directory (magit-git-dir
(convert-standard-filename
(concat "modules/" name)))
(delete-directory (convert-standard-filename
(expand-file-name
(concat "modules/" name)
(magit-gitdir)))
t t)
(error "BUG: Weird module name and/or path for %s" module)))))
(magit-refresh))))
@@ -480,10 +481,10 @@ or, failing that, the abbreviated HEAD commit hash."
(defun magit--insert-modules-overview (&optional _section)
(magit-with-toplevel
(let* ((modules (magit-list-module-paths))
(path-format (format "%%-%is "
(path-format (format "%%-%ds "
(min (apply #'max (mapcar #'length modules))
(/ (window-width) 2))))
(branch-format (format "%%-%is " (min 25 (/ (window-width) 3)))))
(branch-format (format "%%-%ds " (min 25 (/ (window-width) 3)))))
(dolist (module modules)
(let ((default-directory
(expand-file-name (file-name-as-directory module))))
@@ -492,44 +493,41 @@ or, failing that, the abbreviated HEAD commit hash."
'font-lock-face 'magit-diff-file-heading))
(if (not (file-exists-p ".git"))
(insert "(unpopulated)")
(insert (format
branch-format
(--if-let (magit-get-current-branch)
(propertize it 'font-lock-face 'magit-branch-local)
(propertize "(detached)" 'font-lock-face 'warning))))
(--if-let (magit-git-string "describe" "--tags")
(insert
(format
branch-format
(if-let ((branch (magit-get-current-branch)))
(propertize branch 'font-lock-face 'magit-branch-local)
(propertize "(detached)" 'font-lock-face 'warning))))
(if-let ((desc (magit-git-string "describe" "--tags")))
(progn (when (and magit-modules-overview-align-numbers
(string-match-p "\\`[0-9]" it))
(string-match-p "\\`[0-9]" desc))
(insert ?\s))
(insert (propertize it 'font-lock-face 'magit-tag)))
(--when-let (magit-rev-format "%h")
(insert (propertize it 'font-lock-face 'magit-hash)))))
(insert (propertize desc 'font-lock-face 'magit-tag)))
(when-let ((abbrev (magit-rev-format "%h")))
(insert (propertize abbrev 'font-lock-face 'magit-hash)))))
(insert ?\n))))))
(insert ?\n))
(defvar magit-modules-section-map
(let ((map (make-sparse-keymap)))
(magit-menu-set map [remap magit-visit-thing]
#'magit-list-submodules "List %t")
map)
"Keymap for `modules' sections.")
(defvar-keymap magit-modules-section-map
:doc "Keymap for `modules' sections."
"<remap> <magit-visit-thing>" #'magit-list-submodules
"<1>" (magit-menu-item "List %t" #'magit-list-submodules))
(defvar magit-module-section-map
(let ((map (make-sparse-keymap)))
(define-key map (kbd "C-j") #'magit-submodule-visit)
(define-key map [C-return] #'magit-submodule-visit)
(magit-menu-set map [magit-visit-thing]
#'magit-submodule-visit "Visit %s")
(magit-menu-set map [magit-stage-file]
#'magit-stage "Stage %T"
'(:visible (eq (magit-diff-type) 'unstaged)))
(magit-menu-set map [magit-unstage-file]
#'magit-unstage "Unstage %T"
'(:visible (eq (magit-diff-type) 'staged)))
(define-key-after map [separator-magit-submodule] menu-bar-separator)
(magit-menu-set map [magit-submodule] #'magit-submodule "Module commands...")
map)
"Keymap for `module' sections.")
(defvar-keymap magit-module-section-map
:doc "Keymap for `module' sections."
"C-j" #'magit-submodule-visit
"C-<return>" #'magit-submodule-visit
"<remap> <magit-unstage-file>" #'magit-unstage
"<remap> <magit-stage-file>" #'magit-stage
"<remap> <magit-visit-thing>" #'magit-submodule-visit
"<5>" (magit-menu-item "Module commands..." #'magit-submodule)
"<4>" '(menu-item "--")
"<3>" (magit-menu-item "Unstage %T" #'magit-unstage
'(:visible (eq (magit-diff-type) 'staged)))
"<2>" (magit-menu-item "Stage %T" #'magit-stage
'(:visible (eq (magit-diff-type) 'unstaged)))
"<1>" (magit-menu-item "Visit %s" #'magit-submodule-visit))
(defun magit-submodule-visit (module &optional other-window)
"Visit MODULE by calling `magit-status' on it.
@@ -628,15 +626,13 @@ These sections can be expanded to show the respective commits."
;;;###autoload
(defun magit-list-submodules ()
"Display a list of the current repository's submodules."
"Display a list of the current repository's populated submodules."
(interactive)
(magit-submodule-list-setup magit-submodule-list-columns))
(defvar magit-submodule-list-mode-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map magit-repolist-mode-map)
map)
"Local keymap for Magit-Submodule-List mode buffers.")
(defvar-keymap magit-submodule-list-mode-map
:doc "Local keymap for Magit-Submodule-List mode buffers."
:parent magit-repolist-mode-map)
(define-derived-mode magit-submodule-list-mode tabulated-list-mode "Modules"
"Major mode for browsing a list of Git submodules."
@@ -663,22 +659,23 @@ These sections can be expanded to show the respective commits."
(defun magit-submodule-list-refresh ()
(setq tabulated-list-entries
(-keep (lambda (module)
(let ((default-directory
(expand-file-name (file-name-as-directory module))))
(and (file-exists-p ".git")
(or (not magit-submodule-list-predicate)
(funcall magit-submodule-list-predicate module))
(list module
(vconcat
(mapcar (pcase-lambda (`(,title ,width ,fn ,props))
(or (funcall fn `((:path ,module)
(:title ,title)
(:width ,width)
,@props))
""))
magit-repolist-columns))))))
(magit-list-module-paths)))
(seq-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
(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)
@@ -694,8 +691,9 @@ These sections can be expanded to show the respective commits."
;;; Utilities
(defun magit-submodule--maybe-reuse-gitdir (name path)
(let ((gitdir
(magit-git-dir (convert-standard-filename (concat "modules/" name)))))
(let ((gitdir (convert-standard-filename
(expand-file-name (concat "modules/" name)
(magit-gitdir)))))
(when (and (file-exists-p gitdir)
(not (file-exists-p path)))
(pcase (read-char-choice

View File

@@ -1,6 +1,6 @@
;;; magit-subtree.el --- Subtree support for Magit -*- lexical-binding:t -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
@@ -107,9 +107,9 @@
:reader #'magit-transient-read-revision)
(defun magit-subtree-prefix (transient prompt)
(--if-let (--first (string-prefix-p "--prefix=" it)
(transient-args transient))
(substring it 9)
(if-let ((arg (--first (string-prefix-p "--prefix=" it)
(transient-args transient))))
(substring arg 9)
(magit-subtree-read-prefix prompt)))
(defun magit-subtree-arguments (transient)

View File

@@ -1,6 +1,6 @@
;;; magit-tag.el --- Tag functionality -*- lexical-binding:t -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
@@ -69,7 +69,7 @@ With a prefix argument annotate the tag.
(magit-read-branch-or-commit "Place tag on")
(let ((args (magit-tag-arguments)))
(when current-prefix-arg
(cl-pushnew "--annotate" args))
(cl-pushnew "--annotate" args :test #'equal))
args)))
(magit-run-git-with-editor "tag" args name rev))
@@ -80,8 +80,8 @@ If the region marks multiple tags (and nothing else), then offer
to delete those, otherwise prompt for a single tag to be deleted,
defaulting to the tag at point.
\n(git tag -d TAGS)"
(interactive (list (--if-let (magit-region-values 'tag)
(magit-confirm t nil "Delete %i tags" nil it)
(interactive (list (if-let ((tags (magit-region-values 'tag)))
(magit-confirm t nil "Delete %d tags" nil tags)
(let ((helm-comp-read-use-marked t))
(magit-read-tag "Delete tag" t)))))
(magit-run-git "tag" "-d" tags))
@@ -95,18 +95,18 @@ defaulting to the tag at point.
(rtags (prog2 (message "Determining remote tags...")
(magit-remote-list-tags remote)
(message "Determining remote tags...done")))
(ltags (-difference tags rtags))
(rtags (-difference rtags tags)))
(ltags (cl-set-difference tags rtags :test #'equal))
(rtags (cl-set-difference rtags tags :test #'equal)))
(unless (or ltags rtags)
(message "Same tags exist locally and remotely"))
(unless (magit-confirm t
"Delete %s locally"
"Delete %i tags locally"
"Delete %d tags locally"
'noabort ltags)
(setq ltags nil))
(unless (magit-confirm t
"Delete %s from remote"
"Delete %i tags from remote"
"Delete %d tags from remote"
'noabort rtags)
(setq rtags nil))
(list ltags rtags remote)))
@@ -127,7 +127,7 @@ defaulting to the tag at point.
See also `magit-release-tag-regexp'.")
(defvar magit-release-tag-regexp "\\`\
\\(?1:\\(?:v\\(?:ersion\\)?\\|r\\(?:elease\\)?\\)?[-_]?\\)?\
\\(?1:\\(?:v\\(?:ersion\\)?\\|r\\(?:elease\\)?\\)[-_]?\\)?\
\\(?2:[0-9]+\\(?:\\.[0-9]+\\)*\
\\(?:-[a-zA-Z0-9-]+\\(?:\\.[a-zA-Z0-9-]+\\)*\\)?\\)\\'"
"Regexp used by `magit-tag-release' to parse release tags.

View File

@@ -1,6 +1,6 @@
;;; magit-transient.el --- Support for transients -*- lexical-binding:t -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
@@ -37,12 +37,12 @@
(defclass magit--git-variable (transient-variable)
((scope :initarg :scope)
(global :initarg :global :initform nil)))
(global :initarg :global :initform nil)
(default :initarg :default :initform nil)))
(defclass magit--git-variable:choices (magit--git-variable)
((choices :initarg :choices)
(fallback :initarg :fallback :initform nil)
(default :initarg :default :initform nil)))
(fallback :initarg :fallback :initform nil)))
(defclass magit--git-variable:boolean (magit--git-variable:choices)
((choices :initarg :choices :initform '("true" "false"))))
@@ -134,9 +134,9 @@
(seturl (oref obj seturl-arg))
(remote (oref transient--prefix scope)))
(oset obj value values)
(dolist (v (-difference values previous))
(dolist (v (cl-set-difference values previous :test #'equal))
(magit-call-git "remote" "set-url" seturl "--add" remote v))
(dolist (v (-difference previous values))
(dolist (v (cl-set-difference previous values :test #'equal))
(magit-call-git "remote" "set-url" seturl "--delete" remote
(concat "^" (regexp-quote v) "$")))
(magit-refresh)))
@@ -158,7 +158,11 @@
(propertize (car value) 'face 'transient-value))
(propertize (car (split-string value "\n"))
'face 'transient-value))
(propertize "unset" 'face 'transient-inactive-value)))
(if-let* ((default (oref obj default))
(default (if (functionp default) (funcall default) default)))
(concat (propertize "default:" 'face 'transient-inactive-value)
(propertize default 'face 'transient-value))
(propertize "unset" 'face 'transient-inactive-value))))
(cl-defmethod transient-format-value ((obj magit--git-variable:choices))
(let* ((variable (oref obj variable))
@@ -215,6 +219,15 @@
'transient-value))))))
(propertize "]" 'face 'transient-inactive-value))))
;;; Utilities
(defun magit--transient-args-and-files ()
"Return (args files) for use by log and diff functions.
The value derives from that returned by `transient-get-value'."
(let ((args (transient-get-value)))
(list (seq-filter #'atom args)
(cdr (assoc "--" args)))))
;;; _
(provide 'magit-transient)
;;; magit-transient.el ends here

View File

@@ -1,6 +1,6 @@
;;; magit-wip.el --- Commit snapshots to work-in-progress refs -*- lexical-binding:t -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
@@ -103,11 +103,14 @@ is used as `branch-ref'."
;;; Modes
(defvar magit--wip-activation-cache nil)
(defvar magit--wip-inhibit-autosave nil)
;;;###autoload
(define-minor-mode magit-wip-mode
"Save uncommitted changes to work-in-progress refs.
Whenever appropriate (i.e. when dataloss would be a possibility
Whenever appropriate (i.e., when dataloss would be a possibility
otherwise) this mode causes uncommitted changes to be committed
to dedicated work-in-progress refs.
@@ -119,7 +122,8 @@ but that is discouraged."
:lighter magit-wip-mode-lighter
:global t
(let ((arg (if magit-wip-mode 1 -1)))
(magit-wip-after-save-mode arg)
(let ((magit--wip-activation-cache (list t)))
(magit-wip-after-save-mode arg))
(magit-wip-after-apply-mode arg)
(magit-wip-before-change-mode arg)
(magit-wip-initial-backup-mode arg)))
@@ -143,10 +147,32 @@ variant `magit-wip-after-save-mode'."
(remove-hook 'after-save-hook #'magit-wip-commit-buffer-file t)))
(defun magit-wip-after-save-local-mode-turn-on ()
(and buffer-file-name
(magit-inside-worktree-p t)
(magit-file-tracked-p buffer-file-name)
(magit-wip-after-save-local-mode)))
(when (and buffer-file-name
(if magit--wip-activation-cache
(if-let ((elt (assoc default-directory
magit--wip-activation-cache)))
(and-let* ((top (cadr elt)))
(member (file-relative-name buffer-file-name top)
(cddr elt)))
(if-let ((top (magit-toplevel)))
(let (files)
(if-let ((elt (assoc top magit--wip-activation-cache)))
(setq files (cddr elt))
(progn
(setq files (let ((default-directory top))
(magit-tracked-files)))
(push `(,top ,top ,@files)
magit--wip-activation-cache)
(unless (eq default-directory top)
(push `(,default-directory ,top ,@files)
magit--wip-activation-cache))))
(member (file-relative-name buffer-file-name) files))
(push (list default-directory nil)
magit--wip-activation-cache)
nil))
(and (magit-inside-worktree-p t)
(magit-file-tracked-p buffer-file-name))))
(magit-wip-after-save-local-mode)))
;;;###autoload
(define-globalized-minor-mode magit-wip-after-save-mode
@@ -159,18 +185,14 @@ variant `magit-wip-after-save-mode'."
Also see `magit-wip-after-save-mode' which calls this function
automatically whenever a buffer visiting a tracked file is saved."
(interactive)
(--when-let (magit-wip-get-ref)
(magit-with-toplevel
(let ((file (file-relative-name buffer-file-name)))
(magit-wip-commit-worktree
it (list file)
(format (cond (msg)
((called-interactively-p 'any)
"wip-save %s after save")
(t
"autosave %s after save"))
file))))))
(interactive (list "wip-save %s after save"))
(unless magit--wip-inhibit-autosave
(when-let ((ref (magit-wip-get-ref)))
(magit-with-toplevel
(let ((file (file-relative-name buffer-file-name)))
(magit-wip-commit-worktree
ref (list file)
(format (or msg "autosave %s after save") file)))))))
;;;###autoload
(define-minor-mode magit-wip-after-apply-mode
@@ -273,9 +295,9 @@ commit message."
(interactive (list nil (if current-prefix-arg
(magit-read-string "Wip commit message")
"wip-save tracked files")))
(--when-let (magit-wip-get-ref)
(magit-wip-commit-index it files msg)
(magit-wip-commit-worktree it files msg)))
(when-let ((ref (magit-wip-get-ref)))
(magit-wip-commit-index ref files msg)
(magit-wip-commit-worktree ref files msg)))
(defun magit-wip-commit-index (ref files msg)
(let* ((wipref (magit--wip-index-ref ref))
@@ -415,7 +437,8 @@ many \"branches\" of each wip ref are shown."
(interactive
(nconc (list (magit-completing-read
"Log branch and its wip refs"
(-snoc (magit-list-local-branch-names) "HEAD")
(nconc (magit-list-local-branch-names)
(list "HEAD"))
nil t nil 'magit-revision-history
(or (magit-branch-at-point)
(magit-get-current-branch)

View File

@@ -1,6 +1,6 @@
;;; magit-worktree.el --- Worktree support -*- lexical-binding:t -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
@@ -33,7 +33,7 @@
(defcustom magit-worktree-read-directory-name-function #'read-directory-name
"Function used to read a directory for worktree commands.
This is called with one argument, the prompt, and can be used
to e.g. use a base directory other than `default-directory'.
to, e.g., use a base directory other than `default-directory'.
Used by `magit-worktree-checkout' and `magit-worktree-branch'."
:package-version '(magit . "3.0.0")
:group 'magit-commands
@@ -145,14 +145,14 @@ then show it in Dired instead."
;;; Sections
(defvar magit-worktree-section-map
(let ((map (make-sparse-keymap)))
(magit-menu-set map [magit-visit-thing] #'magit-worktree-status "Visit %s")
(magit-menu-set map [magit-delete-thing] #'magit-worktree-delete "Delete %m")
(define-key-after map [separator-magit-worktree] menu-bar-separator)
(magit-menu-set map [magit-worktree ] #'magit-worktree "Worktree commands...")
map)
"Keymap for `worktree' sections.")
(defvar-keymap magit-worktree-section-map
:doc "Keymap for `worktree' sections."
"<remap> <magit-delete-thing>" #'magit-worktree-delete
"<remap> <magit-visit-thing>" #'magit-worktree-status
"<4>" (magit-menu-item "Worktree commands..." #'magit-worktree)
"<3>" '(menu-item "--")
"<2>" (magit-menu-item "Delete %m" #'magit-worktree-delete)
"<1>" (magit-menu-item "Visit %s" #'magit-worktree-status))
(defun magit-insert-worktrees ()
"Insert sections for all worktrees.
@@ -163,29 +163,45 @@ If there is only one worktree, then insert nothing."
(magit-insert-heading "Worktrees:")
(let* ((cols
(mapcar
(pcase-lambda (`(,path ,barep ,commit ,branch))
(cons (cond
(branch (propertize
branch 'font-lock-face
(if (equal branch (magit-get-current-branch))
'magit-branch-current
'magit-branch-local)))
(commit (propertize (magit-rev-abbrev commit)
'font-lock-face 'magit-hash))
(barep "(bare)"))
path))
(lambda (config)
(pcase-let ((`(,_ ,commit ,branch ,bare) config))
(cons (cond
(branch
(propertize
branch 'font-lock-face
(if (equal branch (magit-get-current-branch))
'magit-branch-current
'magit-branch-local)))
(commit
(propertize (magit-rev-abbrev commit)
'font-lock-face 'magit-hash))
(bare "(bare)"))
config)))
worktrees))
(align (1+ (-max (--map (string-width (car it)) cols)))))
(pcase-dolist (`(,head . ,path) cols)
(magit-insert-section (worktree path)
(insert head)
(insert (make-string (- align (length head)) ?\s))
(insert (let ((r (file-relative-name path))
(a (abbreviate-file-name path)))
(if (< (string-width r) (string-width a)) r a)))
(insert ?\n))))
(align (1+ (apply #'max (--map (string-width (car it)) cols)))))
(pcase-dolist (`(,head . ,config) cols)
(magit--insert-worktree
config
(concat head (make-string (- align (length head)) ?\s)))))
(insert ?\n)))))
(defun magit--insert-worktree (config head)
"Insert worktree section for CONFIG.
See `magit-list-worktrees' for the format of CONFIG. HEAD is
a prettified reference or revision representing the worktree,
with padding for alignment."
;; #4926 Before changing the signature, inform @vermiculus.
(let ((path (car config)))
(magit-insert-section (worktree path)
(insert head)
(insert (let ((relative (file-relative-name path))
(absolute (abbreviate-file-name path)))
(if (or (> (string-width relative) (string-width absolute))
(equal relative "./"))
absolute
relative)))
(insert ?\n))))
;;; _
(provide 'magit-worktree)
;;; magit-worktree.el ends here

View File

@@ -1,6 +1,6 @@
;;; magit.el --- A Git porcelain inside Emacs -*- lexical-binding:t; coding:utf-8 -*-
;; Copyright (C) 2008-2022 The Magit Project Contributors
;; Copyright (C) 2008-2023 The Magit Project Contributors
;; Author: Marius Vollmer <marius.vollmer@gmail.com>
;; Jonas Bernoulli <jonas@bernoul.li>
@@ -20,10 +20,11 @@
;; Package-Version: 3.3.0.50-git
;; Package-Requires: (
;; (emacs "25.1")
;; (compat "28.1.1.2")
;; (compat "29.1.3.4")
;; (dash "2.19.1")
;; (git-commit "3.3.0")
;; (magit-section "3.3.0")
;; (seq "2.24")
;; (transient "0.3.6")
;; (with-editor "3.0.5"))
@@ -75,6 +76,7 @@
;; For `magit:--gpg-sign'
(declare-function epg-list-keys "epg" (context &optional name mode))
(declare-function epg-decode-dn "epg" (alist))
(defvar epa-protocol)
;;; Options
@@ -84,7 +86,7 @@ If the specified primary key has signing capacity then it is used
as the value of the `--gpg-sign' argument without prompting, even
when other such keys exist. To be able to select another key you
must then use a prefix argument."
:package-version '(magit . "3.4.0")
:package-version '(magit . "4.0.0")
:group 'magit-commands
:type 'string)
@@ -227,7 +229,7 @@ and/or `magit-branch-remote-head'."
(defface magit-signature-error
'((t :foreground "light blue"))
"Face for signatures that cannot be checked (e.g. missing key)."
"Face for signatures that cannot be checked (e.g., missing key)."
:group 'magit-faces)
(defface magit-cherry-unmatched
@@ -248,69 +250,79 @@ and/or `magit-branch-remote-head'."
;;; Global Bindings
;;;###autoload
(define-obsolete-variable-alias 'global-magit-file-mode
'magit-define-global-key-bindings "Magit 3.0.0")
(defcustom magit-define-global-key-bindings 'default
"Which set of key bindings to add to the global keymap, if any.
;;;###autoload
(defcustom magit-define-global-key-bindings t
"Whether to bind some Magit commands in the global keymap.
This option controls which set of Magit key bindings, if any, may
be added to the global keymap, even before Magit is first used in
the current Emacs session.
If this variable is non-nil, then the following bindings may
be added to the global keymap. The default is t.
If the value is nil, no bindings are added.
key binding
--- -------
C-x g magit-status
C-x M-g magit-dispatch
C-c M-g magit-file-dispatch
If `default', maybe add:
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
that are unnecessary, as well as bindings that conflict with
other bindings.
C-x g `magit-status'
C-x M-g `magit-dispatch'
C-c M-g `magit-file-dispatch'
Adding the above bindings is delayed until `after-init-hook'
is called to allow users to set the variable anywhere in their
init file (without having to make sure to do so before `magit'
is loaded or autoloaded) and to increase the likelihood that
all the potentially conflicting user bindings have already
been added.
If `recommended', maybe add:
C-x g `magit-status'
C-c g `magit-dispatch'
C-c f `magit-file-dispatch'
These bindings are strongly recommended, but we cannot use
them by default, because the \"C-c <LETTER>\" namespace is
strictly reserved for bindings added by the user.
The bindings in the chosen set 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 that are unnecessary, as well
as bindings that conflict with other bindings.
Adding these bindings is delayed until `after-init-hook' is
run to allow users to set the variable anywhere in their init
file (without having to make sure to do so before `magit' is
loaded or autoloaded) and to increase the likelihood that all
the potentially conflicting user bindings have already been
added.
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
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
but the \"C-c <letter>\" namespace is strictly reserved for
users; preventing Magit from using it by default.
Also see info node `(magit)Commands for Buffers Visiting Files'."
:package-version '(magit . "3.0.0")
Setting this variable has no effect if `after-init-hook' has
already been run."
:package-version '(magit . "4.0.0")
:group 'magit-essentials
:type 'boolean)
:type '(choice (const :tag "Add no binding" nil)
(const :tag "Use default bindings" default)
(const :tag "Use recommended bindings" recommended)))
;;;###autoload
(progn
(defun magit-maybe-define-global-key-bindings (&optional force)
"See variable `magit-define-global-key-bindings'."
(when magit-define-global-key-bindings
(let ((map (current-global-map)))
(dolist (elt '(("C-x g" . magit-status)
("C-x M-g" . magit-dispatch)
("C-c M-g" . magit-file-dispatch)))
(let ((key (kbd (car elt)))
(def (cdr elt)))
(when (or force
(not (or (lookup-key map key)
(where-is-internal def (make-sparse-keymap) t))))
(define-key map key def)))))))
(pcase-dolist (`(,key . ,def)
(cond ((eq magit-define-global-key-bindings 'recommended)
'(("C-x g" . magit-status)
("C-c g" . magit-dispatch)
("C-c f" . magit-file-dispatch)))
('(("C-x g" . magit-status)
("C-x M-g" . magit-dispatch)
("C-c M-g" . magit-file-dispatch)))))
;; This is autoloaded and thus is used before `compat' is
;; loaded, so we cannot use `keymap-lookup' and `keymap-set'.
(when (or force
(not (or (lookup-key map (kbd key))
(where-is-internal def (make-sparse-keymap) t))))
(define-key map (kbd key) def))))))
(if after-init-time
(magit-maybe-define-global-key-bindings)
(add-hook 'after-init-hook #'magit-maybe-define-global-key-bindings t)))
@@ -389,12 +401,12 @@ Also see info node `(magit)Commands for Buffers Visiting Files'."
("U" "Unstage all" magit-unstage-all)]]
["Essential commands"
:if-derived magit-mode
[("g" " refresh current buffer" magit-refresh)
("q" " bury current buffer" magit-mode-bury-buffer)
("<tab>" " toggle section at point" magit-section-toggle)
("<return>" "visit thing at point" magit-visit-thing)]
[("C-x m" "show all key bindings" describe-mode)
("C-x i" "show Info manual" magit-info)]])
[("g" " Refresh current buffer" magit-refresh)
("q" " Bury current buffer" magit-mode-bury-buffer)
("<tab>" " Toggle section at point" magit-section-toggle)
("<return>" "Visit thing at point" magit-visit-thing)]
[("C-x m" "Show all key bindings" describe-mode)
("C-x i" "Show Info manual" magit-info)]])
;;; Git Popup
@@ -544,7 +556,7 @@ is run in the top-level directory of the current working tree."
(defconst magit-font-lock-keywords
(eval-when-compile
`((,(concat "(\\(magit-define-section-jumper\\)\\_>"
"[ \t'\(]*"
"[ \t'(]*"
"\\(\\(?:\\sw\\|\\s_\\)+\\)?")
(1 'font-lock-keyword-face)
(2 'font-lock-function-name-face nil t))
@@ -553,7 +565,8 @@ is run in the top-level directory of the current working tree."
"magit-bind-match-strings"
"magit-with-temp-index"
"magit-with-blob"
"magit-with-toplevel") t)
"magit-with-toplevel")
t)
"\\_>")
. 1))))
@@ -566,13 +579,16 @@ is run in the top-level directory of the current working tree."
Use the function by the same name instead of this variable.")
;;;###autoload
(defun magit-version (&optional print-dest)
(defun magit-version (&optional print-dest interactive)
"Return the version of Magit currently in use.
If optional argument PRINT-DEST is non-nil, output
stream (interactively, the echo area, or the current buffer with
a prefix argument), also print the used versions of Magit, Git,
and Emacs to it."
(interactive (list (if current-prefix-arg (current-buffer) t)))
If optional argument PRINT-DEST is non-nil, also print the used
versions of Magit, Transient, Git and Emacs to the output stream
selected by that argument. Interactively use the echo area, or
with a prefix argument use the current buffer. Additionally put
the output in the kill ring.
\n(fn &optional PRINT-DEST)"
(interactive (list (if current-prefix-arg (current-buffer) t) t))
(let ((magit-git-global-arguments nil)
(toplib (or load-file-name buffer-file-name))
debug)
@@ -614,12 +630,12 @@ and Emacs to it."
(when (featurep 'package)
(push 'elpa debug)
(ignore-errors
(--when-let (assq 'magit package-alist)
(when-let ((version (cadr (assq 'magit package-alist))))
(push t debug)
(setq magit-version
(and (fboundp 'package-desc-version)
(package-version-join
(package-desc-version (cadr it))))))))
(package-desc-version version)))))))
(progn
(push 'dirname debug)
(let ((dirname (file-name-nondirectory
@@ -628,7 +644,7 @@ and Emacs to it."
(setq magit-version (match-string 1 dirname)))))
;; If all else fails, just report the commit hash. It's
;; better than nothing and we cannot do better in the case
;; of e.g. a shallow clone.
;; of e.g., a shallow clone.
(progn
(push 'hash debug)
;; Same check as above to see if it's really the Magit repo.
@@ -640,24 +656,35 @@ and Emacs to it."
(magit-git-string "rev-parse" "HEAD"))))))))
(if (stringp magit-version)
(when print-dest
(princ (format "Magit %s%s, Git %s, Emacs %s, %s"
(or magit-version "(unknown)")
(or (and (ignore-errors
(magit--version>= magit-version "2008"))
(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"))))))
"")
(magit--safe-git-version)
emacs-version
system-type)
print-dest))
(let ((str (format
"Magit %s%s, Transient %s, Git %s, Emacs %s, %s"
(or magit-version "(unknown)")
(or (and (ignore-errors
(magit--version>= magit-version "2008"))
(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 (ignore-errors
(require 'lisp-mnt)
(and (fboundp 'lm-header)
(with-temp-buffer
(insert-file-contents
(locate-library "transient.el" t))
(lm-header "Package-Version"))))
"(unknown)")
(magit--safe-git-version)
emacs-version
system-type)))
(when interactive
(kill-new str))
(princ str print-dest)))
(setq debug (reverse debug))
(setq magit-version 'error)
(when magit-version
@@ -726,7 +753,6 @@ For X11 something like ~/.xinitrc should work.\n"
(require 'magit-bisect)
(require 'magit-stash)
(require 'magit-blame)
(require 'magit-obsolete)
(require 'magit-submodule)
(unless (load "magit-autoloads" t t)
(require 'magit-patch)

File diff suppressed because it is too large Load Diff