fordon_greeman / voidfiles

Branch: 2079ec5
Switch branches/tags
main
theidioticdev add emacs 2079ec5 23h ago
217 lines · 7.3 KB Raw Blame History
1 ;;; magit-notes.el --- Notes support -*- lexical-binding:t -*-
2
3 ;; Copyright (C) 2008-2026 The Magit Project Contributors
4
5 ;; Author: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
6 ;; Maintainer: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
7
8 ;; SPDX-License-Identifier: GPL-3.0-or-later
9
10 ;; Magit is free software: you can redistribute it and/or modify it
11 ;; under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation, either version 3 of the License, or
13 ;; (at your option) any later version.
14 ;;
15 ;; Magit is distributed in the hope that it will be useful, but WITHOUT
16 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
18 ;; License for more details.
19 ;;
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with Magit. If not, see <https://www.gnu.org/licenses/>.
22
23 ;;; Commentary:
24
25 ;; This library implements support for `git-notes'.
26
27 ;;; Code:
28
29 (require 'magit)
30
31 ;;; Commands
32
33 ;;;###autoload(autoload 'magit-notes "magit" nil t)
34 (transient-define-prefix magit-notes ()
35 "Edit notes attached to commits."
36 :man-page "git-notes"
37 ["Configure local settings"
38 ("c" magit-core.notesRef)
39 ("d" magit-notes.displayRef)]
40 ["Configure global settings"
41 ("C" magit-global-core.notesRef)
42 ("D" magit-global-notes.displayRef)]
43 ["Arguments for prune"
44 :if-not magit-notes-merging-p
45 ("-n" "Dry run" ("-n" "--dry-run"))]
46 ["Arguments for edit and remove"
47 :if-not magit-notes-merging-p
48 (magit-notes:--ref)]
49 ["Arguments for merge"
50 :if-not magit-notes-merging-p
51 (magit-notes:--strategy)]
52 ["Actions"
53 :if-not magit-notes-merging-p
54 ("T" "Edit" magit-notes-edit)
55 ("r" "Remove" magit-notes-remove)
56 ("m" "Merge" magit-notes-merge)
57 ("p" "Prune" magit-notes-prune)]
58 ["Actions"
59 :if magit-notes-merging-p
60 ("c" "Commit merge" magit-notes-merge-commit)
61 ("a" "Abort merge" magit-notes-merge-abort)])
62
63 (defun magit-notes-merging-p ()
64 (let ((dir (expand-file-name "NOTES_MERGE_WORKTREE" (magit-gitdir))))
65 (and (file-directory-p dir)
66 (directory-files dir nil "\\`[^.]"))))
67
68 (transient-define-infix magit-core.notesRef ()
69 :class 'magit--git-variable
70 :variable "core.notesRef"
71 :reader #'magit-notes-read-ref
72 :prompt "Set local core.notesRef")
73
74 (transient-define-infix magit-notes.displayRef ()
75 :class 'magit--git-variable
76 :variable "notes.displayRef"
77 :multi-value t
78 :reader #'magit-notes-read-refs
79 :prompt "Set local notes.displayRef")
80
81 (transient-define-infix magit-global-core.notesRef ()
82 :class 'magit--git-variable
83 :variable "core.notesRef"
84 :global t
85 :reader #'magit-notes-read-ref
86 :prompt "Set global core.notesRef")
87
88 (transient-define-infix magit-global-notes.displayRef ()
89 :class 'magit--git-variable
90 :variable "notes.displayRef"
91 :global t
92 :multi-value t
93 :reader #'magit-notes-read-refs
94 :prompt "Set global notes.displayRef")
95
96 (transient-define-argument magit-notes:--ref ()
97 :description "Manipulate ref"
98 :class 'transient-option
99 :key "-r"
100 :argument "--ref="
101 :reader #'magit-notes-read-ref)
102
103 (transient-define-argument magit-notes:--strategy ()
104 :description "Merge strategy"
105 :class 'transient-option
106 :shortarg "-s"
107 :argument "--strategy="
108 :choices '("manual" "ours" "theirs" "union" "cat_sort_uniq"))
109
110 (defun magit-notes-edit (commit &optional ref)
111 "Edit the note attached to COMMIT.
112 REF is the notes ref used to store the notes.
113
114 Interactively or when optional REF is nil use the value of Git
115 variable `core.notesRef' or \"refs/notes/commits\" if that is
116 undefined."
117 (interactive (magit-notes-read-args "Edit notes"))
118 (magit-run-git-with-editor "notes" (and ref (concat "--ref=" ref))
119 "edit" commit))
120
121 (defun magit-notes-remove (commit &optional ref)
122 "Remove the note attached to COMMIT.
123 REF is the notes ref from which the note is removed.
124
125 Interactively or when optional REF is nil use the value of Git
126 variable `core.notesRef' or \"refs/notes/commits\" if that is
127 undefined."
128 (interactive (magit-notes-read-args "Remove notes"))
129 (magit-run-git-with-editor "notes" (and ref (concat "--ref=" ref))
130 "remove" commit))
131
132 (defun magit-notes-merge (ref)
133 "Merge the notes ref REF into the current notes ref.
134
135 The current notes ref is the value of Git variable
136 `core.notesRef' or \"refs/notes/commits\" if that is undefined.
137
138 When there are conflicts, then they have to be resolved in the
139 temporary worktree \".git/NOTES_MERGE_WORKTREE\". When
140 done use `magit-notes-merge-commit' to finish. To abort
141 use `magit-notes-merge-abort'."
142 (interactive (list (magit-read-string-ns "Merge reference")))
143 (magit-run-git-with-editor "notes" "merge" ref))
144
145 (defun magit-notes-merge-commit ()
146 "Commit the current notes ref merge.
147 Also see `magit-notes-merge'."
148 (interactive)
149 (magit-run-git-with-editor "notes" "merge" "--commit"))
150
151 (defun magit-notes-merge-abort ()
152 "Abort the current notes ref merge.
153 Also see `magit-notes-merge'."
154 (interactive)
155 (magit-run-git-with-editor "notes" "merge" "--abort"))
156
157 (defun magit-notes-prune (&optional dry-run)
158 "Remove notes about unreachable commits."
159 (interactive (list (and (member "--dry-run" (transient-args 'magit-notes)) t)))
160 (when dry-run
161 (magit-process-buffer))
162 (magit-run-git-with-editor "notes" "prune" (and dry-run "--dry-run")))
163
164 ;;; Readers
165
166 (defun magit-notes-read-ref (prompt &optional _initial-input history)
167 (and-let ((ref (magit-completing-read
168 prompt (magit-list-notes-refnames) nil t
169 (and-let ((def (magit-get "core.notesRef")))
170 (if (string-prefix-p "refs/notes/" def)
171 (substring def 11)
172 def))
173 history)))
174 (if (string-prefix-p "refs/" ref)
175 ref
176 (concat "refs/notes/" ref))))
177
178 (defun magit-notes-read-refs (prompt &optional _initial-input _history)
179 (mapcar (lambda (ref)
180 (if (string-prefix-p "refs/" ref)
181 ref
182 (concat "refs/notes/" ref)))
183 (completing-read-multiple
184 (concat prompt ": ")
185 (magit-list-notes-refnames) nil nil
186 (mapconcat (lambda (ref)
187 (if (string-prefix-p "refs/notes/" ref)
188 (substring ref 11)
189 ref))
190 (magit-get-all "notes.displayRef")
191 ","))))
192
193 (defun magit-notes-read-args (prompt)
194 (list (magit-read-branch-or-commit prompt (magit-stash-at-point))
195 (and-let ((str (seq-find (##string-match "^--ref=\\(.+\\)" %)
196 (transient-args 'magit-notes))))
197 (match-str 1 str))))
198
199 ;;; _
200 (provide 'magit-notes)
201 ;; Local Variables:
202 ;; read-symbol-shorthands: (
203 ;; ("and$" . "cond-let--and$")
204 ;; ("thread$" . "cond-let--thread$")
205 ;; ("when$" . "cond-let--when$")
206 ;; ("and-let*" . "cond-let--and-let*")
207 ;; ("and-let" . "cond-let--and-let")
208 ;; ("if-let*" . "cond-let--if-let*")
209 ;; ("if-let" . "cond-let--if-let")
210 ;; ("when-let*" . "cond-let--when-let*")
211 ;; ("when-let" . "cond-let--when-let")
212 ;; ("while-let*" . "cond-let--while-let*")
213 ;; ("while-let" . "cond-let--while-let")
214 ;; ("match-string" . "match-string")
215 ;; ("match-str" . "match-string-no-properties"))
216 ;; End:
217 ;;; magit-notes.el ends here