update of packages
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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))))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")))
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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")))
|
||||
|
||||
|
||||
@@ -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"))
|
||||
|
||||
@@ -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)))))))
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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+)]
|
||||
|
||||
@@ -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
@@ -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))
|
||||
|
||||
@@ -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}")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user