Codebase list magit / dcb22a1
Update upstream source from tag 'upstream/3.0.0' Update to upstream version '3.0.0' with Debian dir 64c87ca3c2feb87f720a3dcbba85205952d98ed0 Rémi Vanicat 2 years ago
68 changed file(s) with 3304 addition(s) and 1841 deletion(s). Raw diff Collapse all Expand all
0 Asking for help
1 ===============
2
3 To ask for help please use the **Discussions** feature. To open
4 a new discussion, click [here][new] and then click on <kbd>Select
5 Category</kbd>, most likely to select the **Q&A** category.
6
7 Alternatively you can ask for help on the Emacs [StackExchange][se]
8 site (using the `magit` tag) or on the Emacs [subreddit].
9
010 Reporting issues and suggesting features
111 ========================================
212
3242 [monetary donation][donations].
3343
3444
35 [donations]: https://magit.vc/donate/
36 [issues]: https://github.com/magit/magit/issues
37 [metadocs]: https://github.com/magit/magit/wiki/Documentation-tools-and-conventions
38 [pulls]: https://github.com/magit/magit/pulls
45 [discussions]: https://github.com/magit/magit/discussions
46 [donations]: https://magit.vc/donate/
47 [issues]: https://github.com/magit/magit/issues
48 [metadocs]: https://github.com/magit/magit/wiki/Documentation-tools-and-conventions
49 [new]: https://github.com/magit/magit/discussions/new
50 [pulls]: https://github.com/magit/magit/pulls
51 [se]: https://emacs.stackexchange.com
52 [subreddit]: https://www.reddit.com/r/emacs
00 ---
11 title:
22 name: Bug report
3 about: Report a defect
3 about: Report a defect.
44 ---
55
66 Please do not ignore these instructions.
00 blank_issues_enabled: false
11 contact_links:
2 - name: Emacs StackExchange
2 - name: "SUPPORT ☛ The Discussions feature of this repository"
3 url: https://github.com/magit/magit/discussions
4 about: Please search, ask and answer questions here.
5 - name: "SUPPORT ☛ Emacs StackExchange"
36 url: https://emacs.stackexchange.com/questions/tagged/magit
4 about: Please search, ask and answer questions here.
5 - name: Emacs Reddit
7 about: Another place to search, ask and answer questions.
8 - name: "SUPPORT ☛ Emacs Reddit"
69 url: https://www.reddit.com/r/emacs
7 about: Another place to ask questions.
8 - name: Magit FAQ
10 about: Another place to search, ask and answer questions.
11 - name: "Magit FAQ"
912 url: https://magit.vc/manual/magit/FAQ.html
1013 about: It might be that many others had the same question.
11 - name: Magit Manual
14 - name: "Magit Manual"
1215 url: https://magit.vc/manual/magit/#Top
1316 about: The fine manual may also be of use.
00 ---
11 title:
22 name: Feature request
3 about: Suggest a new feature
3 about: Suggest a new feature. ⚠ PLEASE DO NOT USE THIS FOR SUPPORT REQUESTS. ⚠
44 ---
55
66 Before you ask for a new feature to be added to Magit or for an existing feature to be improved, please make sure that what are asking for does not already exist by consulting the documentation [1].
0 name: test
1 on: [ push, pull_request ]
2 jobs:
3 test:
4 runs-on: ubuntu-20.04
5 strategy:
6 matrix:
7 emacs_version:
8 - 25.1
9 # 25.2 is identical to 25.3 except for a critical security bug in
10 # enriched text mode (see Emacs Bug#28350).
11 - 25.3
12 - 26.1 # Debian is on this version.
13 - 26.3
14 - 27.1
15 - snapshot
16 git_impl:
17 - git
18 - libgit
19 steps:
20 - uses: cachix/install-nix-action@v12
21 with:
22 nix_path: nixpkgs=channel:nixos-unstable
23 - uses: cachix/cachix-action@v8
24 with:
25 name: emacs-ci
26 - uses: actions/checkout@v2
27 - name: Install
28 run: |
29 # Build and install Emacs (+ magit dependencies) using Nix
30 emacs_ci_version=$(echo "emacs-${{ matrix.emacs_version }}" | sed -e "s/\./-/g")
31 nix-env -f ./t/default.nix -iA $emacs_ci_version
32 emacs --version
33
34 # Configure Git
35 git config --global user.name "A U Thor"
36 git config --global user.email a.u.thor@example.com
37 git tag 0
38 - name: Test
39 run: |
40 make test-${{ matrix.git_impl }} DASH_DIR=$PWD
77 Chillar Anand <anand21nanda@gmail.com>
88 Christophe Junke <junke.christophe@gmail.com> <christophe.junke@parrot.com>
99 Damien Cassou <damien@cassou.me> <damien.cassou@gmail.com>
10 Daniel Fleischer <danflscr@gmail.com> danielfleischer <daniel.fleischer@amobee.com>
1011 David Abrahams <dave@boostpro.com>
1112 Dean Kariniemi <8913263+d3k4r@users.noreply.github.com>
1213 Dennis Paskorz <dennis@walltowall.com>
1920 Ivan Brennan <ivan.brennan@gmail.com>
2021 Jesse Alama <jesse.alama@gmail.com> <alama@stanford.edu>
2122 Joakim Jalap <JOJA@stoneridge.com>
23 Johann Klähn <johann@jklaehn.de> <kljohann@gmail.com>
2224 Jon Vanderwijk <jonathn@github.com>
2325 Jonas Bernoulli <jonas@bernoul.li>
2426 Jonas Bernoulli <jonas@bernoul.li> <jonasbernoulli@gmail.com>
4143 Natalie Weizenbaum <nex342@gmail.com> Nathan Weizenbaum
4244 Noam Postavsky <npostavs@users.sourceforge.net>
4345 Noam Postavsky <npostavs@users.sourceforge.net> <github.10.npostavs@spamgourmet.com>
46 Pancho Horrillo <pancho@pancho.name>
4447 Peter J. Weisberg <pj@irregularexpressions.net>
4548 Peter Vasil <mail@petervasil.net>
4649 Phil Sainty <phil@catalyst.net.nz> <phil-s@users.noreply.github.com>
5356 Sylvain Rousseau <thisirs@gmail.com>
5457 Syohei Yoshida <syohex@gmail.com>
5558 Sébastien Gross <seb@chezwam.org> <seb•ɑƬ•chezwam•ɖɵʈ•org>
59 Thierry Volpiatto <thievol@posteo.net> <thierry.volpiatto@gmail.com>
5660 Tunc Uzlu <bb2020@users.noreply.github.com>
5761 Wei Huang <weih@opera.com>
5862 Wilfred Hughes <me@wilfred.me.uk> <whughes@ahl.com>
+0
-45
.travis.yml less more
0 language: generic
1 os: linux
2 dist: xenial
3
4 env:
5 global:
6 - CURL="curl -fsSkL --retry 9 --retry-delay 9"
7 - GHRAW="https://raw.githubusercontent.com"
8 - BUILD_MAGIT_LIBGIT="false"
9 jobs:
10 - EMACS_VERSION=25.1
11 # 25.2 is identical to 25.3 except for a critical security bug in
12 # enriched text mode (see Emacs Bug#28350).
13 - EMACS_VERSION=25.3
14 - EMACS_VERSION=26.1 # Debian is on this version.
15 - EMACS_VERSION=26.3
16 - EMACS_VERSION=27 # 27.0.90, emacs-27 branch, built daily
17 - EMACS_VERSION=master # 28.0.50, master branch, built daily
18
19 jobs:
20 allow_failures:
21 - env: EMACS_VERSION=master
22
23 install:
24 - $CURL -O https://github.com/npostavs/emacs-travis/releases/download/bins/emacs-bin-${EMACS_VERSION}.tar.gz
25 - tar -xaf emacs-bin-${EMACS_VERSION}.tar.gz -C /
26 - export EMACS=/tmp/emacs/bin/emacs
27 - $CURL -O ${GHRAW}/magnars/dash.el/master/dash.el
28 - $CURL -O ${GHRAW}/magit/transient/master/lisp/transient.el
29 - $CURL -O ${GHRAW}/magit/with-editor/master/with-editor.el
30 - $EMACS -Q --batch -L . -f batch-byte-compile dash.el transient.el with-editor.el
31 - $EMACS --version
32
33 script:
34 - git config --global user.name "A U Thor"
35 - git config --global user.email a.u.thor@example.com
36 - git tag 0
37 - make lisp EMACSBIN=$EMACS DASH_DIR=$PWD
38 - make test EMACSBIN=$EMACS DASH_DIR=$PWD
39
40 notifications:
41 email:
42 # Default is change, but that includes a new branch's 1st success.
43 on_success: never
44 on_failure: always # The default.
6464 - Andrei Chițu <andrei.chitu1@gmail.com>
6565 - Andrew Eggenberger <andrew.eggenberger@gmail.com>
6666 - Andrew Kirkpatrick <andrew.kirkpatrick@adelaide.edu.au>
67 - Andrew Psaltis <apsaltis@vmware.com>
6768 - Andrew Schwartzmeyer <andrew@schwartzmeyer.com>
6869 - Andrey Smirnov <andrew.smirnov@gmail.com>
6970 - Andriy Kmit' <dev@madand.net>
7172 - Aria Edmonds <aria@ar1as.space>
7273 - Arialdo Martini <arialdomartini@gmail.com>
7374 - Arnau Roig Ninerola <arnau.ninerola@outlook.com>
75 - Ashlynn Anderson <pea@pea.sh>
7476 - Barak A. Pearlmutter <barak+git@pearlmutter.net>
7577 - Bar Magal <bmagamb@gmail.com>
7678 - Bart Bakker <bart@thesoftwarecraft.com>
8284 - Bob Uhl <buhl@zvelo.com>
8385 - Bradley Wright <brad@intranation.com>
8486 - Brandon W Maister <quodlibetor@gmail.com>
87 - Brian Leung <leungbk@mailfence.com>
8588 - Brian Warner <warner@lothar.com>
8689 - Bryan Shell <bryan.shell@orbitz.com>
8790 - Buster Copley <buster@buster.me.uk>
102105 - Craig Andera <candera@wangdera.com>
103106 - Dale Hagglund <dale.hagglund@gmail.com>
104107 - Damien Cassou <damien@cassou.me>
108 - Dan Davison <dandavison7@gmail.com>
105109 - Dan Erikson <derikson3@gmail.com>
106110 - Daniel Brockman <daniel@gointeractive.se>
107111 - Daniel Farina <drfarina@acm.org>
112 - Daniel Fleischer <danflscr@gmail.com>
108113 - Daniel Gröber <daniel@dps.uibk.ac.at>
109114 - Daniel Hackney <dan@haxney.org>
110115 - Daniel Kraus <daniel@kraus.my>
127132 - Duianto Vebotci <vebotci@openmailbox.org>
128133 - Eli Barzilay <eli@barzilay.org>
129134 - Eric Davis <ed@npri.org>
135 - Eric <e.a.gebhart@gmail.com>
130136 - Eric Prud'hommeaux <eric@w3.org>
131137 - Eric Schulte <schulte.eric@gmail.com>
132138 - Erik Anderson <erikbpanderson@gmail.com>
146152 - Graham Dobbins <gdobbins@protonmail.com>
147153 - Greg A. Woods <woods@planix.com>
148154 - Greg Lucas <greg@glucas.net>
155 - Gregory Heytings <ghe@sdf.org>
149156 - Greg Sexton <gregsexton@gmail.com>
150157 - Guillaume Martres <smarter@ubuntu.com>
151158 - Hannu Koivisto <azure@iki.fi>
152159 - Hans-Peter Deifel <hpdeifel@gmx.de>
153160 - Hussein Ait-Lahcen <hussein.ait-lahcen@fretlink.com>
154161 - Ian Eure <ian.eure@gmail.com>
162 - Ian Milligan <ianmllgn@gmail.com>
163 - Ilya Grigoriev <ilyagr@users.noreply.github.com>
164 - Ingmar Sittl <ingmar.sittl@elektrobit.com>
155165 - Ingo Lohmar <i.lohmar@gmail.com>
156166 - Ioan-Adrian Ratiu <adi@adirat.com>
157167 - Ivan Brennan <ivan.brennan@gmail.com>
164174 - Jim Blandy <jimb@red-bean.com>
165175 - Joakim Jalap <JOJA@stoneridge.com>
166176 - Johannes Altmanninger <aclopte@gmail.com>
167 - Johann Klähn <kljohann@gmail.com>
177 - Johann Klähn <johann@jklaehn.de>
168178 - John Mastro <john.b.mastro@gmail.com>
169179 - John Morris <john@zultron.com>
170180 - John Wiegley <johnw@newartisans.com>
171181 - Jonas Bernoulli <jonas@bernoul.li>
182 - Jonas Galvão Xavier <jonas.agx@gmail.com>
172183 - Jonathan Arnett <jonathan@scriptdrop.co>
184 - Jonathan del Strother <me@delstrother.com>
173185 - Jonathan Leech-Pepin <jonathan.leechpepin@gmail.com>
174186 - Jonathan Roes <jroes@jroes.net>
175187 - Jon Vanderwijk <jonathn@github.com>
197209 - Lele Gaifax <lele@metapensiero.it>
198210 - Leo Liu <sdl.web@gmail.com>
199211 - Leonardo Etcheverry <leo@kalio.net>
212 - Leo Vivier <leo.vivier+dev@gmail.com>
200213 - Lingchao Xin <douglarek@users.noreply.github.com>
201214 - Li-Yun Chang <michael142536@gmail.com>
202215 - Lluís Vilanova <vilanova@ac.upc.edu>
219232 - Mark Hepburn <Mark.Hepburn@csiro.au>
220233 - Mark Karpov <markkarpov@opmbx.org>
221234 - Mark Oteiza <mvoteiza@udel.edu>
235 - Martin Joerg <martin.joerg@gmail.com>
236 - Martin Polden <mpolden@yahoo-inc.com>
222237 - Matthew Fluet <matthew.fluet@gmail.com>
238 - Matthew Kraai <kraai@ftbfs.org>
223239 - Matthieu Hauglustaine <matt.hauglustaine@gmail.com>
224240 - Matus Goljer <dota.keys@gmail.com>
241 - Maxim Cournoyer <maxim.cournoyer@gmail.com>
225242 - Michael Fogleman <michaelwfogleman@gmail.com>
226243 - Michael Griffiths <mikey@cich.li>
227244 - Michael Heerdegen <michael_heerdegen@web.de>
245262 - Nikolay Martynov <mar.kolya@gmail.com>
246263 - Noam Postavsky <npostavs@users.sourceforge.net>
247264 - N. Troy de Freitas <me@ntdef.com>
265 - Ola x Nilsson <olani@axis.com>
248266 - Ole Arndt <oliver.arndt@cegedim.com>
249267 - Oleh Krehel <ohwoeowho@gmail.com>
250268 - Orivej Desh <orivej@gmx.fr>
251269 - Óscar Fuentes <ofv@wanadoo.es>
270 - Pancho Horrillo <pancho@pancho.name>
252271 - Paul Stadig <paul@stadig.name>
253272 - Pavel Holejsovsky <pavel.holejsovsky@upek.com>
254273 - Pekka Pessi <nospam@pessi.fi>
257276 - Peter J. Weisberg <pj@irregularexpressions.net>
258277 - Peter Vasil <mail@petervasil.net>
259278 - Philippe Vaucher <philippe.vaucher@gmail.com>
279 - Philipp Fehre <pfehre@twitter.com>
260280 - Philipp Haselwarter <philipp@haselwarter.org>
261281 - Philipp Stephani <phst@google.com>
262282 - Philip Weaver <philip.weaver@gmail.com>
265285 - Pierre Neidhardt <ambrevar@gmail.com>
266286 - Pieter Praet <pieter@praet.org>
267287 - Prathamesh Sonpatki <csonpatki@gmail.com>
288 - Pritam Baral <pritam@pritambaral.com>
268289 - rabio <rabiodev@o2.pl>
269290 - Radon Rosborough <radon.neon@gmail.com>
270291 - Rafael Laboissiere <rafael@laboissiere.net>
284305 - Rüdiger Sonderfeld <ruediger@c-plusplus.net>
285306 - Russell Black <black.russell@gmail.com>
286307 - Ryan C. Thompson <rct@thompsonclan.org>
308 - Sam Cedarbaum <scedarbaum@gmail.com>
287309 - Samuel Bronson <naesten@gmail.com>
288310 - Samuel W. Flint <swflint@flintfam.org>
289311 - Sanjoy Das <sanjoy@playingwithpointers.com>
297319 - Sergey Vinokurov <serg.foo@gmail.com>
298320 - Servilio Afre Puentes <afrepues@mcmaster.ca>
299321 - Silent Sphere <silentsphere110@gmail.com>
322 - Simon Pintarelli <simon.pintarelli@cscs.ch>
300323 - Štěpán Němec <stepnem@gmail.com>
301324 - Steven Chow <steve@myfreestuffapp.com>
302325 - Steven E. Harris <seh@panix.com>
306329 - Suhail Shergill <suhailshergill@gmail.com>
307330 - Sylvain Rousseau <thisirs@gmail.com>
308331 - Syohei Yoshida <syohex@gmail.com>
332 - Szunti <Szunti@users.noreply.github.com>
309333 - Takafumi Arakaki <aka.tkf@gmail.com>
310334 - Tassilo Horn <tsdh@gnu.org>
311335 - Teemu Likonen <tlikonen@iki.fi>
312336 - Teruki Shigitani <teruki.shigitani@gmail.com>
313 - Thierry Volpiatto <thierry.volpiatto@gmail.com>
337 - Thierry Volpiatto <thievol@posteo.net>
314338 - Thomas A Caswell <tcaswell@gmail.com>
315339 - Thomas Fini Hansen <xen@xen.dk>
316340 - Thomas Frössman <thomasf@jossystem.se>
329353 - Vineet Naik <vineet@helpshift.com>
330354 - Vitaly Ostashov <hotosho@yandex-team.ru>
331355 - Vladimir Panteleev <git@thecybershadow.net>
356 - Vladimir Sedach <vas@oneofus.la>
332357 - Wei Huang <weih@opera.com>
333358 - Wilfred Hughes <me@wilfred.me.uk>
334359 - Win Treese <treese@acm.org>
360 - Wojciech Siewierski <wojciech@siewierski.eu>
335361 - Wouter Bolsterlee <wouter@bolsterl.ee>
336362 - Xavier Noria <fxn@hashref.com>
337363 - Xu Chunyang <mail@xuchunyang.me>
364 - Yann Herklotz <git@yannherklotz.com>
338365 - Yann Hodique <yann.hodique@gmail.com>
339366 - Ynilu <ynilu.chang@gmail.com>
340367 - York Zhao <gtdplatform@gmail.com>
2222 @echo $^ | xargs -n 1 $(INSTALL_INFO) --dir=$@
2323
2424 HTML_FIXUP_CSS = '/<link rel="stylesheet" type="text\/css" href="\/assets\/page.css">/a\
25 <link class="s-css-s--style" rel="stylesheet" title="Default" href="/assets/themes/default.css">\
25 <link rel="icon" href="/assets/magit_alt1.ico">\
26 \n<link class="s-css-s--style" rel="stylesheet" title="Default" href="/assets/themes/default.css">\
2627 \n<link class="s-css-s--style" rel="stylesheet alternate" title="Default high contrast" href="/assets/themes/default-high-contrast.css">\
2728 \n<link class="s-css-s--style" rel="stylesheet alternate" title="Solarized dark xterm" href="/assets/themes/solarized-dark-xterm.css">\
2829 \n<link class="s-css-s--style" rel="stylesheet alternate" title="Black on white" href="/assets/themes/black-on-white.css">\
106107
107108 stats:
108109 @printf "Generating statistics\n"
109 @gitstats -c style=/assets/stats.css -c max_authors=999 $(TOP) $(statsdir)
110 @gitstats -c style=https://magit.vc/assets/stats.css -c max_authors=999 $(TOP) $(statsdir)
110111
111112 authors: AUTHORS.md
112113
0 * Magit v3.0.0 Release Notes (unreleased)
0 * It's Magit! A Git Porcelain inside Emacs
1
2 Magit is a text-based Git user interface that puts an unmatched focus
3 on streamlining workflows. Commands are invoked using short mnemonic
4 key sequences that take the cursor’s position in the highly actionable
5 interface into account to provide context-sensitive behavior.
6
7 With Magit you can do nearly everything that you can do when using Git
8 on the command-line, but at greater speed and while taking advantage
9 of advanced features that previously seemed too daunting to use on a
10 daily basis. Many users will find that by using Magit they can become
11 more effective Git user.
12
13 For more information about Magit, see https://magit.vc.
14
15 * Magit v3.0.0 Release Notes
16
17 Released 25th May 2021 by Jonas Bernoulli.
18
19 I am pleased to announce the release of Magit version 3.0.0,
20 representing 1264 commits by 87 contributors over 2.5 years.
21
22 Also see https://emacsair.me/2021/05/25/magit-3.0.
23
124 ** Breaking changes
225
326 - Dropped support for Git v2.0 and v2.1.
1639
1740 - The commands ~magit-branch-pull-request~, ~magit-checkout-pull-request~
1841 and ~magit-worktree-checkout-pull-request~ were removed in favor of
19 improved implementations provided by the new Forge package.
42 improved implementations provided by the new Forge package. (See
43 https://emacsair.me/2018/12/19/forge-0.1 for more information about
44 Forge.)
2045
2146 - ~C-c C-e~ is no longer bound to ~magit-dispatch-popup~. It is bound to
2247 ~magit-edit-thing~ now, so that Forge can add section-specific
3863 compatibility. Packages using the obsolete variable and functions
3964 should be adjusted soon. #3836
4065
66 - Magit-Section is now distributed as a separate package, as announced
67 here: https://emacsair.me/2020/01/23/magit-section. #4003
68
69 - Magit now adds three global key bindings, which can be prevented
70 by setting the new option ~magit-define-global-key-bindings~ before
71 loading ~magit~. Note that if you bind these keys to other commands
72 anywhere in your init file (even *after* loading ~magit~), then Magit
73 won't override those bindings. See the options doc-string for
74 more information. #4237
75
76 - Magit no longer depends on ~async-bytecomp~ to avoid a certain class
77 of mystery bugs because this effort backfired. 86eec7ba3
78
79 - ~global-git-commit-mode~ is no longer autoloaded. Users who commit
80 from the command-line but still want to use ~git-commit-mode~, might
81 now have to load ~git-commit~ explicitly in their init file.
82 13f20763a
83
4184 ** Changes since v2.90.0
4285
4386 - It isn't always obvious that a section can be expanded, especially
84127 to drop such commits, then you have to enable ~--autosquash~ in the
85128 popup and then invoke ~magit-rebase-interactive~. #3670
86129
130 - ~magit-rebase-remove-commit~ now supports removing the ~HEAD~
131 commit. #4195
132
87133 - The option ~magit-repository-directories~ defaults to ~nil~ again
88134 because the non-nil default added in v2.90.0 led to surprising
89135 changes in behavior. The documentation of this option and the
137183 - New command ~git-rebase-break~ inserts a "break" action in the
138184 rebase to-do sequence (available as of Git v2.20). #3762
139185
186 - ~git-rebase-kill-line~ and the commands for changing the action of a
187 commit line (e.g., ~git-rebase-squash~) learned to work on all lines
188 selected by the region. #4172
189
140190 - The ~--color-moved~ diff argument is supported now, but isn't
141191 available from the diff transients by default. To enable it
142192 use "C-x l" in those transients. #3424
149199 - ~magit-cherry~ is now available from the ~magit-dispatch~ prefix.
150200 ef311f378
151201
152 ~ ~magit-cherry-spinoff~ now offers the upstream as the default
202 - ~magit-cherry-spinoff~ now offers the upstream as the default
153203 starting-point. e5a2a0ac2
154204
155205 - Added new command ~magit-branch-spinout~. #3794.
174224
175225 - Added new option ~magit-worktree-read-directory-name-function~. #3820
176226
177 - TODO Added basic support for libgit2. #3841
227 - Basic optional support for ~libgit2~ was added, but because so few
228 functions are currently implemented using that library, opting in
229 currently has almost no effect. #3841
178230
179231 - ~git bisect~ is now run asynchronously. #3802
232
233 - ~magit-bisect~ now supports specifying alternate terms. The new
234 infixes and suffix related to this functionality are disabled by
235 default.
180236
181237 - ~magit-branch-or-commit-at-point~ now falls back to an abbreviated
182238 hash instead of something like "master~2", because the latter often
330386 available from the diff transients by default. To enable it use
331387 "C-x l" in those transients. #4056
332388
389 - Added new command ~magit-reset-keep~. 0ea8b0ef6
390
391 - Added new option ~magit-reshelve-since-committer-only~. #4101
392
393 - Added new command ~magit-commit-absorb~ as an alternative to
394 ~magit-commit-autofixup~. 9423edc0b
395
396 - Added new option ~magit-status-use-buffer-arguments~. #4046
397
398 - Added new command ~magit-project-status~. #4173
399
400 - Added new variable ~magit-process-extreme-logging~ for debugging
401 purposes. #4217
402
403 - Taught Isearch and Swiper how to expand Magit sections when the
404 current match is inside a hidden section and how to close sections
405 again. #3999
406
407 - Added new command ~magit-commit-absorb-modules~. 10b4bec53
408
409 - Added new transient command ~magit-shortlog~. #4262
410
411 - Added new command ~magit-generate-changelog~. c5e118111
412
413 - The name of the main branch is no longer hard-coded to "master".
414 Now we use the value of ~init.defaultBranch~ if that is set and the
415 named branch exists. If not, then some other names that are
416 commonly used for the main branch are tried as a potential fallback.
417 c4494ac0b
418
419 - Added new option ~magit-diff-extra-stat-arguments~. 1bd4fe26e
420
421 - Added support for ~git-credential-manager-core~. #4318
422
423 - The name of the upstream remote is no longer hard-code to "origin".
424 See the doc-string of function ~magit-primary-remote~ to learn how to
425 customize this. f883b62fe
426
427 This release also contains numerous other improvements.
428
333429 ** Fixes since v2.90.0
334430
335431 - Bumped the minimal required version of ~git-commit~ to the correct
375471 - A regression in ~magit-log-move-to-parent~ prevented it from doing its
376472 job. #3682
377473
474 - Since v2.11.0 ~magit-log-revision-headers-format~ lines in the log
475 output (shown via ~++header~) weren't displayed properly when
476 ~--graph~ was enabled. #4129
477
378478 - ~magit-clone~ didn't run ~magit-credential-hook~. #3683
379479
380480 - ~magit-list-repositories~ failed if one of the repositories that it
460560 - Modifying a file, marking it with a "skip-worktree" or "assume
461561 unchanged" bit, and then modifying it again triggered a failure in
462562 ~magit-wip-commit-worktree~. #4037
563
564 - ~magit-abbrev-length~ returned an incorrect result when
565 ~core.abbrev~ was explicitly set to "auto".
566
567 - Calling ~magit-status~ in a repository with a corrupt Git
568 configuration didn't propagate the error and instead preseted the
569 directory as though it was uninitialized. #4337
570
571 - When the status buffer is not shown in any buffer but point is on
572 a hunk, and editing and saving the respective file causes, that
573 hunk to disappear or change, then Magit ended up changing point
574 in the file-visiting buffer. #4196
463575
464576 - Various bug fixes to
465577 ~magit-branch-delete~ (3e73ff19d),
492604 ~magit-stash-drop~ (a4972766a),
493605 ~magit-ignore-submodules-p~ (a7699f868),
494606 ~magit-log-propertize-keywords~ (ac1ee3df5),
495
496 This release also contains other minor improvements, bug fixes, typo
497 fixes, and documentation fixes.
607 and then I stopped adding to this list.
608
609 This release also contains numerous other bug fixes, typo fixes, and
610 documentation fixes.
611
612 * Authors
613
614 1001 Jonas Bernoulli
615 120 Kyle Meyer
616 10 Basil L. Contovounesios
617 9 Noam Postavsky
618 5 Vladimir Panteleev
619 4 Damien Cassou
620 4 Daniel Martín
621 4 Sam Cedarbaum
622 4 Štěpán Němec
623 3 Adam Porter
624 3 Benjamin Motz
625 3 Kévin Le Gouguec
626 2 Alban Gruin
627 2 Allen Li
628 2 Bastian Beischer
629 2 Clément Pit-Claudel
630 2 Daniel Fleischer
631 2 Evan Torrie
632 2 Ingmar Sittl
633 2 Leo Vivier
634 2 Martin Polden
635 2 Naoya Yamashita
636 2 Phil Sainty
637 2 Philipp Stephani
638 2 Radon Rosborough
639 2 Ryan C. Thompson
640 2 Szunti
641 2 Tassilo Horn
642 2 Thierry Volpiatto
643 2 Troy Hinckley
644 2 zilongshanren
645 1 Adam Kruszewski
646 1 Adam Spiers
647 1 Alexander Miller
648 1 Andrew Eggenberger
649 1 Andrew Psaltis
650 1 Andrew Schwartzmeyer
651 1 Arnau Roig Ninerola
652 1 Ashlynn Anderson
653 1 Ben North
654 1 Brian Leung
655 1 Dan Davison
656 1 Danny Zhu
657 1 David Ellison
658 1 Dominique Quatravaux
659 1 Eric
660 1 Fritz Grabo
661 1 Gregory Heytings
662 1 Hussein Ait-Lahcen
663 1 Ian Milligan
664 1 Ilya Grigoriev
665 1 Johann Klähn
666 1 Johannes Altmanninger
667 1 Jonas Galvão Xavier
668 1 Jonathan Arnett
669 1 Jonathan del Strother
670 1 Jordan Galby
671 1 Josh Elsasser
672 1 Justin Guenther
673 1 Keshav Kini
674 1 Kevin Brubeck Unhammer
675 1 Kevin J. Foley
676 1 Knut Olav Bøhmer
677 1 Magnus Malm
678 1 Mario Rodas
679 1 Martin Joerg
680 1 Matthew Kraai
681 1 Maxim Cournoyer
682 1 Michael Griffiths
683 1 Ola x Nilsson
684 1 Pancho Horrillo
685 1 Philipp Fehre
686 1 Pritam Baral
687 1 Roey Darwish Dror
688 1 Sean Whitton
689 1 Simon Pintarelli
690 1 Steve Purcell
691 1 Thomas Fini Hansen
692 1 Topi Miettinen
693 1 Tsuyoshi Kitamoto
694 1 Vitaly Ostashov
695 1 Vladimir Sedach
696 1 Wojciech Siewierski
697 1 Yann Herklotz
698 1 Ynilu
699 1 Zhu Zihao
700 1 zakora
11 :PREAMBLE:
22 #+AUTHOR: Jonas Bernoulli
33 #+EMAIL: jonas@bernoul.li
4 #+DATE: 2015-2020
4 #+DATE: 2015-2021
55 #+LANGUAGE: en
66
77 #+TEXINFO_DIR_CATEGORY: Emacs
88 #+TEXINFO_DIR_TITLE: Magit-Section: (magit-section).
99 #+TEXINFO_DIR_DESC: Use Magit sections in your own packages.
10 #+SUBTITLE: for version 2.90.1 (v2.90.1-948-ge293416ce+1)
10 #+SUBTITLE: for version 3.0.0
1111
1212 #+TEXINFO_DEFFN: t
1313 #+OPTIONS: H:4 num:3 toc:2
2525 can use sections in your own packages.
2626
2727 #+TEXINFO: @noindent
28 This manual is for Magit-Section version 2.90.1 (v2.90.1-948-ge293416ce+1).
28 This manual is for Magit-Section version 3.0.0.
2929
3030 #+BEGIN_QUOTE
31 Copyright (C) 2015-2020 Jonas Bernoulli <jonas@bernoul.li>
31 Copyright (C) 2015-2021 Jonas Bernoulli <jonas@bernoul.li>
3232
3333 You can redistribute this document and/or modify it under the terms
3434 of the GNU General Public License as published by the Free Software
6161
6262 - Function: magit-insert-section [name] (type &optional value hide) &rest body
6363
64 Insert a section at point.
65
66 TYPE is the section type, a symbol. Many commands that act on
67 the current section behave differently depending on that type.
68 Like functions and variables, TYPE must be prefixed with the
69 package name. (For historic reasons the types used by Magit
70 and Forge do not use a package prefix.)
71
72 Optional VALUE is the value of the section, usually a string
73 that is required when acting on the section.
64 Create a section object of type CLASS, storing VALUE in its
65 ~value~ slot, and insert the section at point. CLASS is a
66 subclass of `magit-section' or has the form ~(eval FORM)~, in
67 which case FORM is evaluated at runtime and should return a
68 subclass. In other places a sections class is oftern referred
69 to as its "type".
70
71 Many commands behave differently depending on the class of the
72 current section and sections of a certain class can have their
73 own keymap, which is specified using the `keymap' class slot.
74 The value of that slot should be a variable whose value is a
75 keymap.
76
77 For historic reasons Magit and Forge in most cases use symbols
78 as CLASS that don't actually identify a class and that lack the
79 appropriate package prefix. This works due to some undocumented
80 kludges, which are not available to other packages.
7481
7582 When optional HIDE is non-nil collapse the section body by
7683 default, i.e. when first creating the section, but not when
95102 of the partially inserted section. This can happen when creating
96103 a section by washing Git's output and Git didn't actually output
97104 anything this time around.
98
99 For historic reasons, if a variable ~magit-TYPE-section-map~
100 or ~forge-TYPE-section-map~ exists, then use that as the
101 text-property keymap~ of all text belonging to the section (but
102 this may be overwritten in subsections). TYPE can also have the
103 form ~(eval FORM)~ in which case FORM is evaluated at runtime.
104105
105106 - Function: magit-insert-heading &rest args
106107
253254 :END:
254255
255256 #+BEGIN_QUOTE
256 Copyright (C) 2015-2020 Jonas Bernoulli <jonas@bernoul.li>
257 Copyright (C) 2015-2021 Jonas Bernoulli <jonas@bernoul.li>
257258
258259 You can redistribute this document and/or modify it under the terms
259260 of the GNU General Public License as published by the Free Software
77
88 @copying
99 @quotation
10 Copyright (C) 2015-2020 Jonas Bernoulli <jonas@@bernoul.li>
10 Copyright (C) 2015-2021 Jonas Bernoulli <jonas@@bernoul.li>
1111
1212 You can redistribute this document and/or modify it under the terms
1313 of the GNU General Public License as published by the Free Software
3030 @finalout
3131 @titlepage
3232 @title Magit-Section Developer Manual
33 @subtitle for version 2.90.1 (v2.90.1-948-ge293416ce+1)
33 @subtitle for version 3.0.0
3434 @author Jonas Bernoulli
3535 @page
3636 @vskip 0pt plus 1filll
5353 can use sections in your own packages.
5454
5555 @noindent
56 This manual is for Magit-Section version 2.90.1 (v2.90.1-948-ge293416ce+1).
56 This manual is for Magit-Section version 3.0.0.
5757
5858 @quotation
59 Copyright (C) 2015-2020 Jonas Bernoulli <jonas@@bernoul.li>
59 Copyright (C) 2015-2021 Jonas Bernoulli <jonas@@bernoul.li>
6060
6161 You can redistribute this document and/or modify it under the terms
6262 of the GNU General Public License as published by the Free Software
9999
100100 @defun magit-insert-section [name] (type &optional value hide) &rest body
101101
102 Insert a section at point.
103
104 TYPE is the section type, a symbol. Many commands that act on
105 the current section behave differently depending on that type.
106 Like functions and variables, TYPE must be prefixed with the
107 package name. (For historic reasons the types used by Magit
108 and Forge do not use a package prefix.)
109
110 Optional VALUE is the value of the section, usually a string
111 that is required when acting on the section.
102 Create a section object of type CLASS, storing VALUE in its
103 @code{value} slot, and insert the section at point. CLASS is a
104 subclass of `magit-section' or has the form @code{(eval FORM)}, in
105 which case FORM is evaluated at runtime and should return a
106 subclass. In other places a sections class is oftern referred
107 to as its "type".
108
109 Many commands behave differently depending on the class of the
110 current section and sections of a certain class can have their
111 own keymap, which is specified using the `keymap' class slot.
112 The value of that slot should be a variable whose value is a
113 keymap.
114
115 For historic reasons Magit and Forge in most cases use symbols
116 as CLASS that don't actually identify a class and that lack the
117 appropriate package prefix. This works due to some undocumented
118 kludges, which are not available to other packages.
112119
113120 When optional HIDE is non-nil collapse the section body by
114121 default, i.e. when first creating the section, but not when
133140 of the partially inserted section. This can happen when creating
134141 a section by washing Git's output and Git didn't actually output
135142 anything this time around.
136
137 For historic reasons, if a variable @code{magit-TYPE-section-map}
138 or @code{forge-TYPE-section-map} exists, then use that as the
139 text-property keymap~ of all text belonging to the section (but
140 this may be overwritten in subsections). TYPE can also have the
141 form @code{(eval FORM)} in which case FORM is evaluated at runtime.
142143 @end defun
143144
144145 @defun magit-insert-heading &rest args
11 :PREAMBLE:
22 #+AUTHOR: Jonas Bernoulli
33 #+EMAIL: jonas@bernoul.li
4 #+DATE: 2015-2020
4 #+DATE: 2015-2021
55 #+LANGUAGE: en
66
77 #+TEXINFO_DIR_CATEGORY: Emacs
88 #+TEXINFO_DIR_TITLE: Magit: (magit).
99 #+TEXINFO_DIR_DESC: Using Git from Emacs with Magit.
10 #+SUBTITLE: for version 2.90.1 (v2.90.1-954-g509e97b7+1)
10 #+SUBTITLE: for version 3.0.0
1111
1212 #+TEXINFO_DEFFN: t
1313 #+OPTIONS: H:4 num:3 toc:2
2424 Magit and Git itself deserve to be called porcelains.
2525
2626 #+TEXINFO: @noindent
27 This manual is for Magit version 2.90.1 (v2.90.1-954-g509e97b7+1).
27 This manual is for Magit version 3.0.0.
2828
2929 #+BEGIN_QUOTE
30 Copyright (C) 2015-2020 Jonas Bernoulli <jonas@bernoul.li>
30 Copyright (C) 2015-2021 Jonas Bernoulli <jonas@bernoul.li>
3131
3232 You can redistribute this document and/or modify it under the terms
3333 of the GNU General Public License as published by the Free Software
190190 with the following content before running ~make~:
191191
192192 #+BEGIN_SRC makefile
193 LOAD_PATH = -L /path/to/magit/lisp
194 LOAD_PATH += -L /path/to/dash
195 LOAD_PATH += -L /path/to/transient
196 LOAD_PATH += -L /path/to/with-editor
193 LOAD_PATH = -L ~/.emacs.d/site-lisp/magit/lisp
194 LOAD_PATH += -L ~/.emacs.d/site-lisp/dash
195 LOAD_PATH += -L ~/.emacs.d/site-lisp/transient/lisp
196 LOAD_PATH += -L ~/.emacs.d/site-lisp/with-editor
197197 #+END_SRC
198198
199199 Finally add this to your init file:
208208 "~/.emacs.d/site-lisp/magit/Documentation/"))
209209 #+END_SRC
210210
211 Of course if you installed the dependencies manually as well, then
212 you have to tell Emacs about them too, by prefixing the above with:
213
214 #+BEGIN_SRC emacs-lisp
215 (add-to-list 'load-path "~/.emacs.d/site-lisp/dash")
216 (add-to-list 'load-path "~/.emacs.d/site-lisp/transient/lisp")
217 (add-to-list 'load-path "~/.emacs.d/site-lisp/with-editor")
218 #+END_SRC
219
211220 Note that you have to add the ~lisp~ subdirectory to the ~load-path~, not
212221 the top-level of the repository, and that elements of ~load-path~ should
213222 not end with a slash, while those of ~Info-directory-list~ should.
281290 if you do that, then you should commit all uncommitted changes before
282291 proceeding.
283292
284 To display information about the current Git repository, type ~M-x
285 magit-status RET~. You will be using this command a lot, and should
286 therefore give it a global key binding. This is what we recommend:
287
288 #+BEGIN_SRC emacs-lisp
289 (global-set-key (kbd "C-x g") 'magit-status)
290 #+END_SRC
293 Type ~C-x g~ to display information about the current Git repository in
294 a dedicated buffer, called the status buffer.
291295
292296 Most Magit commands are commonly invoked from the status buffer. It
293297 can be considered the primary interface for interacting with Git using
339343
340344 Now two new buffers appear. One is for writing the commit message,
341345 the other shows a diff with the changes that you are about to
342 committed. Write a message and then type ~C-c C-c~ to actually create
346 commit. Write a message and then type ~C-c C-c~ to actually create
343347 the commit.
344348
345349 You probably don't want to push the commit you just created because
350354 push-remote is not configured yet, then you would first be prompted
351355 for the remote to push to.)
352356
353 So far we have mentioned the commit, push, and log transient prefix
354 commands. These are probably among the transients you will be using
355 the most, but many others exist. To show a transient that lists all
356 other transients (as well as the various apply commands and some other
357 essential commands), type ~h~. Try a few.
358
359 The key bindings in that transient correspond to the bindings in Magit
357 So far we have mentioned the commit, push, and log menu commands.
358 These are probably among the menus you will be using the most, but
359 many others exist. To show a menu that lists all other menus (as well
360 as the various apply commands and some other essential commands), type
361 ~h~. Try a few. (Such menus are also called "transient prefix
362 commands" or just "transients".)
363
364 The key bindings in that menu correspond to the bindings in Magit
360365 buffers, including but not limited to the status buffer. So you could
361 type ~h d~ to bring up the diff transient, but once you remember that
362 "d" stands for "diff", you would usually do so by just typing ~d~. But
363 this "prefix of prefixes" is useful even once you have memorized all
364 the bindings, as it can provide easy access to Magit commands from
365 non-Magit buffers. You should create a global key binding for this
366 command too:
367
368 #+BEGIN_SRC emacs-lisp
369 (global-set-key (kbd "C-x M-g") 'magit-dispatch)
370 #+END_SRC
371
372 In the same vein, you might also want to enable ~global-magit-file-mode~
373 to get some more Magit key bindings in regular file-visiting buffers
374 (see [[*Minor Mode for Buffers Visiting Files]]).
366 type ~h d~ to bring up the diff menu, but once you remember that "d"
367 stands for "diff", you would usually do so by just typing ~d~. But this
368 "prefix of prefixes" is useful even once you have memorized all the
369 bindings, as it can provide easy access to Magit commands from
370 non-Magit buffers. The global binding is ~C-x M-g~.
371
372 In file visiting buffers ~C-c M-g~ brings up a similar menu featuring
373 commands that act on just the visited file, see [[*Commands for Buffers
374 Visiting Files]].
375375
376376 It is not necessary that you do so now, but if you stick with Magit,
377377 then it is highly recommended that you read the next section too.
644644 by adding a hook, like so:
645645
646646 #+BEGIN_SRC emacs-lisp
647 (add-hook 'after-save-hook 'magit-after-save-refresh-status t)
647 (with-eval-after-load 'magit-mode
648 (add-hook 'after-save-hook 'magit-after-save-refresh-status t))
648649 #+END_SRC
649650
650651 Automatically refreshing Magit buffers ensures that the displayed
14831484
14841485 - ~delete-pr-remote~ When deleting a branch that was created from a
14851486 pull-request and if no other branches still exist on that
1486 remote, then `magit-branch-delete' offers to delete the remote
1487 remote, then ~magit-branch-delete~ offers to delete the remote
14871488 as well. This should be safe because it only happens if no
14881489 other refs exist in the remotes namespace, and you can recreate
14891490 the remote if necessary.
14951496 to confirm by accepting the default (or selecting another).
14961497 This action only concerns the deletion of multiple stashes at
14971498 once.
1499
1500 - Publishing:
1501
1502 - ~set-and-push~ When pushing to the upstream or the push-remote
1503 and that isn't actually configured yet, then the user can first
1504 set the target. If s/he confirms the default too quickly, then
1505 s/he might end up pushing to the wrong branch and if the remote
1506 repository is configured to disallow fixing such mistakes, then
1507 that can be quite embarrassing and annoying.
14981508
14991509 - Edit published history:
15001510
25332543
25342544 Show log for all references and ~HEAD~.
25352545
2536
2537 Two additional commands that show the log for the file or blob that
2538 is being visited in the current buffer exists, see [[*Minor Mode for
2539 Buffers Visiting Files]]. The command ~magit-cherry~ also shows a log,
2540 see [[*Cherries]].
2546 Two additional commands that show the log for the file or blob that is
2547 being visited in the current buffer exists, see [[*Commands for Buffers
2548 Visiting Files]]. The command ~magit-cherry~ also shows a log, see
2549 [[*Cherries]].
25412550
25422551 *** Refreshing Logs
25432552
29492958 Show all diffs of a stash in a buffer.
29502959
29512960 Two additional commands that show the diff for the file or blob that
2952 is being visited in the current buffer exists, see [[*Minor Mode for
2961 is being visited in the current buffer exists, see [[*Commands for
29532962 Buffers Visiting Files]].
29542963
29552964 *** Refreshing Diffs
32203229 hunk-internal region only lose their distinct background color or
32213230 also the foreground color. Whether the outside of the region is
32223231 dimmed at all depends on ~magit-diff-highlight-hunk-region-functions~.
3232
3233 - User Option: magit-diff-extra-stat-arguments
3234
3235 This option specifies additional arguments to be used alongside
3236 ~--stat~.
3237
3238 The value is a list of zero or more arguments or a function that
3239 takes no argument and returns such a list. These arguments are
3240 allowed here: ~--stat-width~, ~--stat-name-width~,
3241 ~--stat-graph-width~ and ~--compact-summary~. Also see [[man:git-diff]]
32233242
32243243 *** Revision Buffer
32253244
36603679
36613680 Bisecting a bug means to find the commit that introduced it.
36623681 This command starts such a bisect session by asking for a known
3663 good and a bad commit.
3682 good commit and a known bad commit. If you're bisecting a change
3683 that isn't a regression, you can select alternate terms that are
3684 conceptually more fitting than "bad" and "good", but the infix
3685 arguments to do so are disabled by default.
36643686
36653687 - Key: B s, magit-bisect-run
36663688
36783700
36793701 Mark the current commit as good. Use this after you have asserted
36803702 that the commit does not contain the bug in question.
3703
3704 - Key: B m, magit-bisect-mark
3705
3706 Mark the current commit with one of the bisect terms. This command
3707 provides an alternative to ~magit-bisect-bad~ and
3708 ~magit-bisect-good~ and is useful when using terms other than "bad"
3709 and "good". This suffix is disabled by default.
36813710
36823711 - Key: B k, magit-bisect-skip
36833712
38073836 Also see [[man:git-blame]]
38083837
38093838 To start blaming invoke the ~magit-file-dispatch~ transient prefix
3810 command by pressing ~C-c M-g~. (This is only the default binding and
3811 the recommended binding is ~C-c g~. Also neither binding may be
3812 available if you disabled ~global-magit-file-mode~. Also see [[*Minor
3813 Mode for Buffers Visiting Files]].)
3839 command by pressing ~C-c M-g~.
38143840
38153841 The blaming suffix commands can be invoked from the dispatch
38163842 transient. However if you want to set an infix argument, then you
43504376 Whether to ask to stage all unstaged changes when committing and nothing is
43514377 staged.
43524378
4379 - User Option: magit-commit-show-diff
4380
4381 Whether the relevant diff is automatically shown when committing.
4382
43534383 - User Option: magit-commit-extend-override-date
43544384
43554385 Whether using ~magit-commit-extend~ changes the committer date.
43664396 ~magit-commit-squash~ and ~magit-commit-fixup~. The "instant" variants
43674397 always require confirmation because making an error while using
43684398 those is harder to recover from.
4399
4400 - User Option magit-post-commit-hook
4401
4402 Hook run after creating a commit without the user editing a message.
4403
4404 This hook is run by ~magit-refresh~ if ~this-command~ is a member
4405 of ~magit-post-stage-hook-commands~. This only includes commands
4406 named ~magit-commit-*~ that do *not* require that the user edits
4407 the commit message in a buffer.
4408
4409 Also see ~git-commit-post-finish-hook~.
43694410
43704411 *** Editing Commit Messages
43714412
47224763 - User Option: magit-branch-direct-configure
47234764
47244765 This option controls whether the transient command ~magit-branch~ can
4725 be used directly change the values Git variables. This defaults to
4726 ~t~ (to avoid changing key bindings). When set to ~nil~, then no
4766 be used to directly change the values of Git variables. This defaults
4767 to ~t~ (to avoid changing key bindings). When set to ~nil~, then no
47274768 variables are displayed by that transient command, and its suffix
47284769 command ~magit-branch-configure~ has to be used instead to view and
47294770 change branch related variables.
47684809
47694810 - Key: b c, magit-branch-and-checkout
47704811
4771 This command creates a new branch like ~magit-branch~, but then also
4772 checks it out.
4812 This command creates a new branch like ~magit-branch-create~, but then
4813 also checks it out.
47734814
47744815 Also see option ~magit-branch-prefer-remote-upstream~.
47754816
48614902 - User Option: magit-branch-read-upstream-first
48624903
48634904 When creating a branch, whether to read the upstream branch before
4864 the name of the branch that is to be created. The default is ~nil~,
4905 the name of the branch that is to be created. The default is ~t~,
48654906 and I recommend you leave it at that.
48664907
48674908 - User Option: magit-branch-prefer-remote-upstream
59355976
59365977 Reset the ~HEAD~, index, and working tree to some commit read from the
59375978 user and defaulting to the commit at point.
5979
5980 - Key: X k, magit-reset-keep
5981
5982 Reset the ~HEAD~, index, and working tree to some commit read from the
5983 user and defaulting to the commit at point. Uncommitted changes are
5984 kept as-is.
59385985
59395986 - Key: X i, magit-reset-index
59405987
63756422
63766423 This command pushes a tag to another repository.
63776424
6425 One of the infix arguments, ~--force-with-lease~, deserves a word of
6426 caution. It is passed without a value, which means "permit a force
6427 push as long as the remote-tracking branches match their counterparts
6428 on the remote end". If you've set up a tool to do automatic fetches
6429 (Magit itself does not provide such functionality), using
6430 ~--force-with-lease~ can be dangerous because you don't actually
6431 control or know the state of the remote-tracking refs. In that case,
6432 you should consider setting ~push.useForceIfIncludes~ to ~true~
6433 (available since Git 2.30).
6434
63786435 Two more push commands exist, which by default are not available from
63796436 the push transient. See their doc-strings for instructions on how to
63806437 add them to the transient.
63906447 ~branch.<branch>.remote~, ~branch.<branch>.merge~, and
63916448 ~remote.<remote>.push~.
63926449
6450 If you add this suffix to a transient prefix without explicitly
6451 specifying the description, then an attempt is made to predict
6452 what this command will do. For example:
6453
6454 #+BEGIN_SRC emacs-lisp
6455 (transient-insert-suffix 'magit-push \"p\"
6456 '(\"i\" magit-push-implicitly))"
6457 #+END_SRC
6458
63936459 - Command: magit-push-to-remote remote args
63946460
63956461 This command pushes to the remote REMOTE without using an explicit
64946560 - Key: t t, magit-tag-create
64956561
64966562 This command creates a new tag with the given NAME at REV. With a
6497 prefix argument it creates an annotate tag.
6563 prefix argument it creates an annotated tag.
64986564
64996565 - Key: t r, magit-tag-release
65006566
6501 This commands creates an annotated release tag. It assumes that
6502 release tags match ~magit-release-tag-regexp~.
6567 This commands creates a release tag. It assumes that release tags
6568 match ~magit-release-tag-regexp~.
65036569
65046570 First it prompts for the name of the new tag using the highest
65056571 existing tag as initial input and leaving it to the user to
65086574 ~v1.2.3-custom.1~), you can set the ~magit-release-tag-regexp~ and
65096575 ~magit-tag-version-regexp-alist~ variables.
65106576
6511 Then it prompts for the message of the new tag. The proposed tag
6512 message is based on the message of the highest tag, provided that
6513 that contains the corresponding version string and substituting the
6514 new version string for that. Otherwise it proposes something like
6515 "Foo-Bar 1.2.3", given, for example, a TAG "v1.2.3" and a repository
6516 located at something like "/path/to/foo-bar".
6517
6518 Then it calls "git tag --annotate --sign -m MSG TAG" to create the
6519 tag, regardless of whether these arguments are enabled in the
6520 transient. Finally it shows the refs buffer to let the user quickly
6521 review the result.
6577 If ~--annotate~ is enabled then it prompts for the message of the
6578 new tag. The proposed tag message is based on the message of the
6579 highest tag, provided that that contains the corresponding version
6580 string and substituting the new version string for that. Otherwise
6581 it proposes something like "Foo-Bar 1.2.3", given, for example, a
6582 TAG "v1.2.3" and a repository located at something like
6583 "/path/to/foo-bar".
65226584
65236585 - Key: t k, magit-tag-delete
65246586
66106672 The command ~magit-list-submodules~ displays a list of the current
66116673 repository's submodules in a separate buffer. It's also possible to
66126674 display information about submodules directly in the status buffer of
6613 the super-repository by adding ~magit-insert-submodules~ to the hook
6675 the super-repository by adding ~magit-insert-modules~ to the hook
66146676 ~magit-status-sections-hook~ as described in [[*Status Module Sections]].
66156677
66166678 - Command: magit-list-submodules
66336695 ~default-directory~ bound to the toplevel of its working tree. It
66346696 has to return a string to be inserted or nil. PROPS is an alist
66356697 that supports the keys ~:right-align~ and ~:pad-right~.
6636
6637 - Function: magit-insert-submodules
6638
6639 Insert sections for all submodules. For each section insert the
6640 path, the branch, and the output of ~git describe --tags~,
6641 or, failing that, the abbreviated HEAD commit hash.
6642
6643 Press ~RET~ on such a submodule section to show its own status buffer.
6644 Press ~RET~ on the "Modules" section to display a list of submodules
6645 in a separate buffer. This shows additional information not
6646 displayed in the super-repository's status buffer.
66476698
66486699 *** Submodule Transient
66496700
68056856 major-modes derive from ~magit-mode~. There are other common commands
68066857 beside the ones below, but these didn't fit well anywhere else.
68076858
6808 - Key: M-w, magit-copy-section-value
6859 - Key: C-w, magit-copy-section-value
68096860
68106861 This command saves the value of the current section to the
68116862 ~kill-ring~, and, provided that the current section is a commit,
68186869
68196870 When the region is active, this command saves that to the
68206871 ~kill-ring~, like ~kill-ring-save~ would, instead of behaving as
6821 described above. If a prefix argument is used and the region is
6822 within a hunk, it strips the outer diff marker column before saving
6823 the text.
6824
6825 - Key: C-w, magit-copy-buffer-revision
6872 described above. If a prefix argument is used and the region is
6873 within a hunk, then it strips the diff marker column and keeps
6874 only either the added or removed lines, depending on the sign of
6875 the prefix argument.
6876
6877 - Key: M-w, magit-copy-buffer-revision
68266878
68276879 This command saves the revision being displayed in the current buffer
68286880 to the ~kill-ring~ and also pushes it to the ~magit-revision-stack~. It
70737125
70747126 Mode-line lighter for ~magit-wip-initial-backup-mode~.
70757127
7076 ** Minor Mode for Buffers Visiting Files
7077
7078 The minor-mode ~magit-file-mode~ enables certain Magit features in
7079 file-visiting buffers belonging to a Git repository. The globalized
7080 variant ~global-magit-file-mode~ enables the local mode in all such
7081 buffers. It is enabled by default. Currently the local mode only
7082 establishes a few key bindings, but this might be extended in the
7083 future.
7084
7085 - User Option: global-magit-file-mode
7086
7087 Whether to establish certain Magit key bindings in all file-visiting
7088 buffers belonging to any Git repository. This is enabled by default.
7089 This globalized mode turns on the local minor-mode ~magit-file-mode~
7090 in all suitable buffers.
7091
7092 - Variable: magit-file-mode-map
7093
7094 This keymap is used by the local minor-mode ~magit-file-mode~ and
7095 establishes the key bindings described below.
7096
7097 Note that the default binding for ~magit-file-dispatch~ is very
7098 cumbersome to use and that we recommend that you add a better
7099 binding.
7100
7101 Instead of ~C-c M-g~ I would have preferred to use ~C-c g~ because (1)
7102 it is similar to ~C-x g~ (the recommended global binding for
7103 ~~magit-status~), (2) we cannot use ~C-c C-g~ because we have been
7104 recommending that that be bound to ~magit-dispatch~ for a long time,
7105 (3) we cannot use ~C-x C-g~ because that is a convenient way of
7106 aborting the incomplete key sequence ~C-x~, and most importantly (4)
7107 it would make it much easier to type the next key (a suffix binding)
7108 because most of those are letters.
7109
7110 For example ~C-c g b~ is much easier to type than ~C-c M-g b~. For
7111 suffix bindings that use uppercase letters, the default is just
7112 horrible—having to use e.g. ~C-c M-g B~ (~Control+c Meta+g Shift+b~)
7113 would drive anyone up the walls (or to Vim).
7114
7115 However ~C-c LETTER~ bindings are reserved for users (see
7116 [[info:elisp#Key Binding Conventions]]). Packages are forbidden from
7117 using those. Doing so anyway is considered heresy. Therefore if
7118 you want a better binding, you have to add it yourself:
7119
7120 #+BEGIN_SRC emacs-lisp
7121 (define-key magit-file-mode-map
7122 (kbd "C-c g") 'magit-file-dispatch)
7123 #+END_SRC
7128 ** Commands for Buffers Visiting Files
7129
7130 Magit defines a few global key bindings unless the user sets
7131 ~magit-define-global-key-bindings~ to ~nil~. This includes binding ~C-c
7132 M-g~ to ~magit-file-dispatch~. ~C-c g~ would be a much better binding
7133 but the ~C-c <letter>~ namespace is reserved for users, meaning that
7134 packages are not allowed to use it. If you want to use ~C-c g~, then
7135 you have to add that binding yourself. Also see [[*Default Bindings]]
7136 and [[info:elisp#Key Binding Conventions]].
7137
7138 If you want a better binding, you have to add it yourself:
7139
7140 #+BEGIN_SRC emacs-lisp
7141 (global-set-key (kbd "C-c g") 'magit-file-dispatch)
7142 #+END_SRC
71247143
71257144 The key bindings shown below assume that you have not improved the
71267145 binding for ~magit-file-dispatch~.
71297148
71307149 This transient prefix command binds the following suffix commands
71317150 and displays them in a temporary buffer until a suffix is invoked.
7151
7152 When invoked in a buffer that does not visit a file, then it falls
7153 back to regular ~magit-dispatch~.
71327154
71337155 - Key: C-c M-g s, magit-stage-file
71347156
75687590 the diff, which is useful because it increases the odds that you spot
75697591 potential issues.
75707592
7571 **** The Built-In VC Package
7572 :PROPERTIES:
7573 :NONODE: t
7574 :END:
7575
7576 Emacs comes with a version control interface called "VC", see
7577 [[info:emacs#Version Control]]. It is enabled be default, and if you don't
7578 use it in addition to Magit, then you should disable it to keep it
7579 from performing unnecessary work:
7580
7581 #+BEGIN_SRC emacs-lisp
7582 (setq vc-handled-backends nil)
7583 #+END_SRC
7584
7585 You can also disable its use for Git but keep using it when using
7586 another version control system:
7587
7588 #+BEGIN_SRC emacs-lisp
7589 (setq vc-handled-backends (delq 'Git vc-handled-backends))
7590 #+END_SRC
7591
75927593 **** Microsoft Windows Performance
75937594
75947595 In order to update the status buffer, ~git~ has to be run a few dozen
76317632
76327633 On Catalina, and potentially other macOS releases, there may be a
76337634 performance problem where any action takes 20 times longer on Darwin
7634 than on Linux. This can be fixed by setting ~magit-git-executable~ to
7635 the absolute path of the ~git~ executable, instead of relying on
7636 resolving the ~$PATH~.
7635 than on Linux. This can be worked around by setting
7636 ~magit-git-executable~ to the absolute path of the ~git~ executable,
7637 instead of relying on resolving the ~$PATH~. You should not do that if
7638 you want to use Magit on remote machines using Tramp and if ~git~ is not
7639 installed in the same location on those machines.
76377640
76387641 [fn:mac1] https://lists.gnu.org/archive/html/bug-gnu-emacs/2017-04/msg00201.html
7642
7643 *** Default Bindings
7644
7645 - User Option: magit-define-global-key-bindings
7646
7647 This option controls whether some Magit commands are automatically
7648 bound in the global keymap even before Magit is used for the first
7649 time in the current session.
7650
7651 If this variable is non-nil, which it is by default, then the
7652 following bindings may be added to the global keymap.
7653
7654 | ~C-x g~ | ~magit-status~ |
7655 | ~C-x M-g~ | ~magit-dispatch~ |
7656 | ~C-c M-g~ | ~magit-file-dispatch~ |
7657
7658 These bindings may be added when ~after-init-hook~ is called.
7659 Each binding is added if and only if at that time no other key
7660 is bound to the same command and no other command is bound to
7661 the same key. In other words we try to avoid adding bindings
7662 that are unnecessary, as well as bindings that conflict with
7663 other bindings.
7664
7665 Adding the above bindings is delayed until ~after-init-hook~
7666 is called to allow users to set the variable anywhere in their
7667 init file (without having to make sure to do so before ~magit~
7668 is loaded or autoloaded) and to increase the likelihood that
7669 all the potentially conflicting user bindings have already
7670 been added.
7671
7672 Setting this variable after the hook has already been called
7673 has no effect.
7674
7675 We recommend that you bind ~C-c g~ instead of ~C-c M-g~ to
7676 ~magit-file-dispatch~. The former is a much better binding
7677 but the ~C-c <letter>~ namespace is strictly reserved for
7678 users; preventing Magit from using it by default.
7679
7680 #+BEGIN_SRC emacs-lisp
7681 (global-set-key (kbd "C-c g") 'magit-file-dispatch)
7682 #+END_SRC
7683
7684 Also see [[*Commands for Buffers Visiting Files]] and [[info:elisp#Key
7685 Binding Conventions]].
76397686
76407687 * Plumbing
76417688 ** _ :ignore:
77927839
77937840 Calls git synchronously with ARGS and then refreshes.
77947841
7795 - Function: magit-run-git-with-input input &rest args
7796
7797 Calls git synchronously with ARGS and sends it INPUT on standard
7798 input.
7799
7800 INPUT should be a buffer or the name of an existing buffer. The
7801 content of that buffer is used as the process' standard input.
7802 After the process returns a refresh is performed.
7803
7804 As a special case, INPUT may also be nil. In that case the content
7805 of the current buffer is used as standard input and *no* refresh is
7806 performed.
7807
7808 This function actually runs git asynchronously. But then it waits
7809 for the process to return, so the function itself is synchronous.
7842 - Function: magit-run-git-with-input &rest args
7843
7844 Calls git synchronously with ARGS and sends it the content of the
7845 current buffer on standard input.
7846
7847 If the current buffer's ~default-directory~ is on a remote
7848 filesystem, this function actually runs git asynchronously. But
7849 then it waits for the process to return, so the function itself is
7850 synchronous.
78107851
78117852 - Function: magit-run-git-with-logfile file &rest args
78127853
7813 Calls git synchronously with ARGS. The process' output is saved in
7854 Calls git synchronously with ARGS. The process's output is saved in
78147855 FILE. This is rarely useful and so this function might be removed
78157856 in the future.
78167857
78577898 current when this function was called (if it is a Magit buffer and
78587899 still alive), as well as the respective Magit status buffer.
78597900
7860 - Function: magit-start-git &rest args
7901 - Function: magit-start-git input &rest args
78617902
78627903 Start Git, prepare for refresh, and return the process object.
78637904
83808421 Please also use the [[*Debugging Tools]].
83818422
83828423 ** FAQ - How to ...?
8424 *** How to pronounce Magit?
8425
8426 Either ~mu[m's] git~ or ~magi{c => t}~ is fine.
8427
8428 The slogan is "It's Magit! The magical Git client", so it makes sense
8429 to pronounce Magit like magic, while taking into account that C and T
8430 do not sound the same.
8431
8432 The German "Magie" is not pronounced the same as the English "magic",
8433 so if you speak German then you can use the above rational to justify
8434 using the former pronunciation; ~Mag{ie => it}~.
8435
8436 You can also choose to use the former pronunciation just because you
8437 like it better.
8438
8439 Also see https://magit.vc/assets/videos/magic.mp4.
8440 Also see https://emacs.stackexchange.com/questions/13696.
8441
83838442 *** How to show git's output?
83848443
83858444 To show the output of recently run git commands, press ~$~ (or, if that
84598518 command ~magit-ediff-resolve~ which only shows yet-to-be resolved
84608519 conflicts.
84618520
8521 *** Should I disable VC?
8522
8523 If you don't use VC (the built-in version control interface) then
8524 you might be tempted to disable it, not least because we used to
8525 recommend that you do that.
8526
8527 We no longer recommend that you disable VC. Doing so would break
8528 useful third-party packages (such as ~diff-hl~), which depend on VC
8529 being enabled.
8530
8531 If you choose to disable VC anyway, then you can do so by changing
8532 the value of ~vc-handled-backends~.
8533
84628534 ** FAQ - Issues and Errors
84638535 *** Magit is slow
84648536
85438615 But doing so isn't good for performance. For more (overly optimistic)
85448616 information see [[info:emacs#VC Mode Line]].
85458617
8546 If you don't really care about seeing that information in the
8547 mode-line, but just don't want to see /incorrect/ information, then
8548 consider disabling VC when using Git:
8618 If you don't really care about seeing this information in the
8619 mode-line, but just don't want to see /incorrect/ information,
8620 then consider simply not displaying it in the mode-line:
85498621
85508622 #+BEGIN_SRC emacs-lisp
8551 (setq vc-handled-backends (delq 'Git vc-handled-backends))
8552 #+END_SRC
8553
8554 Or to disable it completely:
8555
8556 #+BEGIN_SRC emacs-lisp
8557 (setq vc-handled-backends nil)
8623 (setq-default mode-line-format
8624 (delete '(vc-mode vc-mode) mode-line-format))
85588625 #+END_SRC
85598626
85608627 *** A branch and tag sharing the same name breaks SOMETHING
86278694 #+END_SRC
86288695
86298696 This will actually end up using ~emacs~, not ~emacsclient~. If you do
8630 this, then can still edit the commit message but ~git-commit-mode~ won't
8631 be used and you have to exit ~emacs~ to finish the process.
8697 this, then you can still edit the commit message but ~git-commit-mode~
8698 won't be used and you have to exit ~emacs~ to finish the process.
86328699
86338700 Tautology ahead. If you want to be able to use ~emacsclient~ to connect
86348701 to a running ~emacs~ instance, even though no ~emacs~ instance is running,
87298796 :END:
87308797
87318798 #+BEGIN_QUOTE
8732 Copyright (C) 2015-2020 Jonas Bernoulli <jonas@bernoul.li>
8799 Copyright (C) 2015-2021 Jonas Bernoulli <jonas@bernoul.li>
87338800
87348801 You can redistribute this document and/or modify it under the terms
87358802 of the GNU General Public License as published by the Free Software
77
88 @copying
99 @quotation
10 Copyright (C) 2015-2020 Jonas Bernoulli <jonas@@bernoul.li>
10 Copyright (C) 2015-2021 Jonas Bernoulli <jonas@@bernoul.li>
1111
1212 You can redistribute this document and/or modify it under the terms
1313 of the GNU General Public License as published by the Free Software
3030 @finalout
3131 @titlepage
3232 @title Magit User Manual
33 @subtitle for version 2.90.1 (v2.90.1-954-g509e97b7+1)
33 @subtitle for version 3.0.0
3434 @author Jonas Bernoulli
3535 @page
3636 @vskip 0pt plus 1filll
5252 Magit and Git itself deserve to be called porcelains.
5353
5454 @noindent
55 This manual is for Magit version 2.90.1 (v2.90.1-954-g509e97b7+1).
55 This manual is for Magit version 3.0.0.
5656
5757 @quotation
58 Copyright (C) 2015-2020 Jonas Bernoulli <jonas@@bernoul.li>
58 Copyright (C) 2015-2021 Jonas Bernoulli <jonas@@bernoul.li>
5959
6060 You can redistribute this document and/or modify it under the terms
6161 of the GNU General Public License as published by the Free Software
262262 * Worktree::
263263 * Common Commands::
264264 * Wip Modes::
265 * Minor Mode for Buffers Visiting Files::
265 * Commands for Buffers Visiting Files::
266266 * Minor Mode for Buffers Visiting Blobs::
267267
268268 Submodules
286286
287287 * Safety::
288288 * Performance::
289 * Default Bindings::
289290
290291
291292 Plumbing
320321
321322 FAQ - How to @dots{}?
322323
324 * How to pronounce Magit?::
323325 * How to show git's output?::
324326 * How to install the gitman info manual?::
325327 * How to show diffs for gpg-encrypted files?::
326328 * How does branching and pushing work?::
327329 * Can Magit be used as @code{ediff-version-control-package}?::
330 * Should I disable VC@?::
328331
329332
330333 FAQ - Issues and Errors
511514 with the following content before running @code{make}:
512515
513516 @example
514 LOAD_PATH = -L /path/to/magit/lisp
515 LOAD_PATH += -L /path/to/dash
516 LOAD_PATH += -L /path/to/transient
517 LOAD_PATH += -L /path/to/with-editor
517 LOAD_PATH = -L ~/.emacs.d/site-lisp/magit/lisp
518 LOAD_PATH += -L ~/.emacs.d/site-lisp/dash
519 LOAD_PATH += -L ~/.emacs.d/site-lisp/transient/lisp
520 LOAD_PATH += -L ~/.emacs.d/site-lisp/with-editor
518521 @end example
519522
520523 Finally add this to your init file:
529532 "~/.emacs.d/site-lisp/magit/Documentation/"))
530533 @end lisp
531534
535 Of course if you installed the dependencies manually as well, then
536 you have to tell Emacs about them too, by prefixing the above with:
537
538 @lisp
539 (add-to-list 'load-path "~/.emacs.d/site-lisp/dash")
540 (add-to-list 'load-path "~/.emacs.d/site-lisp/transient/lisp")
541 (add-to-list 'load-path "~/.emacs.d/site-lisp/with-editor")
542 @end lisp
543
532544 Note that you have to add the @code{lisp} subdirectory to the @code{load-path}, not
533545 the top-level of the repository, and that elements of @code{load-path} should
534546 not end with a slash, while those of @code{Info-directory-list} should.
604616 if you do that, then you should commit all uncommitted changes before
605617 proceeding.
606618
607 To display information about the current Git repository, type @code{M-x
608 magit-status RET}. You will be using this command a lot, and should
609 therefore give it a global key binding. This is what we recommend:
610
611 @lisp
612 (global-set-key (kbd "C-x g") 'magit-status)
613 @end lisp
619 Type @code{C-x g} to display information about the current Git repository in
620 a dedicated buffer, called the status buffer.
614621
615622 Most Magit commands are commonly invoked from the status buffer. It
616623 can be considered the primary interface for interacting with Git using
662669
663670 Now two new buffers appear. One is for writing the commit message,
664671 the other shows a diff with the changes that you are about to
665 committed. Write a message and then type @code{C-c C-c} to actually create
672 commit. Write a message and then type @code{C-c C-c} to actually create
666673 the commit.
667674
668675 You probably don't want to push the commit you just created because
673680 push-remote is not configured yet, then you would first be prompted
674681 for the remote to push to.)
675682
676 So far we have mentioned the commit, push, and log transient prefix
677 commands. These are probably among the transients you will be using
678 the most, but many others exist. To show a transient that lists all
679 other transients (as well as the various apply commands and some other
680 essential commands), type @code{h}. Try a few.
681
682 The key bindings in that transient correspond to the bindings in Magit
683 So far we have mentioned the commit, push, and log menu commands.
684 These are probably among the menus you will be using the most, but
685 many others exist. To show a menu that lists all other menus (as well
686 as the various apply commands and some other essential commands), type
687 @code{h}. Try a few. (Such menus are also called "transient prefix
688 commands" or just "transients".)
689
690 The key bindings in that menu correspond to the bindings in Magit
683691 buffers, including but not limited to the status buffer. So you could
684 type @code{h d} to bring up the diff transient, but once you remember that
685 "d" stands for "diff", you would usually do so by just typing @code{d}. But
686 this "prefix of prefixes" is useful even once you have memorized all
687 the bindings, as it can provide easy access to Magit commands from
688 non-Magit buffers. You should create a global key binding for this
689 command too:
690
691 @lisp
692 (global-set-key (kbd "C-x M-g") 'magit-dispatch)
693 @end lisp
694
695 In the same vein, you might also want to enable @code{global-magit-file-mode}
696 to get some more Magit key bindings in regular file-visiting buffers
697 (see @ref{Minor Mode for Buffers Visiting Files}).
692 type @code{h d} to bring up the diff menu, but once you remember that "d"
693 stands for "diff", you would usually do so by just typing @code{d}. But this
694 "prefix of prefixes" is useful even once you have memorized all the
695 bindings, as it can provide easy access to Magit commands from
696 non-Magit buffers. The global binding is @code{C-x M-g}.
697
698 In file visiting buffers @code{C-c M-g} brings up a similar menu featuring
699 commands that act on just the visited file, see @ref{Commands for Buffers Visiting Files}.
698700
699701 It is not necessary that you do so now, but if you stick with Magit,
700702 then it is highly recommended that you read the next section too.
10341036 by adding a hook, like so:
10351037
10361038 @lisp
1037 (add-hook 'after-save-hook 'magit-after-save-refresh-status t)
1039 (with-eval-after-load 'magit-mode
1040 (add-hook 'after-save-hook 'magit-after-save-refresh-status t))
10381041 @end lisp
10391042
10401043 Automatically refreshing Magit buffers ensures that the displayed
20662069 @item
20672070 @code{delete-pr-remote} When deleting a branch that was created from a
20682071 pull-request and if no other branches still exist on that
2069 remote, then `magit-branch-delete' offers to delete the remote
2072 remote, then @code{magit-branch-delete} offers to delete the remote
20702073 as well. This should be safe because it only happens if no
20712074 other refs exist in the remotes namespace, and you can recreate
20722075 the remote if necessary.
20802083 to confirm by accepting the default (or selecting another).
20812084 This action only concerns the deletion of multiple stashes at
20822085 once.
2086 @end itemize
2087
2088
2089 @item
2090 Publishing:
2091
2092 @itemize
2093 @item
2094 @code{set-and-push} When pushing to the upstream or the push-remote
2095 and that isn't actually configured yet, then the user can first
2096 set the target. If s/he confirms the default too quickly, then
2097 s/he might end up pushing to the wrong branch and if the remote
2098 repository is configured to disallow fixing such mistakes, then
2099 that can be quite embarrassing and annoying.
20832100 @end itemize
20842101
20852102
33903407 Show log for all references and @code{HEAD}.
33913408 @end table
33923409
3393
3394 Two additional commands that show the log for the file or blob that
3395 is being visited in the current buffer exists, see @ref{Minor Mode for Buffers Visiting Files}. The command @code{magit-cherry} also shows a log,
3396 see @ref{Cherries}.
3410 Two additional commands that show the log for the file or blob that is
3411 being visited in the current buffer exists, see @ref{Commands for Buffers Visiting Files}. The command @code{magit-cherry} also shows a log, see
3412 @ref{Cherries}.
33973413
33983414 @menu
33993415 * Refreshing Logs::
39944010 @end table
39954011
39964012 Two additional commands that show the diff for the file or blob that
3997 is being visited in the current buffer exists, see @ref{Minor Mode for Buffers Visiting Files}.
4013 is being visited in the current buffer exists, see @ref{Commands for Buffers Visiting Files}.
39984014
39994015 @menu
40004016 * Refreshing Diffs::
43644380 hunk-internal region only lose their distinct background color or
43654381 also the foreground color. Whether the outside of the region is
43664382 dimmed at all depends on @code{magit-diff-highlight-hunk-region-functions}.
4383 @end defopt
4384
4385 @defopt magit-diff-extra-stat-arguments
4386
4387 This option specifies additional arguments to be used alongside
4388 @code{--stat}.
4389
4390 The value is a list of zero or more arguments or a function that
4391 takes no argument and returns such a list. These arguments are
4392 allowed here: @code{--stat-width}, @code{--stat-name-width},
4393 @code{--stat-graph-width} and @code{--compact-summary}. Also see
4394 @ifinfo
4395 @ref{git-diff,,,gitman,}.
4396 @end ifinfo
4397 @ifhtml
4398 @html
4399 the <a href="http://git-scm.com/docs/git-diff">git-diff(1)</a> manpage.
4400 @end html
4401 @end ifhtml
4402 @iftex
4403 the git-diff(1) manpage.
4404 @end iftex
43674405 @end defopt
43684406
43694407 @node Revision Buffer
49564994
49574995 Bisecting a bug means to find the commit that introduced it.
49584996 This command starts such a bisect session by asking for a known
4959 good and a bad commit.
4997 good commit and a known bad commit. If you're bisecting a change
4998 that isn't a regression, you can select alternate terms that are
4999 conceptually more fitting than "bad" and "good", but the infix
5000 arguments to do so are disabled by default.
49605001
49615002 @kindex B s
49625003 @cindex magit-bisect-run
49825023
49835024 Mark the current commit as good. Use this after you have asserted
49845025 that the commit does not contain the bug in question.
5026
5027 @kindex B m
5028 @cindex magit-bisect-mark
5029 @item @kbd{B m} @tie{}@tie{}@tie{}@tie{}(@code{magit-bisect-mark})
5030
5031 Mark the current commit with one of the bisect terms. This command
5032 provides an alternative to @code{magit-bisect-bad} and
5033 @code{magit-bisect-good} and is useful when using terms other than "bad"
5034 and "good". This suffix is disabled by default.
49855035
49865036 @kindex B k
49875037 @cindex magit-bisect-skip
51685218 @end iftex
51695219
51705220 To start blaming invoke the @code{magit-file-dispatch} transient prefix
5171 command by pressing @code{C-c M-g}. (This is only the default binding and
5172 the recommended binding is @code{C-c g}. Also neither binding may be
5173 available if you disabled @code{global-magit-file-mode}. Also see @ref{Minor Mode for Buffers Visiting Files}.)
5221 command by pressing @code{C-c M-g}.
51745222
51755223 The blaming suffix commands can be invoked from the dispatch
51765224 transient. However if you want to set an infix argument, then you
59275975 staged.
59285976 @end defopt
59295977
5978 @defopt magit-commit-show-diff
5979
5980 Whether the relevant diff is automatically shown when committing.
5981 @end defopt
5982
59305983 @defopt magit-commit-extend-override-date
59315984
59325985 Whether using @code{magit-commit-extend} changes the committer date.
59465999 always require confirmation because making an error while using
59476000 those is harder to recover from.
59486001 @end defopt
6002
6003 @itemize
6004 @item
6005 User Option magit-post-commit-hook
6006
6007 Hook run after creating a commit without the user editing a message.
6008
6009 This hook is run by @code{magit-refresh} if @code{this-command} is a member
6010 of @code{magit-post-stage-hook-commands}. This only includes commands
6011 named @code{magit-commit-*} that do @strong{not} require that the user edits
6012 the commit message in a buffer.
6013
6014 Also see @code{git-commit-post-finish-hook}.
6015 @end itemize
59496016
59506017 @node Editing Commit Messages
59516018 @subsection Editing Commit Messages
63886455 @defopt magit-branch-direct-configure
63896456
63906457 This option controls whether the transient command @code{magit-branch} can
6391 be used directly change the values Git variables. This defaults to
6392 @code{t} (to avoid changing key bindings). When set to @code{nil}, then no
6458 be used to directly change the values of Git variables. This defaults
6459 to @code{t} (to avoid changing key bindings). When set to @code{nil}, then no
63936460 variables are displayed by that transient command, and its suffix
63946461 command @code{magit-branch-configure} has to be used instead to view and
63956462 change branch related variables.
64526519 @cindex magit-branch-and-checkout
64536520 @item @kbd{b c} @tie{}@tie{}@tie{}@tie{}(@code{magit-branch-and-checkout})
64546521
6455 This command creates a new branch like @code{magit-branch}, but then also
6456 checks it out.
6522 This command creates a new branch like @code{magit-branch-create}, but then
6523 also checks it out.
64576524
64586525 Also see option @code{magit-branch-prefer-remote-upstream}.
64596526
65666633 @defopt magit-branch-read-upstream-first
65676634
65686635 When creating a branch, whether to read the upstream branch before
6569 the name of the branch that is to be created. The default is @code{nil},
6636 the name of the branch that is to be created. The default is @code{t},
65706637 and I recommend you leave it at that.
65716638 @end defopt
65726639
80078074 Reset the @code{HEAD}, index, and working tree to some commit read from the
80088075 user and defaulting to the commit at point.
80098076
8077 @kindex X k
8078 @cindex magit-reset-keep
8079 @item @kbd{X k} @tie{}@tie{}@tie{}@tie{}(@code{magit-reset-keep})
8080
8081 Reset the @code{HEAD}, index, and working tree to some commit read from the
8082 user and defaulting to the commit at point. Uncommitted changes are
8083 kept as-is.
8084
80108085 @kindex X i
80118086 @cindex magit-reset-index
80128087 @item @kbd{X i} @tie{}@tie{}@tie{}@tie{}(@code{magit-reset-index})
86658740 This command pushes a tag to another repository.
86668741 @end table
86678742
8743 One of the infix arguments, @code{--force-with-lease}, deserves a word of
8744 caution. It is passed without a value, which means "permit a force
8745 push as long as the remote-tracking branches match their counterparts
8746 on the remote end". If you've set up a tool to do automatic fetches
8747 (Magit itself does not provide such functionality), using
8748 @code{--force-with-lease} can be dangerous because you don't actually
8749 control or know the state of the remote-tracking refs. In that case,
8750 you should consider setting @code{push.useForceIfIncludes} to @code{true}
8751 (available since Git 2.30).
8752
86688753 Two more push commands exist, which by default are not available from
86698754 the push transient. See their doc-strings for instructions on how to
86708755 add them to the transient.
86808765 @code{remote.pushDefault}, @code{branch.<branch>.pushRemote},
86818766 @code{branch.<branch>.remote}, @code{branch.<branch>.merge}, and
86828767 @code{remote.<remote>.push}.
8768
8769 If you add this suffix to a transient prefix without explicitly
8770 specifying the description, then an attempt is made to predict
8771 what this command will do. For example:
8772
8773 @lisp
8774 (transient-insert-suffix 'magit-push \"p\"
8775 '(\"i\" magit-push-implicitly))"
8776 @end lisp
86838777 @end deffn
86848778
86858779 @cindex magit-push-to-remote remote args
88388932 * Worktree::
88398933 * Common Commands::
88408934 * Wip Modes::
8841 * Minor Mode for Buffers Visiting Files::
8935 * Commands for Buffers Visiting Files::
88428936 * Minor Mode for Buffers Visiting Blobs::
88438937 @end menu
88448938
88728966 @item @kbd{t t} @tie{}@tie{}@tie{}@tie{}(@code{magit-tag-create})
88738967
88748968 This command creates a new tag with the given NAME at REV@. With a
8875 prefix argument it creates an annotate tag.
8969 prefix argument it creates an annotated tag.
88768970
88778971 @kindex t r
88788972 @cindex magit-tag-release
88798973 @item @kbd{t r} @tie{}@tie{}@tie{}@tie{}(@code{magit-tag-release})
88808974
8881 This commands creates an annotated release tag. It assumes that
8882 release tags match @code{magit-release-tag-regexp}.
8975 This commands creates a release tag. It assumes that release tags
8976 match @code{magit-release-tag-regexp}.
88838977
88848978 First it prompts for the name of the new tag using the highest
88858979 existing tag as initial input and leaving it to the user to
8886 increment the desired part of the version string.
8887
8888 Then it prompts for the message of the new tag. The proposed tag
8889 message is based on the message of the highest tag, provided that
8890 that contains the corresponding version string and substituting the
8891 new version string for that. Otherwise it proposes something like
8892 "Foo-Bar 1.2.3", given, for example, a TAG "v1.2.3" and a repository
8893 located at something like "/path/to/foo-bar".
8894
8895 Then it calls "git tag --annotate --sign -m MSG TAG" to create the
8896 tag, regardless of whether these arguments are enabled in the
8897 transient. Finally it shows the refs buffer to let the user quickly
8898 review the result.
8980 increment the desired part of the version string. If you use
8981 unconventional release tags or version numbers (e.g.,
8982 @code{v1.2.3-custom.1}), you can set the @code{magit-release-tag-regexp} and
8983 @code{magit-tag-version-regexp-alist} variables.
8984
8985 If @code{--annotate} is enabled then it prompts for the message of the
8986 new tag. The proposed tag message is based on the message of the
8987 highest tag, provided that that contains the corresponding version
8988 string and substituting the new version string for that. Otherwise
8989 it proposes something like "Foo-Bar 1.2.3", given, for example, a
8990 TAG "v1.2.3" and a repository located at something like
8991 "/path/to/foo-bar".
88998992
89008993 @kindex t k
89018994 @cindex magit-tag-delete
90439136 The command @code{magit-list-submodules} displays a list of the current
90449137 repository's submodules in a separate buffer. It's also possible to
90459138 display information about submodules directly in the status buffer of
9046 the super-repository by adding @code{magit-insert-submodules} to the hook
9139 the super-repository by adding @code{magit-insert-modules} to the hook
90479140 @code{magit-status-sections-hook} as described in @ref{Status Module Sections}.
90489141
90499142 @cindex magit-list-submodules
90699162 has to return a string to be inserted or nil. PROPS is an alist
90709163 that supports the keys @code{:right-align} and @code{:pad-right}.
90719164 @end defopt
9072
9073 @defun magit-insert-submodules
9074
9075 Insert sections for all submodules. For each section insert the
9076 path, the branch, and the output of @code{git describe --tags},
9077 or, failing that, the abbreviated HEAD commit hash.
9078
9079 Press @code{RET} on such a submodule section to show its own status buffer.
9080 Press @code{RET} on the "Modules" section to display a list of submodules
9081 in a separate buffer. This shows additional information not
9082 displayed in the super-repository's status buffer.
9083 @end defun
90849165
90859166 @node Submodule Transient
90869167 @subsection Submodule Transient
93259406 beside the ones below, but these didn't fit well anywhere else.
93269407
93279408 @table @asis
9328 @kindex M-w
9409 @kindex C-w
93299410 @cindex magit-copy-section-value
9330 @item @kbd{M-w} @tie{}@tie{}@tie{}@tie{}(@code{magit-copy-section-value})
9411 @item @kbd{C-w} @tie{}@tie{}@tie{}@tie{}(@code{magit-copy-section-value})
93319412
93329413 This command saves the value of the current section to the
93339414 @code{kill-ring}, and, provided that the current section is a commit,
93409421
93419422 When the region is active, this command saves that to the
93429423 @code{kill-ring}, like @code{kill-ring-save} would, instead of behaving as
9343 described above. If a prefix argument is used and the region is
9344 within a hunk, it strips the outer diff marker column before saving
9345 the text.
9346
9347 @kindex C-w
9424 described above. If a prefix argument is used and the region is
9425 within a hunk, then it strips the diff marker column and keeps
9426 only either the added or removed lines, depending on the sign of
9427 the prefix argument.
9428
9429 @kindex M-w
93489430 @cindex magit-copy-buffer-revision
9349 @item @kbd{C-w} @tie{}@tie{}@tie{}@tie{}(@code{magit-copy-buffer-revision})
9431 @item @kbd{M-w} @tie{}@tie{}@tie{}@tie{}(@code{magit-copy-buffer-revision})
93509432
93519433 This command saves the revision being displayed in the current buffer
93529434 to the @code{kill-ring} and also pushes it to the @code{magit-revision-stack}. It
96309712 Mode-line lighter for @code{magit-wip-initial-backup-mode}.
96319713 @end defopt
96329714
9633 @node Minor Mode for Buffers Visiting Files
9634 @section Minor Mode for Buffers Visiting Files
9635
9636 The minor-mode @code{magit-file-mode} enables certain Magit features in
9637 file-visiting buffers belonging to a Git repository. The globalized
9638 variant @code{global-magit-file-mode} enables the local mode in all such
9639 buffers. It is enabled by default. Currently the local mode only
9640 establishes a few key bindings, but this might be extended in the
9641 future.
9642
9643 @defopt global-magit-file-mode
9644
9645 Whether to establish certain Magit key bindings in all file-visiting
9646 buffers belonging to any Git repository. This is enabled by default.
9647 This globalized mode turns on the local minor-mode @code{magit-file-mode}
9648 in all suitable buffers.
9649 @end defopt
9650
9651 @defvar magit-file-mode-map
9652
9653 This keymap is used by the local minor-mode @code{magit-file-mode} and
9654 establishes the key bindings described below.
9655
9656 Note that the default binding for @code{magit-file-dispatch} is very
9657 cumbersome to use and that we recommend that you add a better
9658 binding.
9659
9660 Instead of @code{C-c M-g} I would have preferred to use @code{C-c g} because (1)
9661 it is similar to @code{C-x g} (the recommended global binding for
9662 @code{~magit-status}), (2) we cannot use @code{C-c C-g} because we have been
9663 recommending that that be bound to @code{magit-dispatch} for a long time,
9664 (3) we cannot use @code{C-x C-g} because that is a convenient way of
9665 aborting the incomplete key sequence @code{C-x}, and most importantly (4)
9666 it would make it much easier to type the next key (a suffix binding)
9667 because most of those are letters.
9668
9669 For example @code{C-c g b} is much easier to type than @code{C-c M-g b}. For
9670 suffix bindings that use uppercase letters, the default is just
9671 horrible—having to use e.g. @code{C-c M-g B} (@code{Control+c Meta+g Shift+b})
9672 would drive anyone up the walls (or to Vim).
9673
9674 However @code{C-c LETTER} bindings are reserved for users (see
9675 @ref{Key Binding Conventions,,,elisp,}). Packages are forbidden from
9676 using those. Doing so anyway is considered heresy. Therefore if
9677 you want a better binding, you have to add it yourself:
9715 @node Commands for Buffers Visiting Files
9716 @section Commands for Buffers Visiting Files
9717
9718 Magit defines a few global key bindings unless the user sets
9719 @code{magit-define-global-key-bindings} to @code{nil}. This includes binding @code{C-c
9720 M-g} to @code{magit-file-dispatch}. @code{C-c g} would be a much better binding
9721 but the @code{C-c <letter>} namespace is reserved for users, meaning that
9722 packages are not allowed to use it. If you want to use @code{C-c g}, then
9723 you have to add that binding yourself. Also see @ref{Default Bindings}
9724 and @ref{Key Binding Conventions,,,elisp,}.
9725
9726 If you want a better binding, you have to add it yourself:
96789727
96799728 @lisp
9680 (define-key magit-file-mode-map
9681 (kbd "C-c g") 'magit-file-dispatch)
9729 (global-set-key (kbd "C-c g") 'magit-file-dispatch)
96829730 @end lisp
9683 @end defvar
96849731
96859732 The key bindings shown below assume that you have not improved the
96869733 binding for @code{magit-file-dispatch}.
96929739
96939740 This transient prefix command binds the following suffix commands
96949741 and displays them in a temporary buffer until a suffix is invoked.
9742
9743 When invoked in a buffer that does not visit a file, then it falls
9744 back to regular @code{magit-dispatch}.
96959745
96969746 @kindex C-c M-g s
96979747 @cindex magit-stage-file
1002210072 @menu
1002310073 * Safety::
1002410074 * Performance::
10075 * Default Bindings::
1002510076 @end menu
1002610077
1002710078 @node Safety
1021210263 the diff, which is useful because it increases the odds that you spot
1021310264 potential issues.
1021410265
10215 @unnumberedsubsubsec The Built-In VC Package
10216
10217 Emacs comes with a version control interface called "VC", see
10218 @ref{Version Control,,,emacs,}. It is enabled be default, and if you don't
10219 use it in addition to Magit, then you should disable it to keep it
10220 from performing unnecessary work:
10221
10222 @lisp
10223 (setq vc-handled-backends nil)
10224 @end lisp
10225
10226 You can also disable its use for Git but keep using it when using
10227 another version control system:
10228
10229 @lisp
10230 (setq vc-handled-backends (delq 'Git vc-handled-backends))
10231 @end lisp
10232
1023310266 @node Microsoft Windows Performance
1023410267 @unnumberedsubsubsec Microsoft Windows Performance
1023510268
1027410307
1027510308 On Catalina, and potentially other macOS releases, there may be a
1027610309 performance problem where any action takes 20 times longer on Darwin
10277 than on Linux. This can be fixed by setting @code{magit-git-executable} to
10278 the absolute path of the @code{git} executable, instead of relying on
10279 resolving the @code{$PATH}.
10310 than on Linux. This can be worked around by setting
10311 @code{magit-git-executable} to the absolute path of the @code{git} executable,
10312 instead of relying on resolving the @code{$PATH}. You should not do that if
10313 you want to use Magit on remote machines using Tramp and if @code{git} is not
10314 installed in the same location on those machines.
10315
10316 @node Default Bindings
10317 @subsection Default Bindings
10318
10319 @defopt magit-define-global-key-bindings
10320
10321 This option controls whether some Magit commands are automatically
10322 bound in the global keymap even before Magit is used for the first
10323 time in the current session.
10324
10325 If this variable is non-nil, which it is by default, then the
10326 following bindings may be added to the global keymap.
10327
10328 @multitable {aaaaaaaaa} {aaaaaaaaaaaaaaaaaaaaa}
10329 @item @code{C-x g}
10330 @tab @code{magit-status}
10331 @item @code{C-x M-g}
10332 @tab @code{magit-dispatch}
10333 @item @code{C-c M-g}
10334 @tab @code{magit-file-dispatch}
10335 @end multitable
10336
10337 These bindings may be added when @code{after-init-hook} is called.
10338 Each binding is added if and only if at that time no other key
10339 is bound to the same command and no other command is bound to
10340 the same key. In other words we try to avoid adding bindings
10341 that are unnecessary, as well as bindings that conflict with
10342 other bindings.
10343
10344 Adding the above bindings is delayed until @code{after-init-hook}
10345 is called to allow users to set the variable anywhere in their
10346 init file (without having to make sure to do so before @code{magit}
10347 is loaded or autoloaded) and to increase the likelihood that
10348 all the potentially conflicting user bindings have already
10349 been added.
10350
10351 Setting this variable after the hook has already been called
10352 has no effect.
10353
10354 We recommend that you bind @code{C-c g} instead of @code{C-c M-g} to
10355 @code{magit-file-dispatch}. The former is a much better binding
10356 but the @code{C-c <letter>} namespace is strictly reserved for
10357 users; preventing Magit from using it by default.
10358
10359 @lisp
10360 (global-set-key (kbd "C-c g") 'magit-file-dispatch)
10361 @end lisp
10362
10363 Also see @ref{Commands for Buffers Visiting Files} and @ref{Key Binding Conventions,,,elisp,}.
10364 @end defopt
1028010365
1028110366 @node Plumbing
1028210367 @chapter Plumbing
1046110546 Calls git synchronously with ARGS and then refreshes.
1046210547 @end defun
1046310548
10464 @defun magit-run-git-with-input input &rest args
10465
10466 Calls git synchronously with ARGS and sends it INPUT on standard
10467 input.
10468
10469 INPUT should be a buffer or the name of an existing buffer. The
10470 content of that buffer is used as the process' standard input.
10471 After the process returns a refresh is performed.
10472
10473 As a special case, INPUT may also be nil. In that case the content
10474 of the current buffer is used as standard input and @strong{no} refresh is
10475 performed.
10476
10477 This function actually runs git asynchronously. But then it waits
10478 for the process to return, so the function itself is synchronous.
10549 @defun magit-run-git-with-input &rest args
10550
10551 Calls git synchronously with ARGS and sends it the content of the
10552 current buffer on standard input.
10553
10554 If the current buffer's @code{default-directory} is on a remote
10555 filesystem, this function actually runs git asynchronously. But
10556 then it waits for the process to return, so the function itself is
10557 synchronous.
1047910558 @end defun
1048010559
1048110560 @defun magit-run-git-with-logfile file &rest args
1048210561
10483 Calls git synchronously with ARGS@. The process' output is saved in
10562 Calls git synchronously with ARGS@. The process's output is saved in
1048410563 FILE@. This is rarely useful and so this function might be removed
1048510564 in the future.
1048610565
1053210611 still alive), as well as the respective Magit status buffer.
1053310612 @end defun
1053410613
10535 @defun magit-start-git &rest args
10614 @defun magit-start-git input &rest args
1053610615
1053710616 Start Git, prepare for refresh, and return the process object.
1053810617
1111411193 @appendixsec FAQ - How to @dots{}?
1111511194
1111611195 @menu
11196 * How to pronounce Magit?::
1111711197 * How to show git's output?::
1111811198 * How to install the gitman info manual?::
1111911199 * How to show diffs for gpg-encrypted files?::
1112011200 * How does branching and pushing work?::
1112111201 * Can Magit be used as @code{ediff-version-control-package}?::
11202 * Should I disable VC@?::
1112211203 @end menu
11204
11205 @node How to pronounce Magit?
11206 @appendixsubsec How to pronounce Magit?
11207
11208 Either @code{mu[m's] git} or @code{magi@{c => t@}} is fine.
11209
11210 The slogan is "It's Magit! The magical Git client", so it makes sense
11211 to pronounce Magit like magic, while taking into account that C and T
11212 do not sound the same.
11213
11214 The German "Magie" is not pronounced the same as the English "magic",
11215 so if you speak German then you can use the above rational to justify
11216 using the former pronunciation; @code{Mag@{ie => it@}}.
11217
11218 You can also choose to use the former pronunciation just because you
11219 like it better.
11220
11221 Also see @uref{https://magit.vc/assets/videos/magic.mp4}.
11222 Also see @uref{https://emacs.stackexchange.com/questions/13696}.
1112311223
1112411224 @node How to show git's output?
1112511225 @appendixsubsec How to show git's output?
1120511305 command @code{magit-ediff-resolve} which only shows yet-to-be resolved
1120611306 conflicts.
1120711307
11308 @node Should I disable VC@?
11309 @appendixsubsec Should I disable VC@?
11310
11311 If you don't use VC (the built-in version control interface) then
11312 you might be tempted to disable it, not least because we used to
11313 recommend that you do that.
11314
11315 We no longer recommend that you disable VC@. Doing so would break
11316 useful third-party packages (such as @code{diff-hl}), which depend on VC
11317 being enabled.
11318
11319 If you choose to disable VC anyway, then you can do so by changing
11320 the value of @code{vc-handled-backends}.
11321
1120811322 @node FAQ - Issues and Errors
1120911323 @appendixsec FAQ - Issues and Errors
1121011324
1131411428 But doing so isn't good for performance. For more (overly optimistic)
1131511429 information see @ref{VC Mode Line,,,emacs,}.
1131611430
11317 If you don't really care about seeing that information in the
11318 mode-line, but just don't want to see @emph{incorrect} information, then
11319 consider disabling VC when using Git:
11431 If you don't really care about seeing this information in the
11432 mode-line, but just don't want to see @emph{incorrect} information,
11433 then consider simply not displaying it in the mode-line:
1132011434
1132111435 @lisp
11322 (setq vc-handled-backends (delq 'Git vc-handled-backends))
11323 @end lisp
11324
11325 Or to disable it completely:
11326
11327 @lisp
11328 (setq vc-handled-backends nil)
11436 (setq-default mode-line-format
11437 (delete '(vc-mode vc-mode) mode-line-format))
1132911438 @end lisp
1133011439
1133111440 @node A branch and tag sharing the same name breaks SOMETHING
1140111510 @end example
1140211511
1140311512 This will actually end up using @code{emacs}, not @code{emacsclient}. If you do
11404 this, then can still edit the commit message but @code{git-commit-mode} won't
11405 be used and you have to exit @code{emacs} to finish the process.
11513 this, then you can still edit the commit message but @code{git-commit-mode}
11514 won't be used and you have to exit @code{emacs} to finish the process.
1140611515
1140711516 Tautology ahead. If you want to be able to use @code{emacsclient} to connect
1140811517 to a running @code{emacs} instance, even though no @code{emacs} instance is running,
0
1 GNU GENERAL PUBLIC LICENSE
2 Version 3, 29 June 2007
3
4 Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
0 GNU GENERAL PUBLIC LICENSE
1 Version 3, 29 June 2007
2
3 Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
54 Everyone is permitted to copy and distribute verbatim copies
65 of this license document, but changing it is not allowed.
76
8 Preamble
7 Preamble
98
109 The GNU General Public License is a free, copyleft license for
1110 software and other kinds of works.
6867 The precise terms and conditions for copying, distribution and
6968 modification follow.
7069
71 TERMS AND CONDITIONS
70 TERMS AND CONDITIONS
7271
7372 0. Definitions.
7473
7675
7776 "Copyright" also means copyright-like laws that apply to other kinds of
7877 works, such as semiconductor masks.
79
78
8079 "The Program" refers to any copyrightable work licensed under this
8180 License. Each licensee is addressed as "you". "Licensees" and
8281 "recipients" may be individuals or organizations.
509508 covered work in a country, or your recipient's use of the covered work
510509 in a country, would infringe one or more identifiable patents in that
511510 country that you have reason to believe are valid.
512
511
513512 If, pursuant to or in connection with a single transaction or
514513 arrangement, you convey, or propagate by procuring conveyance of, a
515514 covered work, and grant a patent license to some of the parties
618617 Program, unless a warranty or assumption of liability accompanies a
619618 copy of the Program in return for a fee.
620619
621 END OF TERMS AND CONDITIONS
622
623 How to Apply These Terms to Your New Programs
620 END OF TERMS AND CONDITIONS
621
622 How to Apply These Terms to Your New Programs
624623
625624 If you develop a new program, and you want it to be of the greatest
626625 possible use to the public, the best way to achieve this is to make it
645644 GNU General Public License for more details.
646645
647646 You should have received a copy of the GNU General Public License
648 along with this program. If not, see <http://www.gnu.org/licenses/>.
647 along with this program. If not, see <https://www.gnu.org/licenses/>.
649648
650649 Also add information on how to contact you by electronic and paper mail.
651650
664663 You should also get your employer (if you work as a programmer) or school,
665664 if any, to sign a "copyright disclaimer" for the program, if necessary.
666665 For more information on this, and how to apply and follow the GNU GPL, see
667 <http://www.gnu.org/licenses/>.
666 <https://www.gnu.org/licenses/>.
668667
669668 The GNU General Public License does not permit incorporating your program
670669 into proprietary programs. If your program is a subroutine library, you
671670 may consider it more useful to permit linking proprietary applications with
672671 the library. If this is what you want to do, use the GNU Lesser General
673672 Public License instead of this License. But first, please read
674 <http://www.gnu.org/philosophy/why-not-lgpl.html>.
675
673 <https://www.gnu.org/licenses/why-not-lgpl.html>.
4949 $(info ====)
5050 $(info )
5151 $(info make test - run tests)
52 $(info make test-git - run tests using Git functions)
53 $(info make test-libgit - run tests using libgit functions)
5254 $(info make test-interactive - run tests interactively)
5355 $(info make emacs-Q - run emacs -Q plus Magit)
5456 $(info )
110112 (load-file \"t/magit-tests.el\")\
111113 (ert-run-tests-batch-and-exit))"
112114
115 test-git:
116 @$(BATCH) --eval "(progn\
117 $$suppress_warnings\
118 (require 'magit)\
119 (setq magit-inhibit-libgit t)\
120 (unless (eq 'git (magit-gitimpl))\
121 (message \"Git implementation not being used.\")\
122 (kill-emacs 1))\
123 (load-file \"t/magit-tests.el\")\
124 (ert-run-tests-batch-and-exit))"
125
126 test-libgit:
127 @$(BATCH) --eval "(progn\
128 $$suppress_warnings\
129 (require 'magit)\
130 (unless (eq 'libgit (magit-gitimpl))\
131 (message \"libgit not available.\")\
132 (kill-emacs 1))\
133 (load-file \"t/magit-tests.el\")\
134 (ert-run-tests-batch-and-exit))"
135
113136 test-interactive:
114137 @$(EMACSBIN) -Q $(LOAD_PATH) --eval "(progn\
115138 (load-file \"t/magit-tests.el\")\
196219 `((emacs ,emacs-version) ;`
197220 (dash ,dash-version)
198221 (transient ,transient-version)
199 (with-editor ,with-editor-version)))))
222 (with-editor ,with-editor-version))))
223 (re-search-forward "^;; Package-Version: ")
224 (delete-region (point) (line-end-position))
225 (insert git-commit-version))
226
200227 (with-temp-file "lisp/magit-libgit.el"
201228 (insert-file-contents "lisp/magit-libgit.el")
202229 (re-search-forward "^;; Package-Requires: ")
204231 (insert (format "%S"
205232 `((emacs "$(LIBGIT_EMACS_VERSION)") ;`
206233 (magit "$(LIBGIT_MAGIT_VERSION)")
207 (libgit ,libgit-version)))))
234 (libgit ,libgit-version))))
235 (re-search-forward "^;; Package-Version: ")
236 (delete-region (point) (line-end-position))
237 (insert magit-libgit-version))
208238 (with-temp-file "lisp/magit-section.el"
209239 (insert-file-contents "lisp/magit-section.el")
210240 (re-search-forward "^;; Package-Requires: ")
211241 (delete-region (point) (line-end-position))
212242 (insert (format "%S"
213243 `((emacs ,emacs-version) ;`
214 (dash ,dash-version)))))
244 (dash ,dash-version))))
245 (re-search-forward "^;; Package-Version: ")
246 (delete-region (point) (line-end-position))
247 (insert magit-section-version))
215248 (with-temp-file "lisp/magit-pkg.el"
216 (insert (pp-to-string
217 `(define-package "magit" "$(VERSION)" ;`
218 "A Git porcelain inside Emacs."
219 '((emacs ,emacs-version) ;'
220 (async ,async-version)
221 (dash ,dash-version)
222 (git-commit ,git-commit-version)
223 ;; FIXME (magit-section ,magit-section-version)
224 (transient ,transient-version)
225 (with-editor ,with-editor-version))
226 :keywords '("git" "tools" "vc")))) ;'
249 (insert (format
250 "(define-package \"magit\" \"$(VERSION)\"\
251 \"A Git porcelain inside Emacs.\"
252 '((emacs %S)
253 (dash %S)
254 (git-commit %S)
255 (magit-section %S)
256 (transient %S)
257 (with-editor %S))
258 :homepage \"https://magit.vc\"
259 :keywords '(\"git\" \"tools\" \"vc\"))
260 " emacs-version
261 dash-version
262 git-commit-version
263 magit-section-version
264 transient-version
265 with-editor-version))
227266 (goto-char (point-min))
228267 (re-search-forward " \"A")
229268 (goto-char (match-beginning 0))
235274 bump-versions-1:
236275 @$(BATCH) --eval "(let (\
237276 (emacs-version \"$(EMACS_VERSION)\")\
238 (async-version \"$(ASYNC_VERSION)\")\
239277 (dash-version \"$(DASH_VERSION)\")\
240278 (git-commit-version \"$(GIT_COMMIT_VERSION)\")\
241279 (libgit-version \"$(LIBGIT_VERSION)\")\
280 (magit-libgit-version \"$(MAGIT_LIBGIT_VERSION)\")\
242281 (magit-section-version \"$(MAGIT_SECTION_VERSION)\")\
243282 (transient-version \"$(TRANSIENT_VERSION)\")\
244283 (with-editor-version \"$(WITH_EDITOR_VERSION)\"))\
247286 bump-snapshots:
248287 @$(BATCH) --eval "(let (\
249288 (emacs-version \"$(EMACS_VERSION)\")\
250 (async-version \"$(ASYNC_MELPA_SNAPSHOT)\")\
251289 (dash-version \"$(DASH_MELPA_SNAPSHOT)\")\
252290 (git-commit-version \"$(GIT_COMMIT_MELPA_SNAPSHOT)\")\
253291 (libgit-version \"$(LIBGIT_MELPA_SNAPSHOT)\")\
292 (magit-libgit-version \"$(MAGIT_LIBGIT_MELPA_SNAPSHOT)\")\
254293 (magit-section-version \"$(MAGIT_SECTION_MELPA_SNAPSHOT)\")\
255294 (transient-version \"$(TRANSIENT_MELPA_SNAPSHOT)\")\
256295 (with-editor-version \"$(WITH_EDITOR_MELPA_SNAPSHOT)\"))\
130130 ***
131131 [![Paren Xkcb](https://img.shields.io/badge/%28-%20%20%20-red.svg)](https://xkcd.com/859)
132132 [![GPL v3](https://img.shields.io/badge/license-GPL_v3-green.svg)](http://www.gnu.org/licenses/gpl-3.0.txt)
133 [![Build Status](https://travis-ci.org/magit/magit.svg?branch=master)](https://travis-ci.org/magit/magit)
133 [![Build Status](https://github.com/magit/magit/workflows/test/badge.svg?branch=master)](https://github.com/magit/magit/actions)
134134 [![Melpa](https://melpa.org/packages/magit-badge.svg)](https://melpa.org/#/magit)
135135 [![Melpa Stable](https://stable.melpa.org/packages/magit-badge.svg)](https://stable.melpa.org/#/magit)
136 [![Git Xkcd](https://img.shields.io/badge/xkcd-git-orange.svg)](https://xkcd.com/1597)
137136 [![Eierlegende Wollmilchsau](https://img.shields.io/badge/eierlegende-Wollmilchsau-green.svg)](https://magit.vc/manual/magit)
138137 [![Swiss Made](https://img.shields.io/badge/swiss-made-red.svg?colorA=E11A27&colorB=555555)](https://magit.vc/stats/authors.html#commits_per_author)
139138 [![Netscape](https://magit.vc/assets/netscape-20px.png)](https://en.wikipedia.org/wiki/Browser_wars)
5353 ifeq "$(BUILD_MAGIT_LIBGIT)" "true"
5454 ELS += magit-libgit.el
5555 endif
56 ELS += magit-git.el
5657 ELS += magit-mode.el
5758 ELS += magit-margin.el
5859 ELS += magit-process.el
100101
101102 ## Versions ##########################################################
102103
103 VERSION ?= $(shell test -e $(TOP).git && git describe --tags --abbrev=0 | cut -c2-)
104
105 ASYNC_VERSION = 1.9.3
106 DASH_VERSION = 2.14.1
107 GIT_COMMIT_VERSION = 3.0.0
108 LIBGIT_VERSION = 0
109 MAGIT_SECTION_VERSION = 3.0.0
110 TRANSIENT_VERSION = 0
111 WITH_EDITOR_VERSION = 2.8.0
112
113 ASYNC_MELPA_SNAPSHOT = 20180527
114 DASH_MELPA_SNAPSHOT = 20180910
115 GIT_COMMIT_MELPA_SNAPSHOT = 20181104
116 LIBGIT_MELPA_SNAPSHOT = 0
117 MAGIT_SECTION_MELPA_SNAPSHOT = 20200123
118 TRANSIENT_MELPA_SNAPSHOT = 20190812
119 WITH_EDITOR_MELPA_SNAPSHOT = 20181103
104 VERSION ?= $(shell \
105 test -e $(TOP).git && \
106 git describe --tags --abbrev=0 --always | cut -c2-)
107
108 DASH_VERSION = 2.18.1
109 GIT_COMMIT_VERSION = $(VERSION)
110 LIBGIT_VERSION = 0
111 MAGIT_LIBGIT_VERSION = 0
112 MAGIT_SECTION_VERSION = $(VERSION)
113 TRANSIENT_VERSION = 0.3.3
114 WITH_EDITOR_VERSION = 3.0.4
115
116 DASH_MELPA_SNAPSHOT = 20210330
117 GIT_COMMIT_MELPA_SNAPSHOT = 20210524
118 LIBGIT_MELPA_SNAPSHOT = 0
119 MAGIT_LIBGIT_MELPA_SNAPSHOT = 0
120 MAGIT_SECTION_MELPA_SNAPSHOT = 20210524
121 TRANSIENT_MELPA_SNAPSHOT = 20210524
122 WITH_EDITOR_MELPA_SNAPSHOT = 20210524
120123
121124 EMACS_VERSION = 25.1
122125
123126 LIBGIT_EMACS_VERSION = 26.1
124 LIBGIT_MAGIT_VERSION = 0
127 LIBGIT_MAGIT_VERSION = $(VERSION)
125128
126129 EMACSOLD := $(shell $(BATCH) --eval \
127130 "(and (version< emacs-version \"$(EMACS_VERSION)\") (princ \"true\"))")
133136
134137 ifndef LOAD_PATH
135138
136 ELPA_DIR ?= $(HOME)/.emacs.d/elpa
139 USER_EMACS_DIR = $(HOME)/.emacs.d
140 ifeq "$(wildcard $(USER_EMACS_DIR))" ""
141 XDG_CONFIG_DIR = $(or $(XDG_CONFIG_HOME),$(HOME)/.config)
142 ifneq "$(wildcard $(XDG_CONFIG_DIR)/emacs)" ""
143 USER_EMACS_DIR = $(XDG_CONFIG_DIR)/emacs
144 endif
145 endif
146
147 ELPA_DIR ?= $(USER_EMACS_DIR)/elpa
137148
138149 DASH_DIR ?= $(shell \
139150 find -L $(ELPA_DIR) -maxdepth 1 -regex '.*/dash-[.0-9]*' 2> /dev/null | \
171182 LOAD_PATH = -L $(TOP)lisp
172183
173184 # When making changes here, then don't forget to adjust "Makefile",
174 # ".travis.yml", ".github/ISSUE_TEMPLATE/bug_report.md",
185 # ".github/workflows/test.yml", ".github/ISSUE_TEMPLATE/bug_report.md",
175186 # `magit-emacs-Q-command' and the "Installing from the Git Repository"
176187 # info node accordingly. Also don't forget to "rgrep \b<pkg>\b".
177188
192203 ifndef ORG_LOAD_PATH
193204 ORG_LOAD_PATH = $(LOAD_PATH)
194205 ORG_LOAD_PATH += -L ../../org/lisp
195 ORG_LOAD_PATH += -L ../../org/contrib/lisp
206 ORG_LOAD_PATH += -L ../../org-contrib/lisp
196207 ORG_LOAD_PATH += -L ../../ox-texinfo+
197208 endif
198209
00 ;;; git-commit.el --- Edit Git commit messages -*- lexical-binding: t; -*-
11
2 ;; Copyright (C) 2010-2020 The Magit Project Contributors
2 ;; Copyright (C) 2010-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
7 ;; Authors: Jonas Bernoulli <jonas@bernoul.li>
8 ;; Sebastian Wiesner <lunaryorn@gmail.com>
9 ;; Florian Ragwitz <rafl@debian.org>
10 ;; Marius Vollmer <marius.vollmer@gmail.com>
7 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
8 ;; Sebastian Wiesner <lunaryorn@gmail.com>
9 ;; Florian Ragwitz <rafl@debian.org>
10 ;; Marius Vollmer <marius.vollmer@gmail.com>
1111 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
1212
13 ;; Package-Requires: ((emacs "25.1") (dash "20180910") (transient "20190812") (with-editor "20181103"))
1413 ;; Keywords: git tools vc
1514 ;; Homepage: https://github.com/magit/magit
16
17 ;; This file is not part of GNU Emacs.
15 ;; Package-Requires: ((emacs "25.1") (dash "2.18.1") (transient "0.3.3") (with-editor "3.0.4"))
16 ;; Package-Version: 3.0.0
17 ;; SPDX-License-Identifier: GPL-3.0-or-later
1818
1919 ;; This file is free software; you can redistribute it and/or modify
2020 ;; it under the terms of the GNU General Public License as published by
2121 ;; the Free Software Foundation; either version 3, or (at your option)
2222 ;; any later version.
23
23 ;;
2424 ;; This file is distributed in the hope that it will be useful,
2525 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
2626 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2727 ;; GNU General Public License for more details.
28
28 ;;
2929 ;; You should have received a copy of the GNU General Public License
3030 ;; along with this file. If not, see <http://www.gnu.org/licenses/>.
3131
112112 ;;;; Dependencies
113113
114114 (require 'dash)
115 (require 'log-edit)
115 (require 'subr-x)
116
116117 (require 'magit-git nil t)
117118 (require 'magit-utils nil t)
119
120 (require 'log-edit)
118121 (require 'ring)
122 (require 'rx)
119123 (require 'server)
120124 (require 'transient)
121125 (require 'with-editor)
122126
123 (eval-when-compile
124 (require 'recentf)
125 (require 'subr-x))
127 (defvar recentf-exclude)
126128
127129 ;;;; Declarations
128130
149151 :link '(info-link "(magit)Editing Commit Messages")
150152 :group 'tools)
151153
152 ;;;###autoload
153154 (define-minor-mode global-git-commit-mode
154155 "Edit Git commit messages.
156
155157 This global mode arranges for `git-commit-setup' to be called
156158 when a Git commit message file is opened. That usually happens
157159 when Git uses the Emacsclient as $GIT_EDITOR to have the user
158 provide such a commit message."
160 provide such a commit message.
161
162 Loading the library `git-commit' by default enables this mode,
163 but the library is not automatically loaded because doing that
164 would pull in many dependencies and increase startup time too
165 much. You can either rely on `magit' loading this library or
166 you can load it explicitly. Autoloading is not an alternative
167 because in this case autoloading would immediately trigger
168 full loading."
159169 :group 'git-commit
160170 :type 'boolean
161171 :global t
174184 `git-commit-mode'."
175185 :group 'git-commit
176186 :type '(choice (function-item text-mode)
187 (function-item markdown-mode)
188 (function-item org-mode)
189 (function-item fundamental-mode)
190 (function-item git-commit-elisp-text-mode)
191 (function :tag "Another mode")
177192 (const :tag "No major mode")))
193 ;;;###autoload(put 'git-commit-major-mode 'safe-local-variable
194 ;;;###autoload (lambda (val)
195 ;;;###autoload (memq val '(text-mode
196 ;;;###autoload markdown-mode
197 ;;;###autoload org-mode
198 ;;;###autoload fundamental-mode
199 ;;;###autoload git-commit-elisp-text-mode))))
178200
179201 (defcustom git-commit-setup-hook
180202 '(git-commit-save-message
189211 :get (and (featurep 'magit-utils) 'magit-hook-custom-get)
190212 :options '(git-commit-save-message
191213 git-commit-setup-changelog-support
214 magit-generate-changelog
192215 git-commit-turn-on-auto-fill
193216 git-commit-turn-on-flyspell
194217 git-commit-propertize-diff
308331 (defface git-commit-keyword
309332 '((t :inherit font-lock-string-face))
310333 "Face used for keywords in commit messages.
311 In this context a \"keyword\" is text surrounded be brackets."
334 In this context a \"keyword\" is text surrounded by brackets."
312335 :group 'git-commit-faces)
313336
314337 (define-obsolete-face-alias 'git-commit-note
415438
416439 ;;; Hooks
417440
418 ;;;###autoload
419441 (defconst git-commit-filename-regexp "/\\(\
420442 \\(\\(COMMIT\\|NOTES\\|PULLREQ\\|MERGEREQ\\|TAG\\)_EDIT\\|MERGE_\\|\\)MSG\
421443 \\|\\(BRANCH\\|EDIT\\)_DESCRIPTION\\)\\'")
422444
423 (eval-after-load 'recentf
424 '(add-to-list 'recentf-exclude git-commit-filename-regexp))
445 (with-eval-after-load 'recentf
446 (add-to-list 'recentf-exclude git-commit-filename-regexp))
425447
426448 (add-to-list 'with-editor-file-name-history-exclude git-commit-filename-regexp)
427449
432454
433455 (add-hook 'after-change-major-mode-hook 'git-commit-setup-font-lock-in-buffer)
434456
435 ;;;###autoload
436457 (defun git-commit-setup-check-buffer ()
437458 (and buffer-file-name
438459 (string-match-p git-commit-filename-regexp buffer-file-name)
472493 \\[git-commit-prev-message] and \\[git-commit-next-message] \
473494 to recover older messages")
474495
475 ;;;###autoload
476496 (defun git-commit-setup ()
477497 (when (fboundp 'magit-toplevel)
478498 ;; `magit-toplevel' is autoloaded and defined in magit-git.el,
572592
573593 (defun git-commit-setup-changelog-support ()
574594 "Treat ChangeLog entries as unindented paragraphs."
595 (when (fboundp 'log-indent-fill-entry) ; New in Emacs 27.
596 (setq-local fill-paragraph-function #'log-indent-fill-entry))
575597 (setq-local fill-indent-according-to-mode t)
576598 (setq-local paragraph-start (concat paragraph-start "\\|\\*\\|(")))
577599
617639 "Check for violations of certain basic style conventions.
618640
619641 For each violation ask the user if she wants to proceed anyway.
620 Option `git-commit-check-style-conventions' controls which
642 Option `git-commit-style-convention-checks' controls which
621643 conventions are checked."
622644 (or force
623645 (save-excursion
646668 "Cycle backward through message history, after saving current message.
647669 With a numeric prefix ARG, go back ARG comments."
648670 (interactive "*p")
649 (when (and (git-commit-save-message) (> arg 0))
650 (setq log-edit-comment-ring-index
651 (log-edit-new-comment-index
652 arg (ring-length log-edit-comment-ring))))
653 (save-restriction
654 (goto-char (point-min))
655 (narrow-to-region (point)
656 (if (re-search-forward (concat "^" comment-start) nil t)
657 (max 1 (- (point) 2))
658 (point-max)))
659 (log-edit-previous-comment arg)))
671 (let ((len (ring-length log-edit-comment-ring)))
672 (if (<= len 0)
673 (progn (message "Empty comment ring") (ding))
674 ;; Unlike `log-edit-previous-comment' we save the current
675 ;; non-empty and newly written comment, because otherwise
676 ;; it would be irreversibly lost.
677 (when-let ((message (git-commit-buffer-message)))
678 (unless (ring-member log-edit-comment-ring message)
679 (ring-insert log-edit-comment-ring message)
680 (cl-incf arg)
681 (setq len (ring-length log-edit-comment-ring))))
682 ;; Delete the message but not the instructions at the end.
683 (save-restriction
684 (goto-char (point-min))
685 (narrow-to-region
686 (point)
687 (if (re-search-forward (concat "^" comment-start) nil t)
688 (max 1 (- (point) 2))
689 (point-max)))
690 (delete-region (point-min) (point)))
691 (setq log-edit-comment-ring-index (log-edit-new-comment-index arg len))
692 (message "Comment %d" (1+ log-edit-comment-ring-index))
693 (insert (ring-ref log-edit-comment-ring log-edit-comment-ring-index)))))
660694
661695 (defun git-commit-next-message (arg)
662696 "Cycle forward through message history, after saving current message.
695729
696730 ;;; Headers
697731
698 (define-transient-command git-commit-insert-pseudo-header ()
732 (transient-define-prefix git-commit-insert-pseudo-header ()
699733 "Insert a commit message pseudo header."
700734 [["Insert ... by yourself"
701735 ("a" "Ack" git-commit-ack)
851885 "Changes not staged for commit:"
852886 "Unmerged paths:"
853887 "Author:"
854 "Date:"))
888 "Date:")
889 "Also fontified outside of comments in `git-commit-font-lock-keywords-2'.")
855890
856891 (defconst git-commit-font-lock-keywords-1
857892 '(;; Pseudo headers
859894 (regexp-opt git-commit-known-pseudo-headers))
860895 (1 'git-commit-known-pseudo-header)
861896 (2 'git-commit-pseudo-header)))
862 ("^[-a-zA-Z]+: [^<]+? <[^>]+>"
863 (0 'git-commit-pseudo-header))
864897 ;; Summary
865898 (eval . `(,(git-commit-summary-regexp)
866899 (1 'git-commit-summary)))
886919 (1 'git-commit-comment-heading t)))
887920 (eval . `(,(format "^%s\t\\(?:\\([^:\n]+\\):\\s-+\\)?\\(.*\\)" comment-start)
888921 (1 'git-commit-comment-action t t)
889 (2 'git-commit-comment-file t)))))
922 (2 'git-commit-comment-file t)))
923 ;; "commit HASH"
924 (eval . `(,(rx bol "commit " (1+ alnum) eol)
925 (0 'git-commit-pseudo-header)))
926 ;; `git-commit-comment-headings' (but not in commented lines)
927 (eval . `(,(rx-to-string `(seq bol (or ,@git-commit-comment-headings) (1+ blank) (1+ nonl) eol))
928 (0 'git-commit-pseudo-header)))))
890929
891930 (defconst git-commit-font-lock-keywords-3
892931 `(,@git-commit-font-lock-keywords-2
904943 ;; Your branch is up to date with 'master'.
905944 ;; Your branch and 'master' have diverged,
906945 . `(,(format
907 "^%s Your branch \\(?:is up-to-date with\\|and\\) '%s'"
946 "^%s Your branch \\(?:is up[- ]to[- ]date with\\|and\\) '%s'"
908947 comment-start git-commit--branch-name-regexp)
909948 (1 'git-commit-comment-branch-local t)
910949 (2 'git-commit-comment-branch-remote t)))
916955 (1 'bold t)
917956 (2 'bold t)))))
918957
919 (defvar git-commit-font-lock-keywords git-commit-font-lock-keywords-2
958 (defvar git-commit-font-lock-keywords git-commit-font-lock-keywords-3
920959 "Font-Lock keywords for Git-Commit mode.")
921960
922961 (defun git-commit-setup-font-lock ()
929968 (modify-syntax-entry ?` "." table)
930969 (set-syntax-table table))
931970 (setq-local comment-start
932 (or (ignore-errors
933 (car (process-lines "git" "config" "core.commentchar")))
971 (or (with-temp-buffer
972 (call-process "git" nil (current-buffer) nil
973 "config" "core.commentchar")
974 (unless (bobp)
975 (goto-char (point-min))
976 (buffer-substring (point) (line-end-position))))
934977 "#"))
935978 (setq-local comment-start-skip (format "^%s+[\s\t]*" comment-start))
936979 (setq-local comment-end-skip "\n")
944987 (progn
945988 ;; Make sure the below functions are available.
946989 (require 'magit)
947 ;; Font-Lock wants every submatch to succeed,
948 ;; so also match the empty string. Do not use
949 ;; `regexp-quote' because that is slow if there
950 ;; are thousands of branches outweighing the
951 ;; benefit of an efficient regep.
952 (format "\\(\\(?:%s\\)\\|\\)\\(\\(?:%s\\)\\|\\)"
990 ;; Font-Lock wants every submatch to succeed, so
991 ;; also match the empty string. Avoid listing
992 ;; remote branches and using `regexp-quote',
993 ;; because in repositories have thousands of
994 ;; branches that would be very slow. See #4353.
995 (format "\\(\\(?:%s\\)\\|\\)\\([^']+\\)"
953996 (mapconcat #'identity
954997 (magit-list-local-branch-names)
955 "\\|")
956 (mapconcat #'identity
957 (magit-list-remote-branch-names)
958998 "\\|")))
959999 "\\([^']*\\)"))
9601000 (setq-local font-lock-multiline t)
00 ;;; git-rebase.el --- Edit Git rebase files -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2010-2020 The Magit Project Contributors
2 ;; Copyright (C) 2010-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
77 ;; Author: Phil Jackson <phil@shellarchive.co.uk>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
99
10 ;; This file is not part of GNU Emacs.
10 ;; SPDX-License-Identifier: GPL-3.0-or-later
1111
1212 ;; This file is free software; you can redistribute it and/or modify
1313 ;; it under the terms of the GNU General Public License as published by
7373
7474 ;;; Code:
7575
76 (require 'dash)
76 (require 'magit)
77
7778 (require 'easymenu)
7879 (require 'server)
7980 (require 'with-editor)
80 (require 'magit)
81
82 (and (require 'async-bytecomp nil t)
83 (let ((pkgs (bound-and-true-p async-bytecomp-allowed-packages)))
84 (if (consp pkgs)
85 (cl-intersection '(all magit) pkgs)
86 (memq pkgs '(all t))))
87 (fboundp 'async-bytecomp-package-mode)
88 (async-bytecomp-package-mode 1))
89
90 (eval-when-compile (require 'recentf))
81
82 (defvar recentf-exclude)
9183
9284 ;;; Options
9385 ;;;; Variables
222214 ;;; Commands
223215
224216 (defun git-rebase-pick ()
225 "Use commit on current line."
217 "Use commit on current line.
218 If the region is active, act on all lines touched by the region."
226219 (interactive)
227220 (git-rebase-set-action "pick"))
228221
229222 (defun git-rebase-reword ()
230 "Edit message of commit on current line."
223 "Edit message of commit on current line.
224 If the region is active, act on all lines touched by the region."
231225 (interactive)
232226 (git-rebase-set-action "reword"))
233227
234228 (defun git-rebase-edit ()
235 "Stop at the commit on the current line."
229 "Stop at the commit on the current line.
230 If the region is active, act on all lines touched by the region."
236231 (interactive)
237232 (git-rebase-set-action "edit"))
238233
239234 (defun git-rebase-squash ()
240 "Meld commit on current line into previous commit, edit message."
235 "Meld commit on current line into previous commit, edit message.
236 If the region is active, act on all lines touched by the region."
241237 (interactive)
242238 (git-rebase-set-action "squash"))
243239
244240 (defun git-rebase-fixup ()
245 "Meld commit on current line into previous commit, discard its message."
241 "Meld commit on current line into previous commit, discard its message.
242 If the region is active, act on all lines touched by the region."
246243 (interactive)
247244 (git-rebase-set-action "fixup"))
248245
286283 "r" "reword"
287284 "s" "squash")
288285 "\\(?1:")
289 " \\(?3:[^ \n]+\\) \\(?4:.*\\)"))
286 " \\(?3:[^ \n]+\\) ?\\(?4:.*\\)"))
290287 (exec . "\\(?1:x\\|exec\\) \\(?3:.*\\)")
291288 (bare . ,(concat (regexp-opt '("b" "break" "noop") "\\(?1:")
292289 " *$"))
308305 (goto-char (line-beginning-position))
309306 (if-let ((re-start (concat "^\\(?5:" (regexp-quote comment-start)
310307 "\\)? *"))
311 (type (-some (lambda (arg)
312 (let ((case-fold-search nil))
313 (and (looking-at (concat re-start (cdr arg)))
314 (car arg))))
315 git-rebase-line-regexps)))
308 (type (seq-some (lambda (arg)
309 (let ((case-fold-search nil))
310 (and (looking-at (concat re-start (cdr arg)))
311 (car arg))))
312 git-rebase-line-regexps)))
316313 (git-rebase-action
317314 :action-type type
318315 :action (when-let ((action (match-string-no-properties 1)))
326323 (git-rebase-action))))
327324
328325 (defun git-rebase-set-action (action)
329 (goto-char (line-beginning-position))
330 (with-slots (action-type target trailer)
331 (git-rebase-current-line)
332 (if (eq action-type 'commit)
333 (let ((inhibit-read-only t))
334 (magit-delete-line)
335 (insert (concat action " " target " " trailer "\n"))
336 (unless git-rebase-auto-advance
337 (forward-line -1)))
338 (ding))))
326 "Set action of commit line to ACTION.
327 If the region is active, operate on all lines that it touches.
328 Otherwise, operate on the current line. As a special case, an
329 ACTION of nil comments the rebase line, regardless of its action
330 type."
331 (pcase (git-rebase-region-bounds t)
332 (`(,beg ,end)
333 (let ((end-marker (copy-marker end))
334 (pt-below-p (and mark-active (< (mark) (point)))))
335 (set-marker-insertion-type end-marker t)
336 (goto-char beg)
337 (while (< (point) end-marker)
338 (with-slots (action-type target trailer comment-p)
339 (git-rebase-current-line)
340 (cond
341 ((and action (eq action-type 'commit))
342 (let ((inhibit-read-only t))
343 (magit-delete-line)
344 (insert (concat action " " target " " trailer "\n"))))
345 ((and action-type (not (or action comment-p)))
346 (let ((inhibit-read-only t))
347 (insert comment-start " "))
348 (forward-line))
349 (t
350 ;; In the case of --rebase-merges, commit lines may have
351 ;; other lines with other action types, empty lines, and
352 ;; "Branch" comments interspersed. Move along.
353 (forward-line)))))
354 (goto-char
355 (if git-rebase-auto-advance
356 end-marker
357 (if pt-below-p (1- end-marker) beg)))
358 (goto-char (line-beginning-position))))
359 (_ (ding))))
339360
340361 (defun git-rebase-line-p (&optional pos)
341362 (save-excursion
343364 (and (oref (git-rebase-current-line) action-type)
344365 t)))
345366
346 (defun git-rebase-region-bounds ()
347 (when (use-region-p)
367 (defun git-rebase-region-bounds (&optional fallback)
368 "Return region bounds if both ends touch rebase lines.
369 Each bound is extended to include the entire line touched by the
370 point or mark. If the region isn't active and FALLBACK is
371 non-nil, return the beginning and end of the current rebase line,
372 if any."
373 (cond
374 ((use-region-p)
348375 (let ((beg (save-excursion (goto-char (region-beginning))
349376 (line-beginning-position)))
350377 (end (save-excursion (goto-char (region-end))
351378 (line-end-position))))
352379 (when (and (git-rebase-line-p beg)
353380 (git-rebase-line-p end))
354 (list beg (1+ end))))))
381 (list beg (1+ end)))))
382 ((and fallback (git-rebase-line-p))
383 (list (line-beginning-position)
384 (1+ (line-end-position))))))
355385
356386 (defun git-rebase-move-line-down (n)
357387 "Move the current commit (or command) N lines down.
422452 (funcall (default-value 'redisplay-unhighlight-region-function) rol))
423453
424454 (defun git-rebase-kill-line ()
425 "Kill the current action line."
426 (interactive)
427 (goto-char (line-beginning-position))
428 (unless (oref (git-rebase-current-line) comment-p)
429 (let ((inhibit-read-only t))
430 (insert comment-start)
431 (insert " "))
432 (goto-char (line-beginning-position))
433 (when git-rebase-auto-advance
434 (forward-line))))
455 "Kill the current action line.
456 If the region is active, act on all lines touched by the region."
457 (interactive)
458 (git-rebase-set-action nil))
435459
436460 (defun git-rebase-insert (rev)
437461 "Read an arbitrary commit and insert it below current line."
793817 (add-to-list 'with-editor-server-window-alist
794818 (cons git-rebase-filename-regexp 'switch-to-buffer))
795819
796 (eval-after-load 'recentf
797 '(add-to-list 'recentf-exclude git-rebase-filename-regexp))
820 (with-eval-after-load 'recentf
821 (add-to-list 'recentf-exclude git-rebase-filename-regexp))
798822
799823 (add-to-list 'with-editor-file-name-history-exclude git-rebase-filename-regexp)
800824
00 ;;; magit-apply.el --- apply Git diffs -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2010-2020 The Magit Project Contributors
2 ;; Copyright (C) 2010-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
77 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9
10 ;; SPDX-License-Identifier: GPL-3.0-or-later
911
1012 ;; Magit is free software; you can redistribute it and/or modify it
1113 ;; under the terms of the GNU General Public License as published by
2830 ;; at least at the porcelain level.
2931
3032 ;;; Code:
31
32 (eval-when-compile
33 (require 'subr-x))
3433
3534 (require 'magit-core)
3635 (require 'magit-diff)
5251 (path &optional prefer-short))
5352 (declare-function borg--maybe-absorb-gitdir "borg" (pkg))
5453 (declare-function borg--sort-submodule-sections "borg" (file))
54 (declare-function borg-assimilate "borg" (package url &optional partially))
5555 (defvar borg-user-emacs-directory)
5656
5757 ;;; Options
230230 (ignore-context (magit-diff-ignore-any-space-p)))
231231 (unless (magit-diff-context-p)
232232 (user-error "Not enough context to apply patch. Increase the context"))
233 (when (and magit-wip-before-change-mode (not inhibit-magit-refresh))
233 (when (and magit-wip-before-change-mode (not magit-inhibit-refresh))
234234 (magit-wip-commit-before-change files (concat " before " command)))
235235 (with-temp-buffer
236236 (insert patch)
238238 "apply" args "-p0"
239239 (and ignore-context "-C0")
240240 "--ignore-space-change" "-"))
241 (unless inhibit-magit-refresh
241 (unless magit-inhibit-refresh
242242 (when magit-wip-after-apply-mode
243243 (magit-wip-commit-after-apply files (concat " after " command)))
244244 (magit-refresh))))
361361 `((file . ,repo) (untracked) (status)))
362362 start))
363363 (let* ((topdir (magit-toplevel))
364 (url (let ((default-directory
365 (file-name-as-directory (expand-file-name repo))))
366 (or (magit-get "remote" (magit-get-some-remote) "url")
367 (concat (file-name-as-directory ".") repo))))
364368 (package
365369 (and (equal (bound-and-true-p borg-user-emacs-directory)
366370 topdir)
367371 (file-name-nondirectory (directory-file-name repo)))))
368 (magit-submodule-add-1
369 (let ((default-directory
370 (file-name-as-directory (expand-file-name repo))))
371 (or (magit-get "remote" (magit-get-some-remote) "url")
372 (concat (file-name-as-directory ".") repo)))
373 repo
374 (magit-submodule-read-name-for-path repo package))
375 (when package
376 (borg--sort-submodule-sections
377 (expand-file-name ".gitmodules" topdir))
378 (let ((default-directory borg-user-emacs-directory))
379 (borg--maybe-absorb-gitdir package))
380 (when (and (y-or-n-p
381 (format "Also build and activate `%s' drone?" package))
382 (fboundp 'borg-build)
383 (fboundp 'borg-activate))
384 (borg-build package)
385 (borg-activate package))))))
372 (if (and package
373 (y-or-n-p (format "Also assimilate `%s' drone?" package)))
374 (borg-assimilate package url)
375 (magit-submodule-add-1
376 url repo (magit-submodule-read-name-for-path repo package))
377 (when package
378 (borg--sort-submodule-sections
379 (expand-file-name ".gitmodules" topdir))
380 (let ((default-directory borg-user-emacs-directory))
381 (borg--maybe-absorb-gitdir package)))))))
386382 (magit-wip-commit-after-apply files " after stage")))
387383
388384 ;;;; Unstage
485481 nil (if (magit-file-section-p section)
486482 (oref section value)
487483 (magit-section-parent-value section)))
488 (progn (let ((inhibit-magit-refresh t))
484 (progn (let ((magit-inhibit-refresh t))
489485 (funcall apply section "--reverse" "--cached")
490486 (funcall apply section "--reverse" "--reject"))
491487 (magit-refresh))
505501 nil (if (magit-file-section-p section)
506502 (oref section value)
507503 (magit-section-parent-value section)))
508 (progn (let ((inhibit-magit-refresh t))
504 (progn (let ((magit-inhibit-refresh t))
509505 (funcall apply sections "--reverse" "--cached")
510506 (funcall apply sections "--reverse" "--reject"))
511507 (magit-refresh))
543539 (`(?Y ,_ ?D ) (push file resurrect))
544540 (`(?X ?R ,(or ? ?M ?D)) (push file rename)))))
545541 (unwind-protect
546 (let ((inhibit-magit-refresh t))
542 (let ((magit-inhibit-refresh t))
547543 (magit-wip-commit-before-change files " before discard")
548544 (when resolve
549545 (magit-discard-files--resolve (nreverse resolve)))
00 ;;; magit-autorevert.el --- revert buffers when files in repository change -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2010-2020 The Magit Project Contributors
2 ;; Copyright (C) 2010-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
77 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9
10 ;; SPDX-License-Identifier: GPL-3.0-or-later
911
1012 ;; Magit is free software; you can redistribute it and/or modify it
1113 ;; under the terms of the GNU General Public License as published by
2123 ;; along with Magit. If not, see http://www.gnu.org/licenses.
2224
2325 ;;; Code:
24
25 (require 'cl-lib)
26 (require 'dash)
2726
2827 (require 'magit-git)
2928
00 ;;; magit-bisect.el --- bisect support for Magit -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2011-2020 The Magit Project Contributors
2 ;; Copyright (C) 2011-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
77 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9
10 ;; SPDX-License-Identifier: GPL-3.0-or-later
911
1012 ;; Magit is free software; you can redistribute it and/or modify it
1113 ;; under the terms of the GNU General Public License as published by
5456 ;;; Commands
5557
5658 ;;;###autoload (autoload 'magit-bisect "magit-bisect" nil t)
57 (define-transient-command magit-bisect ()
59 (transient-define-prefix magit-bisect ()
5860 "Narrow in on the commit that introduced a bug."
5961 :man-page "git-bisect"
60 ["Actions"
62 [:class transient-subgroups
6163 :if-not magit-bisect-in-progress-p
62 ("B" "Start" magit-bisect-start)
63 ("s" "Start script" magit-bisect-run)]
64 ["Arguments"
65 ("-n" "Don't checkout commits" "--no-checkout")
66 ("-p" "Follow only first parent of a merge" "--first-parent"
67 :if (lambda () (version<= "2.29" (magit-git-version))))
68 (6 magit-bisect:--term-old
69 :if (lambda () (version<= "2.7" (magit-git-version))))
70 (6 magit-bisect:--term-new
71 :if (lambda () (version<= "2.7" (magit-git-version))))]
72 ["Actions"
73 ("B" "Start" magit-bisect-start)
74 ("s" "Start script" magit-bisect-run)]]
6475 ["Actions"
6576 :if magit-bisect-in-progress-p
6677 ("B" "Bad" magit-bisect-bad)
6778 ("g" "Good" magit-bisect-good)
79 (6 "m" "Mark" magit-bisect-mark
80 :if (lambda () (version<= "2.7" (magit-git-version))))
6881 ("k" "Skip" magit-bisect-skip)
6982 ("r" "Reset" magit-bisect-reset)
7083 ("s" "Run script" magit-bisect-run)])
7184
72 ;;;###autoload
73 (defun magit-bisect-start (bad good)
85 (transient-define-argument magit-bisect:--term-old ()
86 :description "Old/good term"
87 :class 'transient-option
88 :key "=o"
89 :argument "--term-old=")
90
91 (transient-define-argument magit-bisect:--term-new ()
92 :description "New/bad term"
93 :class 'transient-option
94 :key "=n"
95 :argument "--term-new=")
96
97 ;;;###autoload
98 (defun magit-bisect-start (bad good args)
7499 "Start a bisect session.
75100
76101 Bisecting a bug means to find the commit that introduced it.
77 This command starts such a bisect session by asking for a know
78 good and a bad commit. To move the session forward use the
102 This command starts such a bisect session by asking for a known
103 good and a known bad commit. To move the session forward use the
79104 other actions from the bisect transient command (\
80105 \\<magit-status-mode-map>\\[magit-bisect])."
81106 (interactive (if (magit-bisect-in-progress-p)
83108 (magit-bisect-start-read-args)))
84109 (unless (magit-rev-ancestor-p good bad)
85110 (user-error
86 "The good revision (%s) has to be an ancestor of the bad one (%s)"
87 good bad))
111 "The %s revision (%s) has to be an ancestor of the %s one (%s)"
112 (or (transient-arg-value "--term-old=" args) "good")
113 good
114 (or (transient-arg-value "--term-new=" args) "bad")
115 bad))
88116 (when (magit-anything-modified-p)
89117 (user-error "Cannot bisect with uncommitted changes"))
90 (magit-git-bisect "start" (list bad good) t))
118 (magit-git-bisect "start" (list args bad good) t))
91119
92120 (defun magit-bisect-start-read-args ()
93 (let ((b (magit-read-branch-or-commit "Start bisect with bad revision")))
94 (list b (magit-read-other-branch-or-commit "Good revision" b))))
121 (let* ((args (transient-args 'magit-bisect))
122 (bad (magit-read-branch-or-commit
123 (format "Start bisect with %s revision"
124 (or (transient-arg-value "--term-new=" args)
125 "bad")))))
126 (list bad
127 (magit-read-other-branch-or-commit
128 (format "%s revision" (or (transient-arg-value "--term-old=" args)
129 "Good"))
130 bad)
131 args)))
95132
96133 ;;;###autoload
97134 (defun magit-bisect-reset ()
107144 Use this after you have asserted that the commit does not contain
108145 the bug in question."
109146 (interactive)
110 (magit-git-bisect "good"))
147 (magit-git-bisect (or (cadr (magit-bisect-terms))
148 (user-error "Not bisecting"))))
111149
112150 ;;;###autoload
113151 (defun magit-bisect-bad ()
115153 Use this after you have asserted that the commit does contain the
116154 bug in question."
117155 (interactive)
118 (magit-git-bisect "bad"))
156 (magit-git-bisect (or (car (magit-bisect-terms))
157 (user-error "Not bisecting"))))
158
159 ;;;###autoload
160 (defun magit-bisect-mark ()
161 "While bisecting, mark the current commit with a bisect term.
162 During a bisect using alternate terms, commits can still be
163 marked with `magit-bisect-good' and `magit-bisect-bad', as those
164 commands map to the correct term (\"good\" to --term-old's value
165 and \"bad\" to --term-new's). However, in some cases, it can be
166 difficult to keep that mapping straight in your head; this
167 command provides an interface that exposes the underlying terms."
168 (interactive)
169 (magit-git-bisect
170 (pcase-let ((`(,term-new ,term-old) (or (magit-bisect-terms)
171 (user-error "Not bisecting"))))
172 (pcase (read-char-choice
173 (format "Mark HEAD as %s ([n]ew) or %s ([o]ld)"
174 term-new term-old)
175 (list ?n ?o))
176 (?n term-new)
177 (?o term-old)))))
119178
120179 ;;;###autoload
121180 (defun magit-bisect-skip ()
126185 (magit-git-bisect "skip"))
127186
128187 ;;;###autoload
129 (defun magit-bisect-run (cmdline &optional bad good)
188 (defun magit-bisect-run (cmdline &optional bad good args)
130189 "Bisect automatically by running commands after each step.
131190
132191 Unlike `git bisect run' this can be used before bisecting has
136195 (magit-bisect-start-read-args))))
137196 (cons (read-shell-command "Bisect shell command: ") args)))
138197 (when (and bad good)
139 (magit-bisect-start bad good))
198 (magit-bisect-start bad good args))
140199 (magit-git-bisect "run" (list shell-file-name shell-command-switch cmdline)))
141200
142201 (defun magit-git-bisect (subcommand &optional args no-assert)
169228 (defun magit-bisect-in-progress-p ()
170229 (file-exists-p (magit-git-dir "BISECT_LOG")))
171230
231 (defun magit-bisect-terms ()
232 (magit-file-lines (magit-git-dir "BISECT_TERMS")))
233
172234 (defun magit-insert-bisect-output ()
173235 "While bisecting, insert section with output from `git bisect'."
174236 (when (magit-bisect-in-progress-p)
00 ;;; magit-blame.el --- blame support for Magit -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2012-2020 The Magit Project Contributors
2 ;; Copyright (C) 2012-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
77 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9
10 ;; SPDX-License-Identifier: GPL-3.0-or-later
911
1012 ;; Magit is free software; you can redistribute it and/or modify it
1113 ;; under the terms of the GNU General Public License as published by
2628 ;; the revision which last modified the line.
2729
2830 ;;; Code:
29
30 (eval-when-compile
31 (require 'subr-x))
3231
3332 (require 'magit)
3433
5554 "List of styles used to visualize blame information.
5655
5756 Each entry has the form (IDENT (KEY . VALUE)...). IDENT has
58 to be a symbol uniquely identifing the style. The following
57 to be a symbol uniquely identifying the style. The following
5958 KEYs are recognized:
6059
6160 `show-lines'
283282 (define-key map (kbd "q") 'magit-blame-quit)
284283 (define-key map (kbd "M-w") 'magit-blame-copy-hash)
285284 (define-key map (kbd "SPC") 'magit-diff-show-or-scroll-up)
285 (define-key map (kbd "S-SPC") 'magit-diff-show-or-scroll-down)
286286 (define-key map (kbd "DEL") 'magit-diff-show-or-scroll-down)
287287 map)
288288 "Keymap for `magit-blame-read-only-mode'.")
473473
474474 (defun magit-blame--parse-chunk (type)
475475 (let (chunk revinfo)
476 (looking-at "^\\(.\\{40\\}\\) \\([0-9]+\\) \\([0-9]+\\) \\([0-9]+\\)")
476 (unless (looking-at "^\\(.\\{40\\}\\) \\([0-9]+\\) \\([0-9]+\\) \\([0-9]+\\)")
477 (error "Blaming failed due to unexpected output: %s"
478 (buffer-substring-no-properties (point) (line-end-position))))
477479 (with-slots (orig-rev orig-file prev-rev prev-file)
478480 (setq chunk (magit-blame-chunk
479481 :orig-rev (match-string 1)
672674 (propertize
673675 (concat (propertize "\s" 'display '(space :height (2)))
674676 (propertize "\n" 'line-height t))
675 'font-lock-face (list :background
676 (face-attribute 'magit-blame-heading
677 :background nil t))))
677 'font-lock-face `(:background
678 ,(face-attribute 'magit-blame-heading
679 :background nil t)
680 ,@(and (>= emacs-major-version 27) '(:extend t)))))
678681
679682 (defun magit-blame--format-time-string (time tz)
680683 (let* ((time-format (or (magit-blame--style-get 'time-format)
707710 ;;; Commands
708711
709712 ;;;###autoload (autoload 'magit-blame-echo "magit-blame" nil t)
710 (define-suffix-command magit-blame-echo (args)
713 (transient-define-suffix magit-blame-echo (args)
711714 "For each line show the revision in which it was added.
712715 Show the information about the chunk at point in the echo area
713716 when moving between chunks. Unlike other blaming commands, do
732735 (magit-blame--update-overlays)))
733736
734737 ;;;###autoload (autoload 'magit-blame-addition "magit-blame" nil t)
735 (define-suffix-command magit-blame-addition (args)
738 (transient-define-suffix magit-blame-addition (args)
736739 "For each line show the revision in which it was added."
737740 (interactive (list (magit-blame-arguments)))
738741 (magit-blame--pre-blame-assert 'addition)
740743 (magit-blame--run args))
741744
742745 ;;;###autoload (autoload 'magit-blame-removal "magit-blame" nil t)
743 (define-suffix-command magit-blame-removal (args)
746 (transient-define-suffix magit-blame-removal (args)
744747 "For each line show the revision in which it was removed."
745748 :if-nil 'buffer-file-name
746749 (interactive (list (magit-blame-arguments)))
751754 (magit-blame--run args))
752755
753756 ;;;###autoload (autoload 'magit-blame-reverse "magit-blame" nil t)
754 (define-suffix-command magit-blame-reverse (args)
757 (transient-define-suffix magit-blame-reverse (args)
755758 "For each line show the last revision in which it still exists."
756759 :if-nil 'buffer-file-name
757760 (interactive (list (magit-blame-arguments)))
810813 (goto-char (point-min))
811814 (forward-line (1- orig-line))))
812815
813 (define-suffix-command magit-blame-quit ()
816 (transient-define-suffix magit-blame-quit ()
814817 "Turn off Magit-Blame mode.
815818 If the buffer was created during a recursive blame,
816819 then also kill the buffer."
884887 ;;; Popup
885888
886889 ;;;###autoload (autoload 'magit-blame "magit-blame" nil t)
887 (define-transient-command magit-blame ()
890 (transient-define-prefix magit-blame ()
888891 "Show the commits that added or removed lines in the visited file."
889892 :man-page "git-blame"
890893 :value '("-w")
901904 ("q" "Quit blaming" magit-blame-quit)]
902905 ["Refresh"
903906 :if-non-nil magit-blame-mode
904 ("c" "Cycle style" magit-blame-cycle-style)])
907 ("c" "Cycle style" magit-blame-cycle-style :transient t)])
905908
906909 (defun magit-blame-arguments ()
907910 (transient-args 'magit-blame))
908911
909 (define-infix-argument magit-blame:-M ()
912 (transient-define-argument magit-blame:-M ()
910913 :description "Detect lines moved or copied within a file"
911914 :class 'transient-option
912915 :argument "-M"
913916 :reader 'transient-read-number-N+)
914917
915 (define-infix-argument magit-blame:-C ()
918 (transient-define-argument magit-blame:-C ()
916919 :description "Detect lines moved or copied between files"
917920 :class 'transient-option
918921 :argument "-C"
00 ;;; magit-bookmark.el --- bookmark support for Magit -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2010-2020 The Magit Project Contributors
2 ;; Copyright (C) 2010-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
99
1010 ;; Inspired by an earlier implementation by Yuri Khan.
11
12 ;; SPDX-License-Identifier: GPL-3.0-or-later
1113
1214 ;; Magit is free software; you can redistribute it and/or modify it
1315 ;; under the terms of the GNU General Public License as published by
2830
2931 ;;; Code:
3032
31 (eval-when-compile
32 (require 'subr-x))
33
3433 (require 'magit)
3534 (require 'bookmark)
3635
4241 and the buffer-local values of the variables referenced in its
4342 `magit-bookmark-variables' property."
4443 (if (plist-member (symbol-plist major-mode) 'magit-bookmark-variables)
45 (let ((bookmark (bookmark-make-record-default 'no-file)))
44 ;; `bookmark-make-record-default's return value does not match
45 ;; (NAME . ALIST), even though it is used as the default value
46 ;; of `bookmark-make-record-function', which states that such
47 ;; functions must do that. See #4356.
48 (let ((bookmark (cons nil (bookmark-make-record-default 'no-file))))
4649 (bookmark-prop-set bookmark 'handler 'magit--handle-bookmark)
4750 (bookmark-prop-set bookmark 'mode major-mode)
4851 (bookmark-prop-set bookmark 'filename (magit-toplevel))
8689 hidden)
8790 (magit-section-hide child)
8891 (magit-section-show child)))))
92 ;; Compatibility with `bookmark+' package. See #4356.
93 (when (bound-and-true-p bmkp-jump-display-function)
94 (funcall bmkp-jump-display-function (current-buffer)))
8995 nil))
9096
9197 (cl-defgeneric magit-bookmark-name ()
00 ;;; magit-branch.el --- branch support -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2010-2020 The Magit Project Contributors
2 ;; Copyright (C) 2010-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
77 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9
10 ;; SPDX-License-Identifier: GPL-3.0-or-later
911
1012 ;; Magit is free software; you can redistribute it and/or modify it
1113 ;; under the terms of the GNU General Public License as published by
3032
3133 ;;; Code:
3234
33 (eval-when-compile
34 (require 'subr-x))
35
3635 (require 'magit)
3736 (require 'magit-reset)
3837
200199 ;;; Commands
201200
202201 ;;;###autoload (autoload 'magit-branch "magit" nil t)
203 (define-transient-command magit-branch (branch)
202 (transient-define-prefix magit-branch (branch)
204203 "Add, configure or remove a branch."
205204 :man-page "git-branch"
205 ["Arguments"
206 (7 "-r" "Recurse submodules when checking out an existing branch"
207 "--recurse-submodules"
208 :if (lambda () (version<= "2.13" (magit-git-version))))]
206209 ["Variables"
207210 :if (lambda ()
208211 (and magit-branch-direct-configure
234237 (interactive (list (magit-get-current-branch)))
235238 (transient-setup 'magit-branch nil nil :scope branch))
236239
237 ;;;###autoload
238 (defun magit-checkout (revision)
240 (defun magit-branch-arguments ()
241 (transient-args 'magit-branch))
242
243 ;;;###autoload
244 (defun magit-checkout (revision &optional args)
239245 "Checkout REVISION, updating the index and the working tree.
240246 If REVISION is a local branch, then that becomes the current
241247 branch. If it is something else, then `HEAD' becomes detached.
242248 Checkout fails if the working tree or the staging area contain
243249 changes.
244250 \n(git checkout REVISION)."
245 (interactive (list (magit-read-other-branch-or-commit "Checkout")))
251 (interactive (list (magit-read-other-branch-or-commit "Checkout")
252 (magit-branch-arguments)))
246253 (when (string-match "\\`heads/\\(.+\\)" revision)
247254 (setq revision (match-string 1 revision)))
248 (magit-run-git "checkout" revision))
255 (magit-run-git "checkout" args revision))
249256
250257 ;;;###autoload
251258 (defun magit-branch-create (branch start-point)
256263 (magit-refresh))
257264
258265 ;;;###autoload
259 (defun magit-branch-and-checkout (branch start-point)
266 (defun magit-branch-and-checkout (branch start-point &optional args)
260267 "Create and checkout BRANCH at branch or revision START-POINT."
261 (interactive (magit-branch-read-args "Create and checkout branch"))
268 (interactive (append (magit-branch-read-args "Create and checkout branch")
269 (list (magit-branch-arguments))))
262270 (if (string-match-p "^stash@{[0-9]+}$" start-point)
263271 (magit-run-git "stash" "branch" branch start-point)
264 (magit-call-git "checkout" "-b" branch start-point)
272 (magit-call-git "checkout" args "-b" branch start-point)
265273 (magit-branch-maybe-adjust-upstream branch start-point)
266274 (magit-refresh)))
267275
338346 (t
339347 (list choice (magit-read-starting-point "Create" choice))))))
340348 (if (not start-point)
341 (magit-checkout branch)
342 (when (magit-anything-modified-p)
349 (magit-checkout branch (magit-branch-arguments))
350 (when (magit-anything-modified-p t)
343351 (user-error "Cannot checkout when there are uncommitted changes"))
344352 (magit-branch-and-checkout branch start-point)
345353 (when (magit-remote-branch-p start-point)
497505 (or (and (not (equal branch atpoint)) atpoint)
498506 (magit-get-upstream-branch branch)))
499507 current-prefix-arg)))
500 (let ((inhibit-magit-refresh t))
508 (let ((magit-inhibit-refresh t))
501509 (if (equal branch (magit-get-current-branch))
502510 (if (and (magit-anything-modified-p)
503511 (not (yes-or-no-p
561569 ((string-match "^refs/remotes/\\([^/]+\\)" (car refs))
562570 (let* ((remote (match-string 1 (car refs)))
563571 (offset (1+ (length remote))))
564 ;; Assume the branches actually still exists on the remote.
565 (magit-run-git-async
566 "push"
567 (and (or force magit-branch-delete-never-verify) "--no-verify")
568 remote
569 (--map (concat ":" (substring it offset)) branches))
570 ;; If that is not the case, then this deletes the tracking branches.
571 (set-process-sentinel
572 magit-this-process
573 (apply-partially 'magit-delete-remote-branch-sentinel remote refs))))
572 (cond
573 ((magit-confirm 'delete-branch-on-remote
574 "Delete %s on the remote (not just locally)"
575 "Delete %i branches on the remote (not just locally)"
576 'noabort branches)
577 ;; The ref may actually point at another rev on the remote,
578 ;; but this is better than nothing.
579 (dolist (ref refs)
580 (message "Delete %s (was %s)" ref
581 (magit-rev-parse "--short" ref)))
582 ;; Assume the branches actually still exist on the remote.
583 (magit-run-git-async
584 "push"
585 (and (or force magit-branch-delete-never-verify) "--no-verify")
586 remote
587 (--map (concat ":" (substring it offset)) branches))
588 ;; If that is not the case, then this deletes the tracking branches.
589 (set-process-sentinel
590 magit-this-process
591 (apply-partially 'magit-delete-remote-branch-sentinel remote refs)))
592 (t
593 (dolist (ref refs)
594 (message "Delete %s (was %s)" ref
595 (magit-rev-parse "--short" ref))
596 (magit-call-git "update-ref" "-d" ref))
597 (magit-refresh)))))
574598 ((> (length branches) 1)
575599 (setq branches (delete (magit-get-current-branch) branches))
576600 (mapc 'magit-branch-maybe-delete-pr-remote branches)
578602 (magit-run-git "branch" (if force "-D" "-d") branches))
579603 (t ; And now for something completely different.
580604 (let* ((branch (car branches))
581 (prompt (format "Branch %s is checked out. " branch)))
605 (prompt (format "Branch %s is checked out. " branch))
606 (main (magit-main-branch)))
582607 (when (equal branch (magit-get-current-branch))
583 (pcase (if (or (equal branch "master")
584 (not (magit-rev-verify "master")))
608 (pcase (if (or (equal branch main)
609 (not main))
585610 (magit-read-char-case prompt nil
586611 (?d "[d]etach HEAD & delete" 'detach)
587612 (?a "[a]bort" 'abort))
588613 (magit-read-char-case prompt nil
589 (?d "[d]etach HEAD & delete" 'detach)
590 (?c "[c]heckout master & delete" 'master)
591 (?a "[a]bort" 'abort)))
614 (?d "[d]etach HEAD & delete" 'detach)
615 (?c (format "[c]heckout %s & delete" main) 'main)
616 (?a "[a]bort" 'abort)))
592617 (`detach (unless (or (equal force '(4))
593618 (member branch force)
594619 (magit-branch-merged-p branch t))
596621 "Delete unmerged branch %s" ""
597622 nil (list branch)))
598623 (magit-call-git "checkout" "--detach"))
599 (`master (unless (or (equal force '(4))
624 (`main (unless (or (equal force '(4))
600625 (member branch force)
601 (magit-branch-merged-p branch "master"))
626 (magit-branch-merged-p branch main))
602627 (magit-confirm 'delete-unmerged-branch
603628 "Delete unmerged branch %s" ""
604629 nil (list branch)))
605 (magit-call-git "checkout" "master"))
630 (magit-call-git "checkout" main))
606631 (`abort (user-error "Abort")))
607632 (setq force t))
608633 (magit-branch-maybe-delete-pr-remote branch)
685710 (magit-call-git "branch" (if force "-M" "-m") old new)
686711 (when magit-branch-rename-push-target
687712 (let ((remote (magit-get-push-remote old))
688 (old-specific (magit-get "branch" old "pushRemote"))
689 (new-specific (magit-get "branch" new "pushRemote")))
690 (when (and old-specific (or force (not new-specific)))
691 ;; Keep the target setting branch specific, even if that is
713 (old-specified (magit-get "branch" old "pushRemote"))
714 (new-specified (magit-get "branch" new "pushRemote")))
715 (when (and old-specified (or force (not new-specified)))
716 ;; Keep the target setting branch specified, even if that is
692717 ;; redundant. But if a branch by the same name existed before
693718 ;; and the rename isn't forced, then do not change a leftover
694719 ;; setting. Such a leftover setting may or may not conform to
695720 ;; what we expect here...
696 (magit-set old-specific "branch" new "pushRemote"))
721 (magit-set old-specified "branch" new "pushRemote"))
697722 (when (and (equal (magit-get-push-remote new) remote)
698723 ;; ...and if it does not, then we must abort.
699724 (not (eq magit-branch-rename-push-target 'local-only))
761786 ;;; Configure
762787
763788 ;;;###autoload (autoload 'magit-branch-configure "magit-branch" nil t)
764 (define-transient-command magit-branch-configure (branch)
789 (transient-define-prefix magit-branch-configure (branch)
765790 "Configure a branch."
766791 :man-page "git-branch"
767792 [:description
782807 (interactive
783808 (list (or (and (not current-prefix-arg)
784809 (not (and magit-branch-direct-configure
785 (eq current-transient-command 'magit-branch)))
810 (eq transient-current-command 'magit-branch)))
786811 (magit-get-current-branch))
787812 (magit--read-branch-scope))))
788813 (transient-setup 'magit-branch-configure nil nil :scope branch))
794819 (format (oref obj variable) "<name>"))
795820 "Configure branch")))
796821
797 (define-suffix-command magit-branch.<branch>.description (branch)
822 (transient-define-suffix magit-branch.<branch>.description (branch)
798823 "Edit the description of BRANCH."
799824 :class 'magit--git-variable
800825 :transient nil
801826 :variable "branch.%s.description"
802 (interactive (list (oref current-transient-prefix scope)))
827 (interactive (list (oref transient-current-prefix scope)))
803828 (magit-run-git-with-editor "branch" "--edit-description" branch))
804829
805830 (add-hook 'find-file-hook 'magit-branch-description-check-buffers)
811836 (defclass magit--git-branch:upstream (magit--git-variable)
812837 ((format :initform " %k %m %M\n %r %R")))
813838
814 (define-infix-command magit-branch.<branch>.merge/remote ()
839 (transient-define-infix magit-branch.<branch>.merge/remote ()
815840 :class 'magit--git-branch:upstream)
816841
817842 (cl-defmethod transient-init-value ((obj magit--git-branch:upstream))
849874 (propertize value 'face 'transient-argument)
850875 (propertize "unset" 'face 'transient-inactive-argument)))
851876
852 (define-infix-command magit-branch.<branch>.rebase ()
877 (transient-define-infix magit-branch.<branch>.rebase ()
853878 :class 'magit--git-variable:choices
854879 :scope 'magit--read-branch-scope
855880 :variable "branch.%s.rebase"
857882 :choices '("true" "false")
858883 :default "false")
859884
860 (define-infix-command magit-branch.<branch>.pushRemote ()
885 (transient-define-infix magit-branch.<branch>.pushRemote ()
861886 :class 'magit--git-variable:choices
862887 :scope 'magit--read-branch-scope
863888 :variable "branch.%s.pushRemote"
864889 :fallback "remote.pushDefault"
865890 :choices 'magit-list-remotes)
866891
867 (define-infix-command magit-pull.rebase ()
892 (transient-define-infix magit-pull.rebase ()
868893 :class 'magit--git-variable:choices
869894 :variable "pull.rebase"
870895 :choices '("true" "false")
871896 :default "false")
872897
873 (define-infix-command magit-remote.pushDefault ()
898 (transient-define-infix magit-remote.pushDefault ()
874899 :class 'magit--git-variable:choices
875900 :variable "remote.pushDefault"
876901 :choices 'magit-list-remotes)
877902
878 (define-infix-command magit-branch.autoSetupMerge ()
903 (transient-define-infix magit-branch.autoSetupMerge ()
879904 :class 'magit--git-variable:choices
880905 :variable "branch.autoSetupMerge"
881906 :choices '("always" "true" "false")
882907 :default "true")
883908
884 (define-infix-command magit-branch.autoSetupRebase ()
909 (transient-define-infix magit-branch.autoSetupRebase ()
885910 :class 'magit--git-variable:choices
886911 :variable "branch.autoSetupRebase"
887912 :choices '("always" "local" "remote" "never")
00 ;;; magit-clone.el --- clone a repository -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2008-2020 The Magit Project Contributors
2 ;; Copyright (C) 2008-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
77 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9
10 ;; SPDX-License-Identifier: GPL-3.0-or-later
911
1012 ;; Magit is free software; you can redistribute it and/or modify it
1113 ;; under the terms of the GNU General Public License as published by
103105 ;;; Commands
104106
105107 ;;;###autoload (autoload 'magit-clone "magit-clone" nil t)
106 (define-transient-command magit-clone (&optional transient)
108 (transient-define-prefix magit-clone (&optional transient)
107109 "Clone a repository."
108110 :man-page "git-clone"
109111 ["Fetch arguments"
191193 (magit-clone-internal repository directory (cons "--mirror" args)))
192194
193195 (defun magit-clone-internal (repository directory args)
194 (run-hooks 'magit-credential-hook)
195 (setq directory (file-name-as-directory (expand-file-name directory)))
196 (magit-run-git-async "clone" args "--" repository
197 (magit-convert-filename-for-git directory))
198 ;; Don't refresh the buffer we're calling from.
199 (process-put magit-this-process 'inhibit-refresh t)
200 (set-process-sentinel
201 magit-this-process
202 (lambda (process event)
203 (when (memq (process-status process) '(exit signal))
204 (let ((magit-process-raise-error t))
205 (magit-process-sentinel process event)))
206 (when (and (eq (process-status process) 'exit)
207 (= (process-exit-status process) 0))
208 (unless (memq (car args) '("--bare" "--mirror"))
209 (let ((default-directory directory))
210 (when (or (eq magit-clone-set-remote.pushDefault t)
211 (and magit-clone-set-remote.pushDefault
212 (y-or-n-p "Set `remote.pushDefault' to \"origin\"? ")))
213 (setf (magit-get "remote.pushDefault") "origin"))
214 (unless magit-clone-set-remote-head
215 (magit-remote-unset-head "origin"))))
216 (with-current-buffer (process-get process 'command-buf)
217 (magit-status-setup-buffer directory))))))
196 (let* ((checkout (not (memq (car args) '("--bare" "--mirror"))))
197 (remote (or (transient-arg-value "--origin" args)
198 (magit-get "clone.defaultRemote")
199 "origin"))
200 (set-push-default
201 (and checkout
202 (or (eq magit-clone-set-remote.pushDefault t)
203 (and magit-clone-set-remote.pushDefault
204 (y-or-n-p (format "Set `remote.pushDefault' to %S? "
205 remote)))))))
206 (run-hooks 'magit-credential-hook)
207 (setq directory (file-name-as-directory (expand-file-name directory)))
208 (when (file-exists-p directory)
209 (if (file-directory-p directory)
210 (when (> (length (directory-files directory)) 2)
211 (let ((name (magit-clone--url-to-name repository)))
212 (unless (and name
213 (setq directory (file-name-as-directory
214 (expand-file-name name directory)))
215 (not (file-exists-p directory)))
216 (user-error "%s already exists" directory))))
217 (user-error "%s already exists and is not a directory" directory)))
218 (magit-run-git-async "clone" args "--" repository
219 (magit-convert-filename-for-git directory))
220 ;; Don't refresh the buffer we're calling from.
221 (process-put magit-this-process 'inhibit-refresh t)
222 (set-process-sentinel
223 magit-this-process
224 (lambda (process event)
225 (when (memq (process-status process) '(exit signal))
226 (let ((magit-process-raise-error t))
227 (magit-process-sentinel process event)))
228 (when (and (eq (process-status process) 'exit)
229 (= (process-exit-status process) 0))
230 (when checkout
231 (let ((default-directory directory))
232 (when set-push-default
233 (setf (magit-get "remote.pushDefault") remote))
234 (unless magit-clone-set-remote-head
235 (magit-remote-unset-head remote))))
236 (with-current-buffer (process-get process 'command-buf)
237 (magit-status-setup-buffer directory)))))))
218238
219239 (defun magit-clone-read-args ()
220240 (let ((repo (magit-clone-read-repository)))
225245 (funcall magit-clone-default-directory repo)
226246 magit-clone-default-directory)
227247 nil nil
228 (and (string-match "\\([^/:]+?\\)\\(/?\\.git\\)?$" repo)
229 (match-string 1 repo)))
248 (magit-clone--url-to-name repo))
230249 (transient-args 'magit-clone))))
231250
232251 (defun magit-clone-read-repository ()
241260 (?l "or [l]ocal url"
242261 (concat "file://" (read-directory-name "Clone repository: file://")))))
243262
263 (defun magit-clone--url-to-name (url)
264 (and (string-match "\\([^/:]+?\\)\\(/?\\.git\\)?$" url)
265 (match-string 1 url)))
266
244267 (defun magit-clone--name-to-url (name)
245 (or (-some
268 (or (seq-some
246269 (pcase-lambda (`(,re ,host ,user))
247270 (and (string-match re name)
248271 (let ((repo (match-string 1 name)))
00 ;;; magit-commit.el --- create Git commits -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2008-2020 The Magit Project Contributors
2 ;; Copyright (C) 2008-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
77 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9
10 ;; SPDX-License-Identifier: GPL-3.0-or-later
911
1012 ;; Magit is free software; you can redistribute it and/or modify it
1113 ;; under the terms of the GNU General Public License as published by
3335
3436 (eval-when-compile (require 'epa)) ; for `epa-protocol'
3537 (eval-when-compile (require 'epg))
36 (eval-when-compile (require 'subr-x))
3738
3839 ;;; Options
3940
4041 (defcustom magit-commit-ask-to-stage 'verbose
41 "Whether to ask to stage all unstaged changes when committing and nothing is staged."
42 "Whether to ask to stage everything when committing and nothing is staged."
4243 :package-version '(magit . "2.3.0")
4344 :group 'magit-commands
4445 :type '(choice (const :tag "Ask" t)
99100 ;;; Popup
100101
101102 ;;;###autoload (autoload 'magit-commit "magit-commit" nil t)
102 (define-transient-command magit-commit ()
103 (transient-define-prefix magit-commit ()
103104 "Create a new commit or replace an existing commit."
104105 :info-manual "(magit)Initiating a Commit"
105106 :man-page "git-commit"
125126 ("f" "Fixup" magit-commit-fixup)
126127 ("s" "Squash" magit-commit-squash)
127128 ("A" "Augment" magit-commit-augment)
128 (6 "x" "Absorb changes" magit-commit-absorb)]
129 (6 "x" "Absorb changes" magit-commit-autofixup)
130 (6 "X" "Absorb modules" magit-commit-absorb-modules)]
129131 [""
130132 ("F" "Instant fixup" magit-commit-instant-fixup)
131133 ("S" "Instant squash" magit-commit-instant-squash)]]
137139 (defun magit-commit-arguments nil
138140 (transient-args 'magit-commit))
139141
140 (define-infix-argument magit:--gpg-sign ()
142 (transient-define-argument magit:--gpg-sign ()
141143 :description "Sign using gpg"
142144 :class 'transient-option
143145 :shortarg "-S"
144146 :argument "--gpg-sign="
145147 :allow-empty t
146 :reader 'magit-read-gpg-secret-key)
148 :reader 'magit-read-gpg-signing-key)
147149
148150 (defvar magit-gpg-secret-key-hist nil)
149151
150 (defun magit-read-gpg-secret-key (prompt &optional initial-input history)
152 (defun magit-read-gpg-secret-key
153 (prompt &optional initial-input history predicate)
151154 (require 'epa)
152 (let* ((keys (mapcar
153 (lambda (obj)
154 (let ((key (epg-sub-key-id (car (epg-key-sub-key-list obj))))
155 (author
156 (when-let ((id-obj (car (epg-key-user-id-list obj))))
157 (let ((id-str (epg-user-id-string id-obj)))
158 (if (stringp id-str)
159 id-str
160 (epg-decode-dn id-obj))))))
161 (propertize key 'display (concat key " " author))))
155 (let* ((keys (mapcan
156 (lambda (cert)
157 (and (or (not predicate)
158 (funcall predicate cert))
159 (let* ((key (car (epg-key-sub-key-list cert)))
160 (fpr (epg-sub-key-fingerprint key))
161 (id (epg-sub-key-id key))
162 (author
163 (when-let ((id-obj
164 (car (epg-key-user-id-list cert))))
165 (let ((id-str (epg-user-id-string id-obj)))
166 (if (stringp id-str)
167 id-str
168 (epg-decode-dn id-obj))))))
169 (list
170 (propertize fpr 'display
171 (concat (substring fpr 0 (- (length id)))
172 (propertize id 'face 'highlight)
173 " " author))))))
162174 (epg-list-keys (epg-make-context epa-protocol) nil t)))
163175 (choice (completing-read prompt keys nil nil nil
164176 history nil initial-input)))
165177 (set-text-properties 0 (length choice) nil choice)
166178 choice))
167179
168 (define-infix-argument magit-commit:--reuse-message ()
180 (defun magit-read-gpg-signing-key (prompt &optional initial-input history)
181 (magit-read-gpg-secret-key
182 prompt initial-input history
183 (lambda (cert)
184 (cl-some (lambda (key)
185 (memq 'sign (epg-sub-key-capability key)))
186 (epg-key-sub-key-list cert)))))
187
188 (transient-define-argument magit-commit:--reuse-message ()
169189 :description "Reuse commit message"
170190 :class 'transient-option
171191 :shortarg "-C"
216236 (if current-prefix-arg
217237 (not magit-commit-extend-override-date)
218238 magit-commit-extend-override-date)))
219 (when (setq args (magit-commit-assert args (not override-date)))
239 (when (setq args (magit-commit-assert args))
220240 (magit-commit-amend-assert)
221241 (let ((process-environment process-environment))
222242 (unless override-date
356376 (and (not strict)
357377 ;; ^ For amend variants that don't make sense otherwise.
358378 (or (member "--amend" args)
359 (member "--allow-empty" args))))
379 (member "--allow-empty" args)
380 (member "--reset-author" args)
381 (member "--author" args)
382 (member "--signoff" args)
383 (cl-find-if (lambda (a) (string-match-p "\\`--date=" a)) args))))
360384 (or args (list "--")))
361385 ((and (magit-rebase-in-progress-p)
362386 (not (magit-anything-unstaged-p))
385409 (defvar magit--reshelve-history nil)
386410
387411 ;;;###autoload
388 (defun magit-commit-reshelve (date)
412 (defun magit-commit-reshelve (date update-author &optional args)
389413 "Change the committer date and possibly the author date of `HEAD'.
390414
391 If you are the author of `HEAD', then both dates are changed,
392 otherwise only the committer date. The current time is used
393 as the initial minibuffer input and the original author (if
394 that is you) or committer date is available as the previous
395 history element."
415 The current time is used as the initial minibuffer input and the
416 original author or committer date is available as the previous
417 history element.
418
419 Both the author and the committer dates are changes, unless one
420 of the following is true, in which case only the committer date
421 is updated:
422 - You are not the author of the commit that is being reshelved.
423 - The command was invoked with a prefix argument.
424 - Non-interactively if UPDATE-AUTHOR is nil."
396425 (interactive
397 (let ((author-p (magit-rev-author-p "HEAD")))
398 (push (magit-rev-format (if author-p "%ad" "%cd") "HEAD"
426 (let ((update-author (and (magit-rev-author-p "HEAD")
427 (not current-prefix-arg))))
428 (push (magit-rev-format (if update-author "%ad" "%cd") "HEAD"
399429 (concat "--date=format:%F %T %z"))
400430 magit--reshelve-history)
401 (list (read-string (if author-p
431 (list (read-string (if update-author
402432 "Change author and committer dates to: "
403433 "Change committer date to: ")
404434 (cons (format-time-string "%F %T %z") 17)
405 'magit--reshelve-history))))
435 'magit--reshelve-history)
436 update-author
437 (magit-commit-arguments))))
406438 (let ((process-environment process-environment))
407439 (push (concat "GIT_COMMITTER_DATE=" date) process-environment)
408440 (magit-run-git "commit" "--amend" "--no-edit"
409 (and (magit-rev-author-p "HEAD")
410 (concat "--date=" date)))))
441 (and update-author (concat "--date=" date))
442 args)))
443
444 ;;;###autoload
445 (defun magit-commit-absorb-modules (phase commit)
446 "Spread modified modules across recent commits."
447 (interactive (list 'select (magit-get-upstream-branch)))
448 (let ((modules (magit-list-modified-modules)))
449 (unless modules
450 (user-error "There are no modified modules that could be absorbed"))
451 (when commit
452 (setq commit (magit-rebase-interactive-assert commit t)))
453 (if (and commit (eq phase 'run))
454 (progn
455 (dolist (module modules)
456 (when-let ((msg (magit-git-string
457 "log" "-1" "--format=%s"
458 (concat commit "..") "--" module)))
459 (magit-git "commit" "-m" (concat "fixup! " msg)
460 "--only" "--" module)))
461 (magit-refresh)
462 t)
463 (magit-log-select
464 (lambda (commit)
465 (magit-commit-absorb-modules 'run commit))
466 nil nil nil nil commit))))
411467
412468 ;;;###autoload (autoload 'magit-commit-absorb "magit-commit" nil t)
413 (define-transient-command magit-commit-absorb (phase commit args)
414 "Spread unstaged changes across recent commits.
469 (transient-define-prefix magit-commit-absorb (phase commit args)
470 "Spread staged changes across recent commits.
415471 With a prefix argument use a transient command to select infix
416 arguments. This command requires the git-autofixup script, which
417 is available from https://github.com/torbiak/git-autofixup."
472 arguments. This command requires git-absorb executable, which
473 is available from https://github.com/tummychow/git-absorb.
474 See `magit-commit-autofixup' for an alternative implementation."
418475 ["Arguments"
419 (magit-autofixup:--context)
420 (magit-autofixup:--strict)]
476 ("-f" "Skip safety checks" ("-f" "--force"))
477 ("-v" "Display more output" ("-v" "--verbose"))]
421478 ["Actions"
422479 ("x" "Absorb" magit-commit-absorb)]
423480 (interactive (if current-prefix-arg
427484 (transient-args 'magit-commit-absorb))))
428485 (if (eq phase 'transient)
429486 (transient-setup 'magit-commit-absorb)
487 (unless (executable-find "git-absorb")
488 (user-error "This command requires the git-absorb executable, which %s"
489 "is available from https://github.com/tummychow/git-absorb"))
490 (unless (magit-anything-staged-p)
491 (if (magit-anything-unstaged-p)
492 (if (y-or-n-p "Nothing staged. Absorb all unstaged changes? ")
493 (magit-with-toplevel
494 (magit-run-git "add" "-u" "."))
495 (user-error "Abort"))
496 (user-error "There are no changes that could be absorbed")))
497 (when commit
498 (setq commit (magit-rebase-interactive-assert commit t)))
499 (if (and commit (eq phase 'run))
500 (progn (magit-run-git-async "absorb" "-v" args "-b" commit) t)
501 (magit-log-select
502 (lambda (commit)
503 (with-no-warnings ; about non-interactive use
504 (magit-commit-absorb 'run commit args)))
505 nil nil nil nil commit))))
506
507 ;;;###autoload (autoload 'magit-commit-autofixup "magit-commit" nil t)
508 (transient-define-prefix magit-commit-autofixup (phase commit args)
509 "Spread staged or unstaged changes across recent commits.
510
511 If there are any staged then spread only those, otherwise
512 spread all unstaged changes. With a prefix argument use a
513 transient command to select infix arguments.
514
515 This command requires the git-autofixup script, which is
516 available from https://github.com/torbiak/git-autofixup.
517 See `magit-commit-absorb' for an alternative implementation."
518 ["Arguments"
519 (magit-autofixup:--context)
520 (magit-autofixup:--strict)]
521 ["Actions"
522 ("x" "Absorb" magit-commit-autofixup)]
523 (interactive (if current-prefix-arg
524 (list 'transient nil nil)
525 (list 'select
526 (magit-get-upstream-branch)
527 (transient-args 'magit-commit-autofixup))))
528 (if (eq phase 'transient)
529 (transient-setup 'magit-commit-autofixup)
430530 (unless (executable-find "git-autofixup")
431531 (user-error "This command requires the git-autofixup script, which %s"
432532 "is available from https://github.com/torbiak/git-autofixup"))
433 (when (magit-anything-staged-p)
434 (user-error "Cannot absorb when there are staged changes"))
435 (unless (magit-anything-unstaged-p)
436 (user-error "There are no unstaged changes that could be absorbed"))
533 (unless (magit-anything-modified-p)
534 (user-error "There are no changes that could be absorbed"))
437535 (when commit
438536 (setq commit (magit-rebase-interactive-assert commit t)))
439537 (if (and commit (eq phase 'run))
441539 (magit-log-select
442540 (lambda (commit)
443541 (with-no-warnings ; about non-interactive use
444 (magit-commit-absorb 'run commit args)))
542 (magit-commit-autofixup 'run commit args)))
445543 nil nil nil nil commit))))
446544
447 (define-infix-argument magit-autofixup:--context ()
545 (transient-define-argument magit-autofixup:--context ()
448546 :description "Diff context lines"
449547 :class 'transient-option
450548 :shortarg "-c"
451549 :argument "--context="
452550 :reader 'transient-read-number-N0)
453551
454 (define-infix-argument magit-autofixup:--strict ()
552 (transient-define-argument magit-autofixup:--strict ()
455553 :description "Strictness"
456554 :class 'transient-option
457555 :shortarg "-s"
471569 (let ((args (car (magit-diff-arguments)))
472570 (magit-inhibit-save-previous-winconf 'unset)
473571 (magit-display-buffer-noselect t)
474 (inhibit-quit nil))
572 (inhibit-quit nil)
573 (display-buffer-overriding-action '(nil (inhibit-same-window t))))
475574 (message "Diffing changes to be committed (C-g to abort diffing)")
476575 (cl-case last-command
477576 (magit-commit
490589 ;; Mention `magit-diff-while-committing' because that's
491590 ;; always what I search for when I try to find this line.
492591 (add-hook 'server-switch-hook 'magit-commit-diff)
592 (add-hook 'with-editor-filter-visit-hook 'magit-commit-diff)
493593
494594 (add-to-list 'with-editor-server-window-alist
495595 (cons git-commit-filename-regexp 'switch-to-buffer))
00 ;;; magit-core.el --- core functionality -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2010-2020 The Magit Project Contributors
2 ;; Copyright (C) 2010-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
77 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9
10 ;; SPDX-License-Identifier: GPL-3.0-or-later
911
1012 ;; Magit is free software; you can redistribute it and/or modify it
1113 ;; under the terms of the GNU General Public License as published by
00 ;;; magit-diff.el --- inspect Git diffs -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2010-2020 The Magit Project Contributors
2 ;; Copyright (C) 2010-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
77 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9
10 ;; SPDX-License-Identifier: GPL-3.0-or-later
911
1012 ;; Magit is free software; you can redistribute it and/or modify it
1113 ;; under the terms of the GNU General Public License as published by
2729
2830 ;;; Code:
2931
30 (eval-when-compile
31 (require 'ansi-color)
32 (require 'subr-x))
33
32 (require 'magit-core)
3433 (require 'git-commit)
35 (require 'magit-core)
34
35 (eval-when-compile (require 'ansi-color))
36 (require 'diff-mode)
37 (require 'smerge-mode)
3638
3739 ;; For `magit-diff-popup'
3840 (declare-function magit-stash-show "magit-stash" (stash &optional args files))
5456 (declare-function magit-merge-in-progress-p "magit-merge" ())
5557 (declare-function magit--merge-range "magit-merge" (&optional head))
5658 ;; For `magit-diff--dwim'
59 (declare-function forge--pullreq-range "forge-pullreq"
60 (pullreq &optional endpoints))
5761 (declare-function forge--pullreq-ref "forge-pullreq" (pullreq))
5862 ;; For `magit-diff-wash-diff'
5963 (declare-function ansi-color-apply-on-region "ansi-color" (begin end))
6064
6165 (eval-when-compile
62 (cl-pushnew 'base-ref eieio--known-slot-names)
6366 (cl-pushnew 'orig-rev eieio--known-slot-names)
6467 (cl-pushnew 'action-type eieio--known-slot-names)
6568 (cl-pushnew 'target eieio--known-slot-names))
6669
67 (require 'diff-mode)
68 (require 'smerge-mode)
69
7070 ;;; Options
7171 ;;;; Diff Mode
7272
7373 (defgroup magit-diff nil
7474 "Inspect and manipulate Git diffs."
7575 :link '(info-link "(magit)Diffing")
76 :group 'magit-commands
7677 :group 'magit-modes)
7778
7879 (defcustom magit-diff-mode-hook nil
280281 :group 'magit-diff
281282 :type 'boolean)
282283
284 (defcustom magit-diff-extra-stat-arguments nil
285 "Additional arguments to be used alongside `--stat'.
286
287 A list of zero or more arguments or a function that takes no
288 argument and returns such a list. These arguments are allowed
289 here: `--stat-width', `--stat-name-width', `--stat-graph-width'
290 and `--compact-summary'. See the git-diff(1) manpage."
291 :package-version '(magit . "3.0.0")
292 :group 'magit-diff
293 :type '(radio (function-item magit-diff-use-window-width-as-stat-width)
294 function
295 (list string)
296 (const :tag "None" nil)))
297
283298 ;;;; File Diff
284299
285300 (defcustom magit-diff-buffer-file-locked t
296311 :link '(info-link "(magit)Revision Buffer")
297312 :group 'magit-modes)
298313
299 (defcustom magit-revision-mode-hook '(bug-reference-mode)
314 (defcustom magit-revision-mode-hook
315 '(bug-reference-mode
316 goto-address-mode)
300317 "Hook run after entering Magit-Revision mode."
301318 :group 'magit-revision
302319 :type 'hook
303 :options '(bug-reference-mode))
320 :options '(bug-reference-mode
321 goto-address-mode))
304322
305323 (defcustom magit-revision-sections-hook
306324 '(magit-insert-revision-tag
743761 (pcase-let ((`(,args ,files)
744762 (magit-diff--get-value 'magit-diff-mode
745763 magit-prefix-use-buffer-arguments)))
746 (unless (eq current-transient-command 'magit-dispatch)
764 (unless (eq transient-current-command 'magit-dispatch)
747765 (when-let ((file (magit-file-relative-name)))
748766 (setq files (list file))))
749767 (oset obj value (if files `(("--" ,@files) ,args) args))))
764782
765783 (defun magit-diff-arguments (&optional mode)
766784 "Return the current diff arguments."
767 (if (memq current-transient-command '(magit-diff magit-diff-refresh))
785 (if (memq transient-current-command '(magit-diff magit-diff-refresh))
768786 (pcase-let ((`(,args ,alist)
769787 (-separate #'atom (transient-get-value))))
770788 (list args (cdr (assoc "--" alist))))
815833 ;;; Section Classes
816834
817835 (defclass magit-file-section (magit-section)
818 ((source :initform nil)
819 (header :initform nil)))
836 ((keymap :initform magit-file-section-map)
837 (source :initform nil)
838 (header :initform nil)))
820839
821840 (defclass magit-module-section (magit-file-section)
822 ())
841 ((keymap :initform magit-hunk-section-map)))
823842
824843 (defclass magit-hunk-section (magit-section)
825 ((refined :initform nil)
844 ((keymap :initform magit-hunk-section-map)
845 (refined :initform nil)
826846 (combined :initform nil)
827847 (from-range :initform nil)
828848 (from-ranges :initform nil)
837857 ;;;; Prefix Commands
838858
839859 ;;;###autoload (autoload 'magit-diff "magit-diff" nil t)
840 (define-transient-command magit-diff ()
860 (transient-define-prefix magit-diff ()
841861 "Show changes between different versions."
842862 :man-page "git-diff"
843863 :class 'magit-diff-prefix
870890 ("t" "Show stash" magit-stash-show)]])
871891
872892 ;;;###autoload (autoload 'magit-diff-refresh "magit-diff" nil t)
873 (define-transient-command magit-diff-refresh ()
893 (transient-define-prefix magit-diff-refresh ()
874894 "Change the arguments used for the diff(s) in the current buffer."
875895 :man-page "git-diff"
876896 :class 'magit-diff-refresh-prefix
908928 ("r" "switch range type" magit-diff-switch-range-type)
909929 ("f" "flip revisions" magit-diff-flip-revs)]]
910930 (interactive)
911 (if (not (eq current-transient-command 'magit-diff-refresh))
931 (if (not (eq transient-current-command 'magit-diff-refresh))
912932 (transient-setup 'magit-diff-refresh)
913933 (pcase-let ((`(,args ,files) (magit-diff-arguments)))
914934 (setq magit-buffer-diff-args args)
917937
918938 ;;;; Infix Commands
919939
920 (define-infix-argument magit:-- ()
940 (transient-define-argument magit:-- ()
921941 :description "Limit to files"
922942 :class 'transient-files
923943 :key "--"
929949 (defun magit-read-files (prompt initial-input history)
930950 (magit-completing-read-multiple* prompt
931951 (magit-list-files)
932 nil nil initial-input history))
933
934 (define-infix-argument magit-diff:-U ()
952 nil nil
953 (or initial-input (magit-file-at-point))
954 history))
955
956 (transient-define-argument magit-diff:-U ()
935957 :description "Context lines"
936958 :class 'transient-option
937959 :argument "-U"
938 :reader 'transient-read-number-N+)
939
940 (define-infix-argument magit-diff:-M ()
960 :reader 'transient-read-number-N0)
961
962 (transient-define-argument magit-diff:-M ()
941963 :description "Detect renames"
942964 :class 'transient-option
943965 :argument "-M"
944966 :reader 'transient-read-number-N+)
945967
946 (define-infix-argument magit-diff:-C ()
968 (transient-define-argument magit-diff:-C ()
947969 :description "Detect copies"
948970 :class 'transient-option
949971 :argument "-C"
950972 :reader 'transient-read-number-N+)
951973
952 (define-infix-argument magit-diff:--diff-algorithm ()
974 (transient-define-argument magit-diff:--diff-algorithm ()
953975 :description "Diff algorithm"
954976 :class 'transient-option
955977 :key "-A"
963985 (?p "[p]atience" "patience")
964986 (?h "[h]istogram" "histogram")))
965987
966 (define-infix-argument magit-diff:--ignore-submodules ()
988 (transient-define-argument magit-diff:--ignore-submodules ()
967989 :description "Ignore submodules"
968990 :class 'transient-option
969991 :key "-i"
976998 (?d "[d]irty" "dirty")
977999 (?a "[a]ll" "all")))
9781000
979 (define-infix-argument magit-diff:--color-moved ()
1001 (transient-define-argument magit-diff:--color-moved ()
9801002 :description "Color moved lines"
9811003 :class 'transient-option
9821004 :key "-m"
9911013 (?z "[z]ebra" "zebra")
9921014 (?Z "[Z] dimmed-zebra" "dimmed-zebra")))
9931015
994 (define-infix-argument magit-diff:--color-moved-ws ()
1016 (transient-define-argument magit-diff:--color-moved-ws ()
9951017 :description "Whitespace treatment for --color-moved"
9961018 :class 'transient-option
9971019 :key "=w"
10551077 (cons 'commit
10561078 (magit-section-case
10571079 (commit (oref it value))
1058 (file (-> it
1059 (oref parent)
1060 (oref value)))
1061 (hunk (-> it
1062 (oref parent)
1063 (oref parent)
1064 (oref value))))))
1080 (file (thread-first it
1081 (oref parent)
1082 (oref value)))
1083 (hunk (thread-first it
1084 (oref parent)
1085 (oref parent)
1086 (oref value))))))
10651087 ((derived-mode-p 'magit-revision-mode)
10661088 (cons 'commit magit-buffer-revision))
10671089 ((derived-mode-p 'magit-diff-mode)
10861108 atpoint))))
10871109 (commit (cons 'commit (oref it value)))
10881110 (stash (cons 'stash (oref it value)))
1089 (pullreq (let ((pullreq (oref it value)))
1090 (format "%s...%s"
1091 (oref pullreq base-ref)
1092 (forge--pullreq-ref pullreq))))))))
1111 (pullreq (forge--pullreq-range (oref it value) t))))))
10931112
10941113 (defun magit-diff-read-range-or-commit (prompt &optional secondary-default mbase)
10951114 "Read range or revision with special diff range treatment.
12671286 (atpoint (or (and (bound-and-true-p magit-blame-mode)
12681287 (oref (magit-current-blame-chunk) orig-rev))
12691288 mcommit
1289 (thing-at-point 'git-revision t)
12701290 (magit-branch-or-commit-at-point)))
12711291 (`(,args ,files) (magit-show-commit--arguments)))
12721292 (list (or (and (not current-prefix-arg) atpoint)
13301350 (magit-section-update-highlight)
13311351 t))
13321352
1333 (cl-defmethod magit-buffer-value (&context (major-mode magit-revision-mode))
1334 (cons magit-buffer-range magit-buffer-diff-files))
1335
13361353 ;;;; Setting Commands
13371354
13381355 (defun magit-diff-switch-range-type ()
13771394 (cl-rotatef magit-buffer-diff-files
13781395 magit-buffer-diff-files-suspended)
13791396 (setq magit-buffer-diff-files
1380 (magit-read-files "Limit to file(s): "
1381 (magit-file-at-point)
1382 nil)))
1397 (transient-infix-read 'magit:--)))
13831398 (magit-refresh)))
13841399 (cond
13851400 ((derived-mode-p 'magit-log-mode
13961411 (defun magit-diff-less-context (&optional count)
13971412 "Decrease the context for diff hunks by COUNT lines."
13981413 (interactive "p")
1399 (magit-diff-set-context `(lambda (cur) (max 0 (- (or cur 0) ,count)))))
1414 (magit-diff-set-context (lambda (cur) (max 0 (- (or cur 0) count)))))
14001415
14011416 (defun magit-diff-more-context (&optional count)
14021417 "Increase the context for diff hunks by COUNT lines."
14031418 (interactive "p")
1404 (magit-diff-set-context `(lambda (cur) (+ (or cur 0) ,count))))
1419 (magit-diff-set-context (lambda (cur) (+ (or cur 0) count))))
14051420
14061421 (defun magit-diff-default-context ()
14071422 "Reset context for diff hunks to the default height."
15531568 (defun magit-diff-visit-file--internal (file force-worktree fn)
15541569 "From a diff visit the appropriate version of FILE.
15551570 If FORCE-WORKTREE is non-nil, then visit the worktree version of
1556 the file, even if the diff is about a committed change. USE FN
1571 the file, even if the diff is about a committed change. Use FN
15571572 to display the buffer in some window."
15581573 (if (magit-file-accessible-directory-p file)
15591574 (magit-diff-visit-directory file force-worktree)
16991714 (cdr spec)
17001715 (cdr (magit-split-range spec)))))
17011716 (if (and magit-diff-visit-avoid-head-blob
1702 (magit-rev-head-p spec))
1717 (magit-rev-head-p rev))
17031718 'unstaged
17041719 rev))))
17051720
18271842 (cond ((and (--any-p (oref it hidden) children)
18281843 (--any-p (oref it children) children))
18291844 (mapc 'magit-section-show-headings sections))
1830 ((-any-p 'magit-section-hidden-body children)
1845 ((seq-some 'magit-section-hidden-body children)
18311846 (mapc 'magit-section-show-children sections))
18321847 (t
18331848 (mapc 'magit-section-hide sections)))))))
18841899 (magit-buffer-range range)
18851900 (magit-buffer-typearg typearg)
18861901 (magit-buffer-diff-args args)
1887 (magit-buffer-diff-files files)))
1902 (magit-buffer-diff-files files)
1903 (magit-buffer-diff-files-suspended nil)))
18881904
18891905 (defun magit-diff-refresh-buffer ()
18901906 "Refresh the current `magit-diff-mode' buffer."
19181934 (list 'unstaged magit-buffer-typearg)))
19191935 (and magit-buffer-diff-files (cons "--" magit-buffer-diff-files))))
19201936
1921 (defvar magit-file-section-map
1937 (defvar magit-diff-section-base-map
19221938 (let ((map (make-sparse-keymap)))
1923 (define-key map (kbd "C-j") 'magit-diff-visit-worktree-file)
1924 (define-key map [C-return] 'magit-diff-visit-worktree-file)
1939 (define-key map (kbd "C-j") 'magit-diff-visit-worktree-file)
1940 (define-key map (kbd "C-<return>") 'magit-diff-visit-worktree-file)
1941 (define-key map (kbd "C-x 4 <return>") 'magit-diff-visit-file-other-window)
1942 (define-key map (kbd "C-x 5 <return>") 'magit-diff-visit-file-other-frame)
19251943 (define-key map [remap magit-visit-thing] 'magit-diff-visit-file)
19261944 (define-key map [remap magit-delete-thing] 'magit-discard)
19271945 (define-key map [remap magit-revert-no-commit] 'magit-reverse)
19281946 (define-key map "a" 'magit-apply)
1929 (define-key map "C" 'magit-commit-add-log)
19301947 (define-key map "s" 'magit-stage)
19311948 (define-key map "u" 'magit-unstage)
19321949 (define-key map "&" 'magit-do-async-shell-command)
1933 (define-key map "\C-c\C-t" 'magit-diff-trace-definition)
1934 (define-key map "\C-c\C-e" 'magit-diff-edit-hunk-commit)
1950 (define-key map "C" 'magit-commit-add-log)
1951 (define-key map (kbd "C-x a") 'magit-add-change-log-entry)
1952 (define-key map (kbd "C-x 4 a") 'magit-add-change-log-entry-other-window)
1953 (define-key map (kbd "C-c C-t") 'magit-diff-trace-definition)
1954 (define-key map (kbd "C-c C-e") 'magit-diff-edit-hunk-commit)
1955 map)
1956 "Parent of `magit-{hunk,file}-section-map'.")
1957
1958 (defvar magit-file-section-map
1959 (let ((map (make-sparse-keymap)))
1960 (set-keymap-parent map magit-diff-section-base-map)
19351961 map)
19361962 "Keymap for `file' sections.")
19371963
19381964 (defvar magit-hunk-section-map
19391965 (let ((map (make-sparse-keymap)))
1940 (define-key map (kbd "C-j") 'magit-diff-visit-worktree-file)
1941 (define-key map [C-return] 'magit-diff-visit-worktree-file)
1942 (define-key map [remap magit-visit-thing] 'magit-diff-visit-file)
1943 (define-key map [remap magit-delete-thing] 'magit-discard)
1944 (define-key map [remap magit-revert-no-commit] 'magit-reverse)
1945 (define-key map "a" 'magit-apply)
1946 (define-key map "C" 'magit-commit-add-log)
1947 (define-key map "s" 'magit-stage)
1948 (define-key map "u" 'magit-unstage)
1949 (define-key map "&" 'magit-do-async-shell-command)
1950 (define-key map "\C-c\C-t" 'magit-diff-trace-definition)
1951 (define-key map "\C-c\C-e" 'magit-diff-edit-hunk-commit)
1966 (set-keymap-parent map magit-diff-section-base-map)
19521967 map)
19531968 "Keymap for `hunk' sections.")
19541969
1970 (defconst magit-diff-conflict-headline-re
1971 (concat "^" (regexp-opt
1972 ;; Defined in merge-tree.c in this order.
1973 '("merged"
1974 "added in remote"
1975 "added in both"
1976 "added in local"
1977 "removed in both"
1978 "changed in both"
1979 "removed in local"
1980 "removed in remote"))))
1981
19551982 (defconst magit-diff-headline-re
19561983 (concat "^\\(@@@?\\|diff\\|Submodule\\|"
1957 "\\* Unmerged path\\|merged\\|changed in both\\|"
1958 "added in remote\\|removed in remote\\)"))
1984 "\\* Unmerged path\\|"
1985 (substring magit-diff-conflict-headline-re 1)
1986 "\\)"))
19591987
19601988 (defconst magit-diff-statline-re
19611989 (concat "^ ?"
19922020
19932021 (defun magit--insert-diff (&rest args)
19942022 (declare (indent 0))
1995 (let ((magit-git-global-arguments
1996 (remove "--literal-pathspecs" magit-git-global-arguments)))
1997 (setq args (-flatten args))
2023 (pcase-let ((`(,cmd . ,args)
2024 (-flatten args))
2025 (magit-git-global-arguments
2026 (remove "--literal-pathspecs" magit-git-global-arguments)))
19982027 ;; As of Git 2.19.0, we need to generate diffs with
19992028 ;; --ita-visible-in-index so that `magit-stage' can work with
20002029 ;; intent-to-add files (see #4026). Cache the result for each
20012030 ;; repo to avoid a `git version' call for every diff insertion.
2002 (when (pcase (magit-repository-local-get 'diff-ita-kludge-p 'unset)
2003 (`unset
2004 (let ((val (version<= "2.19.0" (magit-git-version))))
2005 (magit-repository-local-set 'diff-ita-kludge-p val)
2006 val))
2007 (val val))
2008 (push "--ita-visible-in-index" (cdr args)))
2031 (when (and (not (equal cmd "merge-tree"))
2032 (pcase (magit-repository-local-get 'diff-ita-kludge-p 'unset)
2033 (`unset
2034 (let ((val (version<= "2.19.0" (magit-git-version))))
2035 (magit-repository-local-set 'diff-ita-kludge-p val)
2036 val))
2037 (val val)))
2038 (push "--ita-visible-in-index" args))
2039 (setq args (magit-diff--maybe-add-stat-arguments args))
20092040 (when (cl-member-if (lambda (arg) (string-prefix-p "--color-moved" arg)) args)
2010 (push "--color=always" (cdr args))
2041 (push "--color=always" args)
20112042 (setq magit-git-global-arguments
20122043 (append magit-diff--reset-non-color-moved
20132044 magit-git-global-arguments)))
2014 (magit-git-wash #'magit-diff-wash-diffs args)))
2045 (magit-git-wash #'magit-diff-wash-diffs cmd args)))
2046
2047 (defun magit-diff--maybe-add-stat-arguments (args)
2048 (if (member "--stat" args)
2049 (append (if (functionp magit-diff-extra-stat-arguments)
2050 (funcall magit-diff-extra-stat-arguments)
2051 magit-diff-extra-stat-arguments)
2052 args)
2053 args))
2054
2055 (defun magit-diff-use-window-width-as-stat-width ()
2056 "Use the `window-width' as the value of `--stat-width'."
2057 (when-let ((window (get-buffer-window (current-buffer) 'visible)))
2058 (list (format "--stat-width=%d" (window-width window)))))
20152059
20162060 (defun magit-diff-wash-diffs (args &optional limit)
2061 (run-hooks 'magit-diff-wash-diffs-hook)
20172062 (when (member "--show-signature" args)
20182063 (magit-diff-wash-signature))
20192064 (when (member "--stat" args)
21172162 'font-lock-face 'magit-diff-file-heading))
21182163 (insert ?\n))))
21192164 t)
2120 ((looking-at (concat "^\\(merged\\|changed in both\\|"
2121 "added in remote\\|removed in remote\\)"))
2122 (let ((status (pcase (match-string 1)
2123 ("merged" "merged")
2124 ("changed in both" "conflict")
2125 ("added in remote" "new file")
2126 ("removed in remote" "deleted")))
2127 file orig base modes)
2165 ((looking-at magit-diff-conflict-headline-re)
2166 (let ((long-status (match-string 0))
2167 (status "BUG")
2168 file orig base)
2169 (if (equal long-status "merged")
2170 (progn (setq status long-status)
2171 (setq long-status nil))
2172 (setq status (pcase-exhaustive long-status
2173 ("added in remote" "new file")
2174 ("added in both" "new file")
2175 ("added in local" "new file")
2176 ("removed in both" "removed")
2177 ("changed in both" "changed")
2178 ("removed in local" "removed")
2179 ("removed in remote" "removed"))))
21282180 (magit-delete-line)
21292181 (while (looking-at
21302182 "^ \\([^ ]+\\) +[0-9]\\{6\\} \\([a-z0-9]\\{40\\}\\) \\(.+\\)$")
21372189 (magit-delete-line))
21382190 (when orig (setq orig (magit-decode-git-path orig)))
21392191 (when file (setq file (magit-decode-git-path file)))
2140 (magit-diff-insert-file-section (or file base) orig status modes nil)))
2192 (magit-diff-insert-file-section
2193 (or file base) orig status nil nil long-status)))
21412194 ((looking-at
21422195 "^diff --\\(?:\\(git\\) \\(?:\\(.+?\\) \\2\\)?\\|\\(cc\\|combined\\) \\(.+\\)\\)")
21432196 (let ((status (cond ((equal (match-string 1) "git") "modified")
21812234 (setq orig (substring orig 2))))
21822235 (magit-diff-insert-file-section file orig status modes header)))))
21832236
2184 (defun magit-diff-insert-file-section (file orig status modes header)
2237 (defun magit-diff-insert-file-section
2238 (file orig status modes header &optional long-status)
21852239 (magit-insert-section section
21862240 (file file (or (equal status "deleted")
21872241 (derived-mode-p 'magit-status-mode)))
2188 (insert (propertize (format "%-10s %s\n" status
2242 (insert (propertize (format "%-10s %s" status
21892243 (if (or (not orig) (equal orig file))
21902244 file
21912245 (format "%s -> %s" orig file)))
21922246 'font-lock-face 'magit-diff-file-heading))
2247 (when long-status
2248 (insert (format " (%s)" long-status)))
21932249 (magit-insert-heading)
21942250 (unless (equal orig file)
21952251 (oset section source orig))
22662322 (when (looking-at "^@\\{2,\\} \\(.+?\\) @\\{2,\\}\\(?: \\(.*\\)\\)?")
22672323 (let* ((heading (match-string 0))
22682324 (ranges (mapcar (lambda (str)
2269 (mapcar (lambda (n) (string-to-number n))
2325 (mapcar #'string-to-number
22702326 (split-string (substring str 1) ",")))
22712327 (split-string (match-string 1))))
22722328 (about (match-string 2))
23322388 (magit-buffer-revision rev)
23332389 (magit-buffer-range (format "%s^..%s" rev rev))
23342390 (magit-buffer-diff-args args)
2335 (magit-buffer-diff-files files)))
2391 (magit-buffer-diff-files files)
2392 (magit-buffer-diff-files-suspended nil)))
23362393
23372394 (defun magit-revision-refresh-buffer ()
2395 (setq magit-buffer-revision-hash (magit-rev-parse magit-buffer-revision))
23382396 (magit-set-header-line-format
2339 (concat (capitalize (magit-object-type magit-buffer-revision))
2397 (concat (magit-object-type magit-buffer-revision-hash)
23402398 " " magit-buffer-revision
23412399 (pcase (length magit-buffer-diff-files)
23422400 (0)
23432401 (1 (concat " limited to file " (car magit-buffer-diff-files)))
23442402 (_ (concat " limited to files "
23452403 (mapconcat #'identity magit-buffer-diff-files ", "))))))
2346 (setq magit-buffer-revision-hash (magit-rev-parse magit-buffer-revision))
23472404 (magit-insert-section (commitbuf)
23482405 (magit-run-section-hook 'magit-revision-sections-hook)))
23492406
23922449 (re-search-forward "-----END PGP SIGNATURE-----")
23932450 (delete-region beg (point)))
23942451 (insert ?\n)
2395 (process-file magit-git-executable nil t nil
2396 "verify-tag" magit-buffer-revision))
2452 (magit-process-file magit-git-executable nil t nil
2453 "verify-tag" magit-buffer-revision))
23972454 (goto-char (point-max)))
23982455 (insert ?\n))))
23992456
25322589 (eq magit-revision-insert-related-refs 'all))
25332590 (magit--insert-related-refs
25342591 magit-buffer-revision "--contains" "Contained"
2535 (eq magit-revision-insert-related-refs '(all mixed)))
2592 (memq magit-revision-insert-related-refs '(all mixed)))
25362593 (when-let ((follows (magit-get-current-tag magit-buffer-revision t)))
25372594 (let ((tag (car follows))
25382595 (cnt (cadr follows)))
27852842 (if (memq type '(file module))
27862843 (magit-diff-type parent)
27872844 type)))
2788 (`hunk (-> it
2789 (oref parent)
2790 (oref parent)
2791 (oref type)))))))
2845 (`hunk (thread-first it
2846 (oref parent)
2847 (oref parent)
2848 (oref type)))))))
27922849 ((derived-mode-p 'magit-log-mode)
27932850 (if (or (and (magit-section-match 'commit section)
27942851 (oref section children))
00 ;;; magit-ediff.el --- Ediff extension for Magit -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2010-2020 The Magit Project Contributors
2 ;; Copyright (C) 2010-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
77 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9
10 ;; SPDX-License-Identifier: GPL-3.0-or-later
911
1012 ;; Magit is free software; you can redistribute it and/or modify it
1113 ;; under the terms of the GNU General Public License as published by
103105 (defvar magit-ediff-previous-winconf nil)
104106
105107 ;;;###autoload (autoload 'magit-ediff "magit-ediff" nil)
106 (define-transient-command magit-ediff ()
108 (transient-define-prefix magit-ediff ()
107109 "Show differences using the Ediff package."
108110 :info-manual "(ediff)"
109111 ["Ediff"
00 ;;; magit-extras.el --- additional functionality for Magit -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2008-2020 The Magit Project Contributors
2 ;; Copyright (C) 2008-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
6
7 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
8 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9
10 ;; SPDX-License-Identifier: GPL-3.0-or-later
611
712 ;; Magit is free software; you can redistribute it and/or modify it
813 ;; under the terms of the GNU General Public License as published by
2328
2429 ;;; Code:
2530
26 (eval-when-compile
27 (require 'subr-x))
28
2931 (require 'magit)
3032
33 (declare-function change-log-insert-entries "add-log" (changelogs))
34 (declare-function diff-add-log-current-defuns "diff-mode" ())
3135 (declare-function dired-read-shell-command "dired-aux" (prompt arg files))
36 ;; For `magit-project-status'.
37 (declare-function project-root "project" (project))
38 (declare-function vc-git-command "vc-git" (buffer okstatus file-or-list &rest flags))
3239
3340 (defvar ido-exit)
3441 (defvar ido-fallback)
42 (defvar project-prefix-map)
43 (defvar project-switch-commands)
3544
3645 (defgroup magit-extras nil
3746 "Additional functionality for Magit."
131140 (exit-minibuffer))
132141
133142 ;;;###autoload
143 (defun magit-project-status ()
144 "Run `magit-status' in the current project's root."
145 (interactive)
146 (magit-status-setup-buffer (project-root (project-current t))))
147
148 (defvar magit-bind-magit-project-status t
149 "Whether to bind \"m\" to `magit-project-status' in `project-prefix-map'.
150 If so, then an entry is added to `project-switch-commands' as
151 well. If you want to use another key, then you must set this
152 to nil before loading Magit to prevent \"m\" from being bound.")
153
154 (with-eval-after-load 'project
155 ;; Only more recent versions of project.el have `project-prefix-map' and
156 ;; `project-switch-commands', though project.el is available in Emacs 25.
157 (when (and magit-bind-magit-project-status
158 (boundp 'project-prefix-map)
159 ;; Only modify if it hasn't already been modified.
160 (equal project-switch-commands
161 (eval (car (get 'project-switch-commands 'standard-value))
162 t)))
163 (define-key project-prefix-map "m" #'magit-project-status)
164 (add-to-list 'project-switch-commands '(magit-project-status "Magit") t)))
165
166 ;;;###autoload
134167 (defun magit-dired-jump (&optional other-window)
135168 "Visit file at point using Dired.
136169 With a prefix argument, visit in another window. If there
248281 (put 'magit-clean 'disabled t)
249282
250283 ;;; ChangeLog
284
285 (defun magit-generate-changelog (&optional amending)
286 "Insert ChangeLog entries into the current buffer.
287
288 The entries are generated from the diff being committed.
289 If prefix argument, AMENDING, is non-nil, include changes
290 in HEAD as well as staged changes in the diff to check."
291 (interactive "P")
292 (unless (magit-commit-message-buffer)
293 (user-error "No commit in progress"))
294 (require 'diff-mode) ; `diff-add-log-current-defuns'.
295 (require 'vc-git) ; `vc-git-diff'.
296 (require 'add-log) ; `change-log-insert-entries'.
297 (unless (and (fboundp 'change-log-insert-entries)
298 (fboundp 'diff-add-log-current-defuns))
299 (user-error "`magit-generate-changelog' requires Emacs 27 or better"))
300 (setq default-directory
301 (if (and (file-regular-p "gitdir")
302 (not (magit-git-true "rev-parse" "--is-inside-work-tree"))
303 (magit-git-true "rev-parse" "--is-inside-git-dir"))
304 (file-name-directory (magit-file-line "gitdir"))
305 (magit-toplevel)))
306 (let ((rev1 (if amending "HEAD^1" "HEAD"))
307 (rev2 nil))
308 ;; Magit may have updated the files without notifying vc, but
309 ;; `diff-add-log-current-defuns' relies on vc being up-to-date.
310 (mapc #'vc-file-clearprops (magit-staged-files))
311 (change-log-insert-entries
312 (with-temp-buffer
313 (vc-git-command (current-buffer) 1 nil
314 "diff-index" "--exit-code" "--patch"
315 (and (magit-anything-staged-p) "--cached")
316 rev1 "--")
317 ;; `diff-find-source-location' consults these vars.
318 (defvar diff-vc-revisions)
319 (setq-local diff-vc-revisions (list rev1 rev2))
320 (setq-local diff-vc-backend 'Git)
321 (diff-add-log-current-defuns)))))
251322
252323 ;;;###autoload
253324 (defun magit-add-change-log-entry (&optional whoami file-name other-window)
347418
348419 ;;; Reshelve
349420
350 ;;;###autoload
351 (defun magit-reshelve-since (rev)
421 (defcustom magit-reshelve-since-committer-only nil
422 "Whether `magit-reshelve-since' changes only the committer dates.
423 Otherwise the author dates are also changed."
424 :package-version '(magit . "3.0.0")
425 :group 'magit-commands
426 :type 'boolean)
427
428 ;;;###autoload
429 (defun magit-reshelve-since (rev keyid)
352430 "Change the author and committer dates of the commits since REV.
353431
354432 Ask the user for the first reachable commit whose dates should
358436 on.
359437
360438 This command is only intended for interactive use and should only
361 be used on highly rearranged and unpublished history."
362 (interactive (list nil))
363 (cond
364 ((not rev)
365 (let ((backup (concat "refs/original/refs/heads/"
366 (magit-get-current-branch))))
439 be used on highly rearranged and unpublished history.
440
441 If KEYID is non-nil, then use that to sign all reshelved commits.
442 Interactively use the value of the \"--gpg-sign\" option in the
443 list returned by `magit-rebase-arguments'."
444 (interactive (list nil
445 (transient-arg-value "--gpg-sign="
446 (magit-rebase-arguments))))
447 (let* ((current (or (magit-get-current-branch)
448 (user-error "Refusing to reshelve detached head")))
449 (backup (concat "refs/original/refs/heads/" current)))
450 (cond
451 ((not rev)
367452 (when (and (magit-ref-p backup)
368453 (not (magit-y-or-n-p
369 "Backup ref %s already exists. Override? " backup)))
370 (user-error "Abort")))
371 (magit-log-select 'magit-reshelve-since
372 "Type %p on a commit to reshelve it and the commits above it,"))
373 (t
374 (cl-flet ((adjust (time offset)
375 (format-time-string
376 "%F %T %z"
377 (+ (floor time)
378 (* offset 60)
379 (- (car (decode-time time)))))))
380 (let* ((start (concat rev "^"))
381 (range (concat start ".." (magit-get-current-branch)))
382 (time-rev (adjust (float-time (string-to-number
383 (magit-rev-format "%at" start)))
384 1))
385 (time-now (adjust (float-time)
386 (- (string-to-number
387 (magit-git-string "rev-list" "--count"
388 range))))))
389 (push time-rev magit--reshelve-history)
390 (let ((date (floor
391 (float-time
392 (date-to-time
393 (read-string "Date for first commit: "
394 time-now 'magit--reshelve-history))))))
395 (magit-with-toplevel
396 (magit-run-git-async
397 "filter-branch" "--force" "--env-filter"
398 (format "case $GIT_COMMIT in %s\nesac"
399 (mapconcat (lambda (rev)
400 (prog1 (format "%s) \
401 export GIT_AUTHOR_DATE=\"%s\"; \
402 export GIT_COMMITTER_DATE=\"%s\";;" rev date date)
403 (cl-incf date 60)))
404 (magit-git-lines "rev-list" "--reverse"
405 range)
406 " "))
407 range "--")
454 (format "Backup ref %s already exists. Override? " backup))))
455 (user-error "Abort"))
456 (magit-log-select
457 (lambda (rev)
458 (magit-reshelve-since rev keyid))
459 "Type %p on a commit to reshelve it and the commits above it,"))
460 (t
461 (cl-flet ((adjust (time offset)
462 (format-time-string
463 "%F %T %z"
464 (+ (floor time)
465 (* offset 60)
466 (- (car (decode-time time)))))))
467 (let* ((start (concat rev "^"))
468 (range (concat start ".." current))
469 (time-rev (adjust (float-time (string-to-number
470 (magit-rev-format "%at" start)))
471 1))
472 (time-now (adjust (float-time)
473 (- (string-to-number
474 (magit-git-string "rev-list" "--count"
475 range))))))
476 (push time-rev magit--reshelve-history)
477 (let ((date (floor
478 (float-time
479 (date-to-time
480 (read-string "Date for first commit: "
481 time-now 'magit--reshelve-history)))))
482 (process-environment process-environment))
483 (push "FILTER_BRANCH_SQUELCH_WARNING=1" process-environment)
484 (magit-with-toplevel
485 (magit-run-git-async
486 "filter-branch" "--force" "--env-filter"
487 (format
488 "case $GIT_COMMIT in %s\nesac"
489 (mapconcat
490 (lambda (rev)
491 (prog1 (concat
492 (format "%s) " rev)
493 (and (not magit-reshelve-since-committer-only)
494 (format "export GIT_AUTHOR_DATE=\"%s\"; " date))
495 (format "export GIT_COMMITTER_DATE=\"%s\";;" date))
496 (cl-incf date 60)))
497 (magit-git-lines "rev-list" "--reverse" range)
498 " "))
499 (and keyid
500 (list "--commit-filter"
501 (format "git commit-tree --gpg-sign=%s \"$@\";"
502 keyid)))
503 range "--"))
408504 (set-process-sentinel
409505 magit-this-process
410506 (lambda (process event)
413509 (magit-process-sentinel process event)
414510 (process-put process 'inhibit-refresh t)
415511 (magit-process-sentinel process event)
416 (magit-run-git "update-ref" "-d"
417 (concat "refs/original/refs/heads/"
418 (magit-get-current-branch))))))))))))))
512 (magit-run-git "update-ref" "-d" backup))))))))))))
419513
420514 ;;; Revision Stack
421515
553647 (kbd "C-c C-w") 'magit-pop-revision-stack)
554648
555649 ;;;###autoload
556 (defun magit-copy-section-value ()
650 (defun magit-copy-section-value (arg)
557651 "Save the value of the current section for later use.
558652
559653 Save the section value to the `kill-ring', and, provided that
571665
572666 When the region is active, then save that to the `kill-ring',
573667 like `kill-ring-save' would, instead of behaving as described
574 above. If a prefix argument is used and the region is within a
575 hunk, strip the outer diff marker column."
576 (interactive)
668 above. If a prefix argument is used and the region is within
669 a hunk, then strip the diff marker column and keep only either
670 the added or removed lines, depending on the sign of the prefix
671 argument."
672 (interactive "P")
577673 (cond
578 ((and current-prefix-arg
674 ((and arg
579675 (magit-section-internal-region-p)
580676 (magit-section-match 'hunk))
581 (deactivate-mark)
582 (kill-new (replace-regexp-in-string
583 "^[ \\+\\-]" ""
584 (buffer-substring-no-properties
585 (region-beginning) (region-end)))))
677 (kill-new
678 (thread-last (buffer-substring-no-properties
679 (region-beginning)
680 (region-end))
681 (replace-regexp-in-string
682 (format "^\\%c.*\n?" (if (< (prefix-numeric-value arg) 0) ?+ ?-))
683 "")
684 (replace-regexp-in-string "^[ \\+\\-]" "")))
685 (deactivate-mark))
586686 ((use-region-p)
587687 (call-interactively #'copy-region-as-kill))
588688 (t
00 ;;; magit-fetch.el --- download objects and refs -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2008-2020 The Magit Project Contributors
2 ;; Copyright (C) 2008-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
77 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9
10 ;; SPDX-License-Identifier: GPL-3.0-or-later
911
1012 ;; Magit is free software; you can redistribute it and/or modify it
1113 ;; under the terms of the GNU General Public License as published by
4042 ;;; Commands
4143
4244 ;;;###autoload (autoload 'magit-fetch "magit-fetch" nil t)
43 (define-transient-command magit-fetch ()
45 (transient-define-prefix magit-fetch ()
4446 "Fetch from another repository."
4547 :man-page "git-fetch"
4648 ["Arguments"
4749 ("-p" "Prune deleted branches" ("-p" "--prune"))
48 ("-t" "Fetch all tags" ("-t" "--tags"))]
50 ("-t" "Fetch all tags" ("-t" "--tags"))
51 (7 "-u" "Fetch full history" "--unshallow")]
4952 ["Fetch from"
5053 ("p" magit-fetch-from-pushremote)
5154 ("u" magit-fetch-from-upstream)
6669 (magit-run-git-async "fetch" remote args))
6770
6871 ;;;###autoload (autoload 'magit-fetch-from-pushremote "magit-fetch" nil t)
69 (define-suffix-command magit-fetch-from-pushremote (args)
72 (transient-define-suffix magit-fetch-from-pushremote (args)
7073 "Fetch from the current push-remote.
7174
7275 With a prefix argument or when the push-remote is either not
9598 (format "%s, setting that" v)))))
9699
97100 ;;;###autoload (autoload 'magit-fetch-from-upstream "magit-fetch" nil t)
98 (define-suffix-command magit-fetch-from-upstream (remote args)
101 (transient-define-suffix magit-fetch-from-upstream (remote args)
99102 "Fetch from the \"current\" remote, usually the upstream.
100103
101104 If the upstream is configured for the current branch and names
00 ;;; magit-files.el --- finding files -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2010-2020 The Magit Project Contributors
2 ;; Copyright (C) 2010-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
77 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9
10 ;; SPDX-License-Identifier: GPL-3.0-or-later
911
1012 ;; Magit is free software; you can redistribute it and/or modify it
1113 ;; under the terms of the GNU General Public License as published by
2830 ;; modes.
2931
3032 ;;; Code:
31
32 (eval-when-compile
33 (require 'subr-x))
3433
3534 (require 'magit)
3635
205204 (unless (equal magit-buffer-refname "{index}")
206205 (user-error "%s isn't visiting the index" file))
207206 (if (y-or-n-p (format "Update index with contents of %s" (buffer-name)))
208 (let ((index (make-temp-file "index"))
207 (let ((index (make-temp-name (magit-git-dir "magit-update-index-")))
209208 (buffer (current-buffer)))
210209 (when magit-wip-before-change-mode
211210 (magit-wip-commit-before-change (list file) " before un-/stage"))
212 (let ((coding-system-for-write buffer-file-coding-system))
213 (with-temp-file index
214 (insert-buffer-substring buffer)))
215 (magit-with-toplevel
216 (magit-call-git "update-index" "--cacheinfo"
217 (substring (magit-git-string "ls-files" "-s" file)
218 0 6)
219 (magit-git-string "hash-object" "-t" "blob" "-w"
220 (concat "--path=" file)
221 "--" index)
222 file))
211 (unwind-protect
212 (progn
213 (let ((coding-system-for-write buffer-file-coding-system))
214 (with-temp-file index
215 (insert-buffer-substring buffer)))
216 (magit-with-toplevel
217 (magit-call-git
218 "update-index" "--cacheinfo"
219 (substring (magit-git-string "ls-files" "-s" file)
220 0 6)
221 (magit-git-string "hash-object" "-t" "blob" "-w"
222 (concat "--path=" file)
223 "--" (magit-convert-filename-for-git index))
224 file)))
225 (ignore-errors (delete-file index)))
223226 (set-buffer-modified-p nil)
224227 (when magit-wip-after-apply-mode
225228 (magit-wip-commit-after-apply (list file) " after un-/stage")))
278281 (confirm-nonexistent-file-or-buffer))))
279282 (find-file-other-frame filename wildcards))
280283
281 ;;; File Mode
282
283 (defvar magit-file-mode-map
284 (let ((map (make-sparse-keymap)))
285 (define-key map "\C-xg" 'magit-status)
286 (define-key map "\C-x\M-g" 'magit-dispatch)
287 (define-key map "\C-c\M-g" 'magit-file-dispatch)
288 map)
289 "Keymap for `magit-file-mode'.")
284 ;;; File Dispatch
290285
291286 ;;;###autoload (autoload 'magit-file-dispatch "magit" nil t)
292 (define-transient-command magit-file-dispatch ()
293 "Invoke a Magit command that acts on the visited file."
287 (transient-define-prefix magit-file-dispatch ()
288 "Invoke a Magit command that acts on the visited file.
289 When invoked outside a file-visiting buffer, then fall back
290 to `magit-dispatch'."
294291 :info-manual "(magit) Minor Mode for Buffers Visiting Files"
295292 ["Actions"
296293 [("s" "Stage" magit-stage-file)
316313 [(5 "C-c r" "Rename file" magit-file-rename)
317314 (5 "C-c d" "Delete file" magit-file-delete)
318315 (5 "C-c u" "Untrack file" magit-file-untrack)
319 (5 "C-c c" "Checkout file" magit-file-checkout)]])
320
321 (defvar magit-file-mode-lighter "")
322
323 (define-minor-mode magit-file-mode
324 "Enable some Magit features in a file-visiting buffer.
325
326 Currently this only adds the following key bindings.
327 \n\\{magit-file-mode-map}"
328 :package-version '(magit . "2.2.0")
329 :lighter magit-file-mode-lighter
330 :keymap magit-file-mode-map)
331
332 (defun magit-file-mode-turn-on ()
333 (and buffer-file-name
334 (magit-inside-worktree-p t)
335 (magit-file-mode)))
336
337 ;;;###autoload
338 (define-globalized-minor-mode global-magit-file-mode
339 magit-file-mode magit-file-mode-turn-on
340 :package-version '(magit . "2.13.0")
341 :link '(info-link "(magit)Minor Mode for Buffers Visiting Files")
342 :group 'magit-essentials
343 :group 'magit-modes
344 :init-value t)
345 ;; Unfortunately `:init-value t' only sets the value of the mode
346 ;; variable but does not cause the mode function to be called, and we
347 ;; cannot use `:initialize' to call that explicitly because the option
348 ;; is defined before the functions, so we have to do it here.
349 (cl-eval-when (load eval)
350 (when global-magit-file-mode
351 (global-magit-file-mode 1)))
316 (5 "C-c c" "Checkout file" magit-file-checkout)]]
317 (interactive)
318 (transient-setup
319 (if (magit-file-relative-name)
320 'magit-file-dispatch
321 'magit-dispatch)))
352322
353323 ;;; Blob Mode
354324
429399 ;;; File Commands
430400
431401 (defun magit-file-rename (file newname)
432 "Rename the FILE to NEWNAME.
433 If FILE isn't tracked in Git, fallback to using `rename-file'."
402 "Rename or move FILE to NEWNAME.
403 NEWNAME may be a file or directory name. If FILE isn't tracked in
404 Git, fallback to using `rename-file'."
434405 (interactive
435406 (let* ((file (magit-read-file "Rename file"))
436407 (dir (file-name-directory file))
437 (newname (read-file-name (format "Rename %s to file: " file)
408 (newname (read-file-name (format "Move %s to destination: " file)
438409 (and dir (expand-file-name dir)))))
439410 (list (expand-file-name file (magit-toplevel))
440411 (expand-file-name newname))))
441 (let ((oldbuf (get-file-buffer file)))
412 (let ((oldbuf (get-file-buffer file))
413 (dstdir (file-name-directory newname))
414 (dstfile (if (directory-name-p newname)
415 (concat newname (file-name-nondirectory file))
416 newname)))
442417 (when (and oldbuf (buffer-modified-p oldbuf))
443418 (user-error "Save %s before moving it" file))
444 (when (file-exists-p newname)
445 (user-error "%s already exists" newname))
419 (when (file-exists-p dstfile)
420 (user-error "%s already exists" dstfile))
421 (unless (file-exists-p dstdir)
422 (user-error "Destination directory %s does not exist" dstdir))
446423 (if (magit-file-tracked-p (magit-convert-filename-for-git file))
447424 (magit-call-git "mv"
448425 (magit-convert-filename-for-git file)
451428 (when oldbuf
452429 (with-current-buffer oldbuf
453430 (let ((buffer-read-only buffer-read-only))
454 (set-visited-file-name newname nil t))
431 (set-visited-file-name dstfile nil t))
455432 (if (fboundp 'vc-refresh-state)
456433 (vc-refresh-state)
457434 (with-no-warnings
00 ;;; magit-git.el --- Git functionality -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2010-2020 The Magit Project Contributors
2 ;; Copyright (C) 2010-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
77 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9
10 ;; SPDX-License-Identifier: GPL-3.0-or-later
911
1012 ;; Magit is free software; you can redistribute it and/or modify it
1113 ;; under the terms of the GNU General Public License as published by
2527 ;; This library implements wrappers for various Git plumbing commands.
2628
2729 ;;; Code:
28
29 (require 'cl-lib)
30 (require 'dash)
31
32 (eval-when-compile
33 (require 'subr-x))
3430
3531 (require 'magit-utils)
3632 (require 'magit-section)
132128 (defcustom magit-git-executable
133129 ;; Git might be installed in a different location on a remote, so
134130 ;; it is better not to use the full path to the executable, except
135 ;; on Window were we would otherwise end up using one one of the
131 ;; on Window where we would otherwise end up using one of the
136132 ;; wrappers "cmd/git.exe" or "cmd/git.cmd", which are much slower
137133 ;; than using "bin/git.exe" directly.
138134 (or (and (eq system-type 'windows-nt)
296292 (with-editor* magit-with-editor-envvar
297293 ,@body)))
298294
295 (defmacro magit--with-temp-process-buffer (&rest body)
296 "Like `with-temp-buffer', but always propagate `process-environment'.
297 When that var is buffer-local in the calling buffer, it is not
298 propagated by `with-temp-buffer', so we explicitly ensure that
299 happens, so that processes will be invoked consistently. BODY is
300 as for that macro."
301 (declare (indent 0) (debug (body)))
302 (let ((p (cl-gensym)))
303 `(let ((,p process-environment))
304 (with-temp-buffer
305 (setq-local process-environment ,p)
306 ,@body))))
307
299308 (defun magit-process-git-arguments (args)
300309 "Prepare ARGS for a function that invokes Git.
301310
338347 This is an experimental replacement for `magit-git-string', and
339348 still subject to major changes."
340349 (magit--with-refresh-cache (cons default-directory args)
341 (with-temp-buffer
350 (magit--with-temp-process-buffer
342351 (and (zerop (apply #'magit-process-file magit-git-executable nil t nil
343352 (magit-process-git-arguments args)))
344353 (not (bobp))
358367 still subject to major changes. Also see `magit-git-string-p'."
359368 (magit--with-refresh-cache
360369 (list default-directory 'magit-git-string-ng args)
361 (with-temp-buffer
370 (magit--with-temp-process-buffer
362371 (let* ((args (magit-process-git-arguments args))
363372 (status (apply #'magit-process-file magit-git-executable
364373 nil t nil args)))
386395 ignore `magit-git-debug'."
387396 (setq args (-flatten args))
388397 (magit--with-refresh-cache (cons default-directory args)
389 (with-temp-buffer
398 (magit--with-temp-process-buffer
390399 (apply #'magit-process-file magit-git-executable nil (list t nil) nil
391400 (magit-process-git-arguments args))
392401 (unless (bobp)
397406 "Execute Git with ARGS, returning its output."
398407 (setq args (-flatten args))
399408 (magit--with-refresh-cache (cons default-directory args)
400 (with-temp-buffer
409 (magit--with-temp-process-buffer
401410 (apply #'magit-process-file magit-git-executable nil (list t nil) nil
402411 (magit-process-git-arguments args))
403412 (buffer-substring-no-properties (point-min) (point-max)))))
467476 newline, return an empty string."
468477 (setq args (-flatten args))
469478 (magit--with-refresh-cache (cons default-directory args)
470 (with-temp-buffer
479 (magit--with-temp-process-buffer
471480 (apply #'magit-git-insert args)
472481 (unless (bobp)
473482 (goto-char (point-min))
479488
480489 If Git exits with a non-zero exit status, then report show a
481490 message and add a section in the respective process buffer."
482 (with-temp-buffer
491 (magit--with-temp-process-buffer
483492 (apply #'magit-git-insert args)
484493 (split-string (buffer-string) "\n" t)))
485494
489498
490499 If Git exits with a non-zero exit status, then report show a
491500 message and add a section in the respective process buffer."
492 (with-temp-buffer
501 (magit--with-temp-process-buffer
493502 (apply #'magit-git-insert args)
494503 (split-string (buffer-string) "\0" t)))
495504
718727 ;; Git bug. See #2364.
719728 (not (equal wtree ".git")))
720729 ;; Return the linked working tree.
721 (file-name-directory wtree))
730 (concat (file-remote-p default-directory)
731 (file-name-directory wtree)))
722732 ;; The working directory may not be the parent directory of
723733 ;; .git if it was set up with `git init --separate-git-dir'.
724734 ;; See #2955.
737747 (magit--not-inside-repository-error)))))
738748
739749 (define-error 'magit-outside-git-repo "Not inside Git repository")
750 (define-error 'magit-corrupt-git-config "Corrupt Git configuration")
740751 (define-error 'magit-git-executable-not-found
741752 "Git executable cannot be found (see https://magit.vc/goto/e6a78ed2)")
742753
754 (defun magit--assert-usable-git ()
755 (if (not (executable-find magit-git-executable))
756 (signal 'magit-git-executable-not-found magit-git-executable)
757 (let ((magit-git-debug
758 (lambda (err)
759 (signal 'magit-corrupt-git-config
760 (format "%s: %s" default-directory err)))))
761 ;; This should always succeed unless there's a corrupt config
762 ;; (or at least a similarly severe failing state). Note that
763 ;; git-config's --default is avoided because it's not available
764 ;; until Git 2.18.
765 (magit-git-string "config" "--get-color" "" "reset"))
766 nil))
767
743768 (defun magit--not-inside-repository-error ()
744 (if (executable-find magit-git-executable)
745 (signal 'magit-outside-git-repo default-directory)
746 (signal 'magit-git-executable-not-found magit-git-executable)))
769 (magit--assert-usable-git)
770 (signal 'magit-outside-git-repo default-directory))
747771
748772 (defun magit-inside-gitdir-p (&optional noerror)
749773 "Return t if `default-directory' is below the repository directory.
892916 revA revB))))
893917
894918 (defun magit-file-status (&rest args)
895 (with-temp-buffer
919 (magit--with-temp-process-buffer
896920 (save-excursion (magit-git-insert "status" "-z" args))
897921 (let ((pos (point)) status)
898922 (while (> (skip-chars-forward "[:print:]") 0)
13711395 then return nil. I.e. return the name of an existing local or
13721396 remote-tracking branch. The returned string is colorized
13731397 according to the branch type."
1374 (when-let ((branch (or branch (magit-get-current-branch)))
1375 (upstream (magit-ref-abbrev (concat branch "@{upstream}"))))
1376 (magit--propertize-face
1377 upstream (if (equal (magit-get "branch" branch "remote") ".")
1378 'magit-branch-local
1379 'magit-branch-remote))))
1398 (magit--with-refresh-cache (list 'magit-get-upstream-branch branch)
1399 (when-let ((branch (or branch (magit-get-current-branch)))
1400 (upstream (magit-ref-abbrev (concat branch "@{upstream}"))))
1401 (magit--propertize-face
1402 upstream (if (equal (magit-get "branch" branch "remote") ".")
1403 'magit-branch-local
1404 'magit-branch-remote)))))
13801405
13811406 (defun magit-get-indirect-upstream-branch (branch &optional force)
13821407 (let ((remote (magit-get "branch" branch "remote")))
14291454 (when-let ((remotes (magit-list-remotes))
14301455 (remote (if (= (length remotes) 1)
14311456 (car remotes)
1432 (car (member "origin" remotes)))))
1457 (magit-primary-remote))))
14331458 (magit--propertize-face remote 'magit-branch-remote))))
14341459
14351460 (defun magit-get-push-remote (&optional branch)
14401465 (magit--propertize-face remote 'magit-branch-remote)))
14411466
14421467 (defun magit-get-push-branch (&optional branch verify)
1443 (when-let ((branch (or branch (setq branch (magit-get-current-branch))))
1444 (remote (magit-get-push-remote branch))
1445 (target (concat remote "/" branch)))
1446 (and (or (not verify)
1447 (magit-rev-verify target))
1448 (magit--propertize-face target 'magit-branch-remote))))
1468 (magit--with-refresh-cache (list 'magit-get-push-branch branch verify)
1469 (when-let ((branch (or branch (setq branch (magit-get-current-branch))))
1470 (remote (magit-get-push-remote branch))
1471 (target (concat remote "/" branch)))
1472 (and (or (not verify)
1473 (magit-rev-verify target))
1474 (magit--propertize-face target 'magit-branch-remote)))))
14491475
14501476 (defun magit-get-@{push}-branch (&optional branch)
14511477 (let ((ref (magit-rev-parse "--symbolic-full-name"
14611487
14621488 (defun magit-get-some-remote (&optional branch)
14631489 (or (magit-get-remote branch)
1464 (and (magit-branch-p "master")
1465 (magit-get-remote "master"))
1466 (let ((remotes (magit-list-remotes)))
1467 (or (car (member "origin" remotes))
1468 (car remotes)))))
1490 (when-let ((main (magit-main-branch)))
1491 (magit-get-remote main))
1492 (magit-primary-remote)
1493 (car (magit-list-remotes))))
1494
1495 (defvar magit-primary-remote-names
1496 '("upstream" "origin"))
1497
1498 (defun magit-primary-remote ()
1499 "Return the primary remote.
1500
1501 The primary remote is the remote that tracks the repository that
1502 other repositories are forked from. It often is called \"origin\"
1503 but because many people name their own fork \"origin\", using that
1504 term would be ambiguous. Likewise we avoid the term \"upstream\"
1505 because a branch's @{upstream} branch may be a local branch or a
1506 branch from a remote other than the primary remote.
1507
1508 If a remote exists whose name matches `magit.primaryRemote', then
1509 that is considered the primary remote. If no remote by that name
1510 exists, then remotes in `magit-primary-remote-names' are tried in
1511 order and the first remote from that list that actually exists in
1512 the current repository is considered its primary remote."
1513 (let ((remotes (magit-list-remotes)))
1514 (seq-find (lambda (name)
1515 (member name remotes))
1516 (delete-dups
1517 (delq nil
1518 (cons (magit-get "magit.primaryRemote")
1519 magit-primary-remote-names))))))
14691520
14701521 (defun magit-branch-merged-p (branch &optional target)
14711522 "Return non-nil if BRANCH is merged into its upstream and TARGET.
14941545 the name of a remote and REF is the ref local to the remote."
14951546 (when-let ((ref (magit-ref-fullname refname)))
14961547 (save-match-data
1497 (-some (lambda (line)
1498 (and (string-match "\
1548 (seq-some (lambda (line)
1549 (and (string-match "\
14991550 \\`remote\\.\\([^.]+\\)\\.fetch=\\+?\\([^:]+\\):\\(.+\\)" line)
1500 (let ((rmt (match-string 1 line))
1501 (src (match-string 2 line))
1502 (dst (match-string 3 line)))
1503 (and (string-match (format "\\`%s\\'"
1504 (replace-regexp-in-string
1505 "*" "\\(.+\\)" dst t t))
1506 ref)
1507 (cons rmt (replace-regexp-in-string
1508 "*" (match-string 1 ref) src))))))
1509 (magit-git-lines "config" "--local" "--list")))))
1551 (let ((rmt (match-string 1 line))
1552 (src (match-string 2 line))
1553 (dst (match-string 3 line)))
1554 (and (string-match (format "\\`%s\\'"
1555 (replace-regexp-in-string
1556 "*" "\\(.+\\)" dst t t))
1557 ref)
1558 (cons rmt (replace-regexp-in-string
1559 "*" (match-string 1 ref) src))))))
1560 (magit-git-lines "config" "--local" "--list")))))
15101561
15111562 (defun magit-split-branch-name (branch)
15121563 (cond ((member branch (magit-list-local-branch-names))
15131564 (cons "." branch))
15141565 ((string-match "/" branch)
1515 (or (-some (lambda (remote)
1516 (and (string-match (format "\\`\\(%s\\)/\\(.+\\)\\'" remote)
1517 branch)
1518 (cons (match-string 1 branch)
1519 (match-string 2 branch))))
1520 (magit-list-remotes))
1566 (or (seq-some (lambda (remote)
1567 (and (string-match
1568 (format "\\`\\(%s\\)/\\(.+\\)\\'" remote)
1569 branch)
1570 (cons (match-string 1 branch)
1571 (match-string 2 branch))))
1572 (magit-list-remotes))
15211573 (error "Invalid branch name %s" branch)))))
15221574
15231575 (defun magit-get-current-tag (&optional rev with-distance)
16021654 (magit-list-related-branches "--contains" commit args))
16031655
16041656 (defun magit-list-publishing-branches (&optional commit)
1605 (--filter (magit-rev-ancestor-p commit it)
1657 (--filter (magit-rev-ancestor-p (or commit "HEAD") it)
16061658 magit-published-branches))
16071659
16081660 (defun magit-list-merged-branches (&optional commit &rest args)
16951747 (substring it 41))
16961748 (magit-git-lines "ls-remote" remote)))
16971749
1750 (defun magit-list-modified-modules ()
1751 (--keep (and (string-match "\\`\\+\\([^ ]+\\) \\(.+\\) (.+)\\'" it)
1752 (match-string 2 it))
1753 (magit-git-lines "submodule" "status")))
1754
16981755 (defun magit-list-module-paths ()
16991756 (--mapcat (and (string-match "^160000 [0-9a-z]\\{40\\} 0\t\\(.+\\)$" it)
17001757 (list (match-string 1 it)))
17011758 (magit-git-items "ls-files" "-z" "--stage")))
17021759
1760 (defun magit-list-module-names ()
1761 (mapcar #'magit-get-submodule-name (magit-list-module-paths)))
1762
17031763 (defun magit-get-submodule-name (path)
17041764 "Return the name of the submodule at PATH.
17051765 PATH has to be relative to the super-repository."
1706 (cadr (split-string
1707 (car (or (magit-git-items
1708 "config" "-z"
1709 "-f" (expand-file-name ".gitmodules" (magit-toplevel))
1710 "--get-regexp" "^submodule\\..*\\.path$"
1711 (concat "^" (regexp-quote (directory-file-name path)) "$"))
1712 (error "No such submodule `%s'" path)))
1713 "\n")))
1766 (magit-git-string "submodule--helper" "name" path))
17141767
17151768 (defun magit-list-worktrees ()
17161769 (let (worktrees worktree)
17671820 (defun magit-remote-p (string)
17681821 (car (member string (magit-list-remotes))))
17691822
1823 (defvar magit-main-branch-names
1824 ;; These are the names that Git suggests
1825 ;; if `init.defaultBranch' is undefined.
1826 '("main" "master" "trunk" "development"))
1827
1828 (defun magit-main-branch ()
1829 "Return the main branch.
1830
1831 If a branch exists whose name matches `init.defaultBranch', then
1832 that is considered the main branch. If no branch by that name
1833 exists, then the branch names in `magit-main-branch-names' are
1834 tried in order. The first branch from that list that actually
1835 exists in the current repository is considered its main branch."
1836 (let ((branches (magit-list-local-branch-names)))
1837 (seq-find (lambda (name)
1838 (member name branches))
1839 (delete-dups
1840 (delq nil
1841 (cons (magit-get "init.defaultBranch")
1842 magit-main-branch-names))))))
1843
17701844 (defun magit-rev-diff-count (a b)
17711845 "Return the commits in A but not B and vice versa.
17721846 Return a list of two integers: (A>B B>A)."
17771851 "\t")))
17781852
17791853 (defun magit-abbrev-length ()
1780 (--if-let (magit-get "core.abbrev")
1781 (string-to-number it)
1782 ;; Guess the length git will be using based on an example
1783 ;; abbreviation. Actually HEAD's abbreviation might be an
1784 ;; outlier, so use the shorter of the abbreviations for two
1785 ;; commits. When a commit does not exist, then fall back
1786 ;; to the default of 7. See #3034.
1787 (min (--if-let (magit-rev-parse "--short" "HEAD") (length it) 7)
1788 (--if-let (magit-rev-parse "--short" "HEAD~") (length it) 7))))
1854 (let ((abbrev (magit-get "core.abbrev")))
1855 (if (and abbrev (not (equal abbrev "auto")))
1856 (string-to-number abbrev)
1857 ;; Guess the length git will be using based on an example
1858 ;; abbreviation. Actually HEAD's abbreviation might be an
1859 ;; outlier, so use the shorter of the abbreviations for two
1860 ;; commits. See #3034.
1861 (if-let ((head (magit-rev-parse "--short" "HEAD"))
1862 (head-len (length head)))
1863 (min head-len
1864 (--if-let (magit-rev-parse "--short" "HEAD~")
1865 (length it)
1866 head-len))
1867 ;; We're on an unborn branch, but perhaps the repository has
1868 ;; other commits. See #4123.
1869 (if-let ((commits (magit-git-lines "rev-list" "-n2" "--all"
1870 "--abbrev-commit")))
1871 (apply #'min (mapcar #'length commits))
1872 ;; A commit does not exist. Fall back to the default of 7.
1873 7)))))
17891874
17901875 (defun magit-abbrev-arg (&optional arg)
17911876 (format "--%s=%d" (or arg "abbrev") (magit-abbrev-length)))
18071892 (cdr (split-string it))))
18081893
18091894 (defun magit-patch-id (rev)
1810 (with-temp-buffer
1895 (magit--with-temp-process-buffer
18111896 (magit-process-file
18121897 shell-file-name nil '(t nil) nil shell-command-switch
18131898 (let ((exec (shell-quote-argument magit-git-executable)))
19582043 (defmacro magit-with-blob (commit file &rest body)
19592044 (declare (indent 2)
19602045 (debug (form form body)))
1961 `(with-temp-buffer
2046 `(magit--with-temp-process-buffer
19622047 (let ((buffer-file-name ,file))
19632048 (save-excursion
19642049 (magit-git-insert "cat-file" "-p"
20532138 (--when-let
20542139 (let ((c "\s\n\t~^:?*[\\"))
20552140 (cl-letf (((get 'git-revision 'beginning-op)
2056 (if (re-search-backward (format "[%s]" c) nil t)
2057 (forward-char)
2058 (goto-char (point-min))))
2141 (lambda ()
2142 (if (re-search-backward (format "[%s]" c) nil t)
2143 (forward-char)
2144 (goto-char (point-min)))))
20592145 ((get 'git-revision 'end-op)
20602146 (lambda ()
20612147 (re-search-forward (format "\\=[^%s]*" c) nil t))))
20622148 (bounds-of-thing-at-point 'git-revision)))
20632149 (let ((text (buffer-substring-no-properties (car it) (cdr it))))
2064 (and (magit-commit-p text) text))))
2150 (and (>= (length text) 7)
2151 (string-match-p "[a-z]" text)
2152 (magit-commit-p text)
2153 text))))
20652154
20662155 ;;; Completion
20672156
22172306 (or (let ((r (car (member (magit-remote-branch-at-point) branches)))
22182307 (l (car (member (magit-local-branch-at-point) branches))))
22192308 (if magit-prefer-remote-upstream (or r l) (or l r)))
2220 (let ((r (car (member "origin/master" branches)))
2221 (l (car (member "master" branches))))
2222 (if magit-prefer-remote-upstream (or r l) (or l r)))
2309 (when-let ((main (magit-main-branch)))
2310 (let ((r (car (member (concat "origin/" main) branches)))
2311 (l (car (member main branches))))
2312 (if magit-prefer-remote-upstream (or r l) (or l r))))
22232313 (car (member (magit-get-previous-branch) branches))))))
22242314
22252315 (defun magit-read-starting-point (prompt &optional branch default)
22532343 (magit-tag-at-point)))
22542344
22552345 (defun magit-read-stash (prompt)
2256 (let ((stashes (magit-list-stashes)))
2257 (magit-completing-read prompt stashes nil t nil nil
2258 (magit-stash-at-point)
2259 (car stashes))))
2346 (let* ((atpoint (magit-stash-at-point))
2347 (default (and atpoint
2348 (concat atpoint (magit-rev-format " %s" atpoint))))
2349 (choices (mapcar (lambda (c)
2350 (pcase-let ((`(,rev ,msg) (split-string c "\0")))
2351 (concat (propertize rev 'face 'magit-hash)
2352 " " msg)))
2353 (magit-list-stashes "%gd%x00%s")))
2354 (choice (magit-completing-read prompt choices
2355 nil t nil nil
2356 default
2357 (car choices))))
2358 (and choice
2359 (string-match "^\\([^ ]+\\) \\(.+\\)" choice)
2360 (substring-no-properties (match-string 1 choice)))))
22602361
22612362 (defun magit-read-remote (prompt &optional default use-only)
22622363 (let ((remotes (magit-list-remotes)))
00 ;;; magit-gitignore.el --- intentionally untracked files -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2008-2020 The Magit Project Contributors
2 ;; Copyright (C) 2008-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
77 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9
10 ;; SPDX-License-Identifier: GPL-3.0-or-later
911
1012 ;; Magit is free software; you can redistribute it and/or modify it
1113 ;; under the terms of the GNU General Public License as published by
2628
2729 ;;; Code:
2830
29 (eval-when-compile
30 (require 'subr-x))
31
3231 (require 'magit)
3332
3433 ;;; Transient
3534
3635 ;;;###autoload (autoload 'magit-gitignore "magit-gitignore" nil t)
37 (define-transient-command magit-gitignore ()
36 (transient-define-prefix magit-gitignore ()
3837 "Instruct Git to ignore a file or pattern."
3938 :man-page "gitignore"
4039 ["Gitignore"
7069
7170 ;;;###autoload
7271 (defun magit-gitignore-in-subdir (rule directory)
73 "Add the Git ignore RULE to a \".gitignore\" file.
74 Prompted the user for a directory and add the rule to the
72 "Add the Git ignore RULE to a \".gitignore\" file in DIRECTORY.
73 Prompt the user for a directory and add the rule to the
7574 \".gitignore\" file in that directory. Since such files are
7675 tracked, they are shared with other clones of the repository.
7776 Also stage the file."
8079 (magit-with-toplevel
8180 (let ((file (expand-file-name ".gitignore" directory)))
8281 (magit--gitignore rule file)
83 (magit-run-git "add" file))))
82 (magit-run-git "add" (magit-convert-filename-for-git file)))))
8483
8584 ;;;###autoload
8685 (defun magit-gitignore-in-gitdir (rule)
00 ;;; magit-imenu.el --- Integrate Imenu in magit major modes -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2010-2020 The Magit Project Contributors
2 ;; Copyright (C) 2010-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
77 ;; Author: Damien Cassou <damien@cassou.me>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9
10 ;; SPDX-License-Identifier: GPL-3.0-or-later
911
1012 ;; Magit is free software; you can redistribute it and/or modify it
1113 ;; under the terms of the GNU General Public License as published by
3133 ;; magit-imenu.el adds Imenu support to every major mode in Magit.
3234
3335 ;;; Code:
34
35 (eval-when-compile
36 (require 'subr-x))
3736
3837 (require 'magit)
3938 (require 'git-rebase)
00 ;;; magit-libgit.el --- Libgit functionality -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2010-2020 The Magit Project Contributors
2 ;; Copyright (C) 2010-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
77 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9
10 ;; Package-Requires: ((emacs "26.1") (magit "0") (libgit "0"))
119 ;; Keywords: git tools vc
1210 ;; Homepage: https://github.com/magit/magit
11
12 ;; Package-Requires: ((emacs "26.1") (magit "3.0.0") (libgit "0"))
13 ;; Package-Version: 0
14 ;; SPDX-License-Identifier: GPL-3.0-or-later
1315
1416 ;; Magit is free software; you can redistribute it and/or modify it
1517 ;; under the terms of the GNU General Public License as published by
4143 ;;; Code:
4244
4345 (require 'cl-lib)
46 (require 'dash)
47 (require 'eieio)
48 (require 'seq)
4449 (require 'subr-x)
4550
4651 (require 'magit-git)
52
4753 (require 'libgit)
4854
4955 ;;; Utilities
00 ;;; magit-log.el --- inspect Git history -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2010-2020 The Magit Project Contributors
2 ;; Copyright (C) 2010-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
77 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9
10 ;; SPDX-License-Identifier: GPL-3.0-or-later
911
1012 ;; Magit is free software; you can redistribute it and/or modify it
1113 ;; under the terms of the GNU General Public License as published by
5254 (require 'crm)
5355 (require 'which-func)
5456
55 (eval-when-compile
56 (require 'subr-x))
57
5857 ;;; Options
5958 ;;;; Log Mode
6059
6160 (defgroup magit-log nil
6261 "Inspect and manipulate Git history."
6362 :link '(info-link "(magit)Logging")
63 :group 'magit-commands
6464 :group 'magit-modes)
6565
6666 (defcustom magit-log-mode-hook nil
317317 (pcase-let ((`(,args ,files)
318318 (magit-log--get-value 'magit-log-mode
319319 magit-prefix-use-buffer-arguments)))
320 (unless (eq current-transient-command 'magit-dispatch)
320 (unless (eq transient-current-command 'magit-dispatch)
321321 (when-let ((file (magit-file-relative-name)))
322322 (setq files (list file))))
323323 (oset obj value (if files `(("--" ,@files) ,args) args))))
338338
339339 (defun magit-log-arguments (&optional mode)
340340 "Return the current log arguments."
341 (if (memq current-transient-command '(magit-log magit-log-refresh))
341 (if (memq transient-current-command '(magit-log magit-log-refresh))
342342 (pcase-let ((`(,args ,alist)
343343 (-separate #'atom (transient-get-value))))
344344 (list args (cdr (assoc "--" alist))))
391391 ;;;; Prefix Commands
392392
393393 ;;;###autoload (autoload 'magit-log "magit-log" nil t)
394 (define-transient-command magit-log ()
394 (transient-define-prefix magit-log ()
395395 "Show a commit or reference log."
396396 :man-page "git-log"
397397 :class 'magit-log-prefix
408408 (7 "=s" "Limit to commits since" "--since=" transient-read-date)
409409 (7 "=u" "Limit to commits until" "--until=" transient-read-date)
410410 (magit-log:--grep)
411 (7 "-I" "Invert search pattern" "--invert-grep")
411 (7 "-i" "Search case-insensitive" ("-i" "--regexp-ignore-case"))
412 (7 "-I" "Invert search pattern" "--invert-grep")
412413 (magit-log:-G) ;2
413414 (magit-log:-S) ;2
414415 (magit-log:-L) ;2
449450 ("r" "current" magit-reflog-current)
450451 ("O" "other" magit-reflog-other)
451452 ("H" "HEAD" magit-reflog-head)]
452 [:if magit--any-wip-mode-enabled-p
453 [:if (lambda ()
454 (require 'magit-wip)
455 (magit--any-wip-mode-enabled-p))
453456 :description "Wiplog"
454457 ("i" "index" magit-wip-log-index)
455 ("w" "worktree" magit-wip-log-worktree)]])
458 ("w" "worktree" magit-wip-log-worktree)]
459 ["Other"
460 (5 "s" "shortlog" magit-shortlog)]])
456461
457462 ;;;###autoload (autoload 'magit-log-refresh "magit-log" nil t)
458 (define-transient-command magit-log-refresh ()
463 (transient-define-prefix magit-log-refresh ()
459464 "Change the arguments used for the log(s) in the current buffer."
460465 :man-page "git-log"
461466 :class 'magit-log-refresh-prefix
465470 (magit-log:-n)
466471 (magit:--author)
467472 (magit-log:--grep)
468 (7 "-I" "Invert search pattern" "--invert-grep")
473 (7 "-i" "Search case-insensitive" ("-i" "--regexp-ignore-case"))
474 (7 "-I" "Invert search pattern" "--invert-grep")
469475 (magit-log:-G)
470476 (magit-log:-S)
471477 (magit-log:-L)]
510516 ("b" "buffer lock" magit-toggle-buffer-lock)]]
511517 (interactive)
512518 (cond
513 ((not (eq current-transient-command 'magit-log-refresh))
519 ((not (eq transient-current-command 'magit-log-refresh))
514520 (pcase major-mode
515521 (`magit-reflog-mode
516522 (user-error "Cannot change log arguments in reflog buffers"))
526532
527533 ;;;; Infix Commands
528534
529 (define-infix-argument magit-log:-n ()
535 (transient-define-argument magit-log:-n ()
530536 :description "Limit number of commits"
531537 :class 'transient-option
532538 ;; For historic reasons (and because it easy to guess what "-n"
536542 :argument "-n"
537543 :reader 'transient-read-number-N+)
538544
539 (define-infix-argument magit:--author ()
545 (transient-define-argument magit:--author ()
540546 :description "Limit to author"
541547 :class 'transient-option
542548 :key "-A"
543549 :argument "--author="
544550 :reader 'magit-transient-read-person)
545551
546 (define-infix-argument magit-log:--*-order ()
552 (transient-define-argument magit-log:--*-order ()
547553 :description "Order commits by"
548554 :class 'transient-switches
549555 :key "-o"
551557 :argument-regexp "\\(--\\(topo\\|author-date\\|date\\)-order\\)"
552558 :choices '("topo" "author-date" "date"))
553559
554 (define-infix-argument magit-log:--grep ()
560 (transient-define-argument magit-log:--grep ()
555561 :description "Search messages"
556562 :class 'transient-option
557563 :key "-F"
558564 :argument "--grep=")
559565
560 (define-infix-argument magit-log:-G ()
566 (transient-define-argument magit-log:-G ()
561567 :description "Search changes"
562568 :class 'transient-option
563569 :argument "-G")
564570
565 (define-infix-argument magit-log:-S ()
571 (transient-define-argument magit-log:-S ()
566572 :description "Search occurrences"
567573 :class 'transient-option
568574 :argument "-S")
569575
570 (define-infix-argument magit-log:-L ()
576 (transient-define-argument magit-log:-L ()
571577 :description "Trace line evolution"
572578 :class 'transient-option
573579 :argument "-L"
870876 "\\[magit-log-double-commit-limit] first"))))
871877 (user-error "Parent %s does not exist" parent-rev))))))
872878
879 ;;;; Shortlog Commands
880
881 ;;;###autoload (autoload 'magit-shortlog "magit-log" nil t)
882 (transient-define-prefix magit-shortlog ()
883 "Show a history summary."
884 :man-page "git-shortlog"
885 :value '("--numbered" "--summary")
886 ["Arguments"
887 ("-n" "Sort by number of commits" ("-n" "--numbered"))
888 ("-s" "Show commit count summary only" ("-s" "--summary"))
889 ("-e" "Show email addresses" ("-e" "--email"))
890 ("-g" "Group commits by" "--group="
891 :choices ("author" "committer" "trailer:"))
892 (7 "-f" "Format string" "--format=")
893 (7 "-w" "Linewrap" "-w" :class transient-option)]
894 ["Shortlog"
895 ("s" "since" magit-shortlog-since)
896 ("r" "range" magit-shortlog-range)])
897
898 (defun magit-git-shortlog (rev args)
899 (with-current-buffer (get-buffer-create "*magit-shortlog*")
900 (erase-buffer)
901 (save-excursion
902 (magit-git-insert "shortlog" args rev))
903 (switch-to-buffer-other-window (current-buffer))))
904
905 ;;;###autoload
906 (defun magit-shortlog-since (rev args)
907 "Show a history summary for commits since REV."
908 (interactive
909 (list (magit-read-branch-or-commit "Shortlog since" (magit-get-current-tag))
910 (transient-args 'magit-shortlog)))
911 (magit-git-shortlog (concat rev "..") args))
912
913 ;;;###autoload
914 (defun magit-shortlog-range (rev-or-range args)
915 "Show a history summary for commit or range REV-OR-RANGE."
916 (interactive
917 (list (magit-read-range-or-commit "Shortlog for revision or range")
918 (transient-args 'magit-shortlog)))
919 (magit-git-shortlog rev-or-range args))
920
873921 ;;; Log Mode
874922
875923 (defvar magit-log-disable-graph-hack-args
9981046 (remove "--literal-pathspecs" magit-git-global-arguments)))
9991047 (magit-git-wash (apply-partially #'magit-log-wash-log 'log)
10001048 "log"
1001 (format "--format=%s%%h%%x00%s%%x00%s%%x00%%aN%%x00%s%%x00%%s%s"
1049 (format "--format=%s%%h%%x0c%s%%x0c%s%%x0c%%aN%%x0c%s%%x0c%%s%s"
10021050 (if (and (member "--left-right" args)
10031051 (not (member "--graph" args)))
10041052 "%m "
10211069 (setq args (cons "--decorate=full" (remove "--decorate" args))))
10221070 (when (member "--reverse" args)
10231071 (setq args (remove "--graph" args)))
1072 (setq args (magit-diff--maybe-add-stat-arguments args))
10241073 args)
10251074 "--use-mailmap" "--no-prefix" revs "--" files)))
10261075
10381087 "Keymap for `module-commit' sections.")
10391088
10401089 (defconst magit-log-heading-re
1090 ;; Note: A form feed instead of a null byte is used as the delimiter
1091 ;; because using the latter interferes with the graph prefix when
1092 ;; ++header is used.
10411093 (concat "^"
10421094 "\\(?4:[-_/|\\*o<>. ]*\\)" ; graph
1043 "\\(?1:[0-9a-fA-F]+\\)?\0" ; sha1
1044 "\\(?3:[^\0\n]+\\)?\0" ; refs
1045 "\\(?7:[BGUXYREN]\\)?\0" ; gpg
1046 "\\(?5:[^\0\n]*\\)\0" ; author
1095 "\\(?1:[0-9a-fA-F]+\\)? " ; sha1
1096 "\\(?3:[^ \n]+\\)? " ; refs
1097 "\\(?7:[BGUXYREN]\\)? " ; gpg
1098 "\\(?5:[^ \n]*\\) " ; author
10471099 ;; Note: Date is optional because, prior to Git v2.19.0,
10481100 ;; `git rebase -i --root` corrupts the root's author date.
1049 "\\(?6:[^\0\n]*\\)\0" ; date
1101 "\\(?6:[^ \n]*\\) " ; date
10501102 "\\(?2:.*\\)$")) ; msg
10511103
10521104 (defconst magit-log-cherry-re
10701122
10711123 (defconst magit-log-bisect-log-re
10721124 (concat "^# "
1073 "\\(?3:bad:\\|skip:\\|good:\\) " ; "refs"
1125 "\\(?3:[^: \n]+:\\) " ; "refs"
10741126 "\\[\\(?1:[^]\n]+\\)\\] " ; sha1
10751127 "\\(?2:.*\\)$")) ; msg
10761128
11601212 (`stash (oset section type 'stash))
11611213 (`module (oset section type 'module-commit))
11621214 (`bisect-log (setq hash (magit-rev-parse "--short" hash))))
1215 (setq hash (propertize hash 'font-lock-face
1216 (pcase (and gpg (aref gpg 0))
1217 (?G 'magit-signature-good)
1218 (?B 'magit-signature-bad)
1219 (?U 'magit-signature-untrusted)
1220 (?X 'magit-signature-expired)
1221 (?Y 'magit-signature-expired-key)
1222 (?R 'magit-signature-revoked)
1223 (?E 'magit-signature-error)
1224 (?N 'magit-hash)
1225 (_ 'magit-hash))))
11631226 (when cherry
11641227 (when (and (derived-mode-p 'magit-refs-mode)
11651228 magit-refs-show-commit-count)
11761239 'magit-cherry-unmatched)))
11771240 (insert ?\s))
11781241 (when align
1179 (insert (propertize hash 'font-lock-face 'magit-hash) ?\s))
1242 (insert hash ?\s))
11801243 (when graph
11811244 (insert graph))
11821245 (unless align
1183 (insert (propertize hash 'font-lock-face 'magit-hash) ?\s))
1246 (insert hash ?\s))
11841247 (when (and refs (not magit-log-show-refname-after-summary))
11851248 (insert (magit-format-ref-labels refs) ?\s))
11861249 (when (eq style 'reflog)
11891252 (insert (magit-reflog-format-subject
11901253 (substring refsub 0 (if (string-match-p ":" refsub) -2 -1))))))
11911254 (when msg
1192 (when gpg
1193 (setq msg (propertize msg 'font-lock-face
1194 (pcase (aref gpg 0)
1195 (?G 'magit-signature-good)
1196 (?B 'magit-signature-bad)
1197 (?U 'magit-signature-untrusted)
1198 (?X 'magit-signature-expired)
1199 (?Y 'magit-signature-expired-key)
1200 (?R 'magit-signature-revoked)
1201 (?E 'magit-signature-error)))))
12021255 (insert (funcall magit-log-format-message-function hash msg)))
12031256 (when (and refs magit-log-show-refname-after-summary)
12041257 (insert ?\s)
13121365 (setq magit--update-revision-buffer (list commit buffer))
13131366 (run-with-idle-timer
13141367 magit-update-other-window-delay nil
1315 (let ((args (with-current-buffer buffer
1316 (let ((magit-direct-use-buffer-arguments 'selected))
1317 (magit-show-commit--arguments)))))
1368 (let ((args (let ((magit-direct-use-buffer-arguments 'selected))
1369 (magit-show-commit--arguments))))
13181370 (lambda ()
13191371 (pcase-let ((`(,rev ,buf) magit--update-revision-buffer))
13201372 (setq magit--update-revision-buffer nil)
13941446 (truncate-string-to-width
13951447 (or author "")
13961448 details-width
1397 nil ?\s (make-string 1 magit-ellipsis))
1449 nil ?\s
1450 (if (char-displayable-p ?…) "…" ">"))
13981451 'magit-log-author)
13991452 " "))
14001453 (magit--propertize-face
16551708 (defun magit-insert-unpulled-from-pushremote ()
16561709 "Insert commits that haven't been pulled from the push-remote yet."
16571710 (--when-let (magit-get-push-branch)
1658 (unless (and (equal (magit-rev-name it)
1659 (magit-rev-name "@{upstream}"))
1660 (or (memq 'magit-insert-unpulled-from-upstream
1661 magit-status-sections-hook)
1662 (memq 'magit-insert-unpulled-from-upstream-or-recent
1663 magit-status-sections-hook)))
1711 (when (magit--insert-pushremote-log-p)
16641712 (magit-insert-section (unpulled (concat ".." it) t)
16651713 (magit-insert-heading
16661714 (format (propertize "Unpulled from %s."
17241772 (defun magit-insert-unpushed-to-pushremote ()
17251773 "Insert commits that haven't been pushed to the push-remote yet."
17261774 (--when-let (magit-get-push-branch)
1727 (unless (and (equal (magit-rev-name it)
1728 (magit-rev-name "@{upstream}"))
1729 (or (memq 'magit-insert-unpushed-to-upstream
1730 magit-status-sections-hook)
1731 (memq 'magit-insert-unpushed-to-upstream-or-recent
1732 magit-status-sections-hook)))
1775 (when (magit--insert-pushremote-log-p)
17331776 (magit-insert-section (unpushed (concat it "..") t)
17341777 (magit-insert-heading
17351778 (format (propertize "Unpushed to %s."
17371780 (propertize it 'font-lock-face 'magit-branch-remote)))
17381781 (magit-insert-log (concat it "..") magit-buffer-log-args)
17391782 (magit-log-insert-child-count)))))
1783
1784 (defun magit--insert-pushremote-log-p ()
1785 (magit--with-refresh-cache 'magit--insert-pushremote-log-p
1786 (not (and (equal (magit-get-push-branch)
1787 (magit-get-upstream-branch))
1788 (or (memq 'magit-insert-unpulled-from-upstream
1789 magit-status-sections-hook)
1790 (memq 'magit-insert-unpulled-from-upstream-or-recent
1791 magit-status-sections-hook))))))
17401792
17411793 (defun magit-log-insert-child-count ()
17421794 (when magit-section-show-child-count
00 ;;; magit-margin.el --- margins in Magit buffers -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2010-2020 The Magit Project Contributors
2 ;; Copyright (C) 2010-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
77 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9
10 ;; SPDX-License-Identifier: GPL-3.0-or-later
911
1012 ;; Magit is free software; you can redistribute it and/or modify it
1113 ;; under the terms of the GNU General Public License as published by
2931
3032 ;;; Code:
3133
32 (require 'dash)
33
34 (eval-when-compile
35 (require 'subr-x))
36
3734 (require 'magit-section)
3835 (require 'magit-transient)
3936 (require 'magit-mode)
6158
6259 ;;; Commands
6360
64 (define-transient-command magit-margin-settings ()
61 (transient-define-prefix magit-margin-settings ()
6562 "Change what information is displayed in the margin."
6663 :info-manual "(magit) Log Margin"
6764 ["Margin"
00 ;;; magit-merge.el --- merge functionality -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2010-2020 The Magit Project Contributors
2 ;; Copyright (C) 2010-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
77 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9
10 ;; SPDX-License-Identifier: GPL-3.0-or-later
911
1012 ;; Magit is free software; you can redistribute it and/or modify it
1113 ;; under the terms of the GNU General Public License as published by
2628
2729 ;;; Code:
2830
29 (eval-when-compile
30 (require 'subr-x))
31
3231 (require 'magit)
3332 (require 'magit-diff)
3433
3736 ;;; Commands
3837
3938 ;;;###autoload (autoload 'magit-merge "magit" nil t)
40 (define-transient-command magit-merge ()
39 (transient-define-prefix magit-merge ()
4140 "Merge branches."
4241 :man-page "git-merge"
4342 :incompatible '(("--ff-only" "--no-ff"))
4645 ("-f" "Fast-forward only" "--ff-only")
4746 ("-n" "No fast-forward" "--no-ff")
4847 (magit-merge:--strategy)
49 (5 magit-diff:--diff-algorithm :argument "--Xdiff-algorithm=")
48 (5 magit-merge:--strategy-option)
49 (5 magit-diff:--diff-algorithm :argument "-Xdiff-algorithm=")
5050 (5 magit:--gpg-sign)]
5151 ["Actions"
5252 :if-not magit-merge-in-progress-p
6666 (defun magit-merge-arguments ()
6767 (transient-args 'magit-merge))
6868
69 (define-infix-argument magit-merge:--strategy ()
69 (transient-define-argument magit-merge:--strategy ()
7070 :description "Strategy"
7171 :class 'transient-option
7272 ;; key for merge and rebase: "-s"
7676 :key "-s"
7777 :argument "--strategy="
7878 :choices '("resolve" "recursive" "octopus" "ours" "subtree"))
79
80 (transient-define-argument magit-merge:--strategy-option ()
81 :description "Strategy Option"
82 :class 'transient-option
83 :key "-X"
84 :argument "--strategy-option="
85 :choices '("ours" "theirs" "patience"))
7986
8087 ;;;###autoload
8188 (defun magit-merge-plain (rev &optional args nocommit)
132139 branch, then also remove the respective remote branch."
133140 (interactive
134141 (list (magit-read-other-local-branch
135 (format "Merge `%s' into" (magit-get-current-branch))
142 (format "Merge `%s' into"
143 (or (magit-get-current-branch)
144 (magit-rev-parse "HEAD")))
136145 nil
137146 (when-let ((upstream (magit-get-upstream-branch))
138147 (upstream (cdr (magit-split-branch-name upstream))))
139148 (and (magit-branch-p upstream) upstream)))
140149 (magit-merge-arguments)))
141 (let ((current (magit-get-current-branch)))
150 (let ((current (magit-get-current-branch))
151 (head (magit-rev-parse "HEAD")))
142152 (when (zerop (magit-call-git "checkout" branch))
143 (magit--merge-absorb current args))))
153 (if current
154 (magit--merge-absorb current args)
155 (magit-run-git-with-editor "merge" args head)))))
144156
145157 ;;;###autoload
146158 (defun magit-merge-absorb (branch &optional args)
157169 (magit--merge-absorb branch args))
158170
159171 (defun magit--merge-absorb (branch args)
160 (when (equal branch "master")
172 (when (equal branch (magit-main-branch))
161173 (unless (yes-or-no-p
162 "Do you really want to merge `master' into another branch? ")
174 (format "Do you really want to merge `%s' into another branch? "
175 branch))
163176 (user-error "Abort")))
164177 (if-let ((target (magit-get-push-branch branch t)))
165178 (progn
182195 (format "Merge branch '%s'%s [#%s]"
183196 branch
184197 (let ((current (magit-get-current-branch)))
185 (if (equal current "master") "" (format " into %s" current)))
198 (if (equal current (magit-main-branch))
199 ""
200 (format " into %s" current)))
186201 pr)
187202 branch)
188203 (magit-run-git-async "merge" args "--no-edit" branch))
00 ;;; magit-mode.el --- create and refresh Magit buffers -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2010-2020 The Magit Project Contributors
2 ;; Copyright (C) 2010-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
77 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9
10 ;; SPDX-License-Identifier: GPL-3.0-or-later
911
1012 ;; Magit is free software; you can redistribute it and/or modify it
1113 ;; under the terms of the GNU General Public License as published by
2830
2931 ;;; Code:
3032
31 (require 'cl-lib)
32 (require 'dash)
33
34 (eval-when-compile
35 (require 'subr-x))
36
37 (require 'transient)
38
3933 (require 'magit-section)
4034 (require 'magit-git)
35
36 (require 'format-spec)
37 (require 'help-mode)
38 (require 'transient)
4139
4240 ;; For `magit-display-buffer-fullcolumn-most-v1' from `git-commit'
4341 (defvar git-commit-mode)
5654 ;; For `magit-mode' from `bookmark'
5755 (defvar bookmark-make-record-function)
5856
59 (require 'format-spec)
60 (require 'help-mode)
61
6257 ;;; Options
6358
6459 (defcustom magit-mode-hook
234229 :package-version '(magit . "3.0.0")
235230 :group 'magit-buffers
236231 :group 'magit-commands
232 :group 'magit-diff
233 :group 'magit-log
237234 :type '(choice
238235 (const :tag "always use args from buffer" always)
239236 (const :tag "use args from buffer if displayed in frame" selected)
265262 :package-version '(magit . "3.0.0")
266263 :group 'magit-buffers
267264 :group 'magit-commands
265 :group 'magit-diff
266 :group 'magit-log
268267 :type '(choice
269268 (const :tag "always use args from buffer" always)
270269 (const :tag "use args from buffer if displayed in frame" selected)
346345 (define-key map (kbd "i") 'magit-gitignore)
347346 (define-key map (kbd "I") 'magit-gitignore)
348347 (define-key map (kbd "SPC") 'magit-diff-show-or-scroll-up)
348 (define-key map (kbd "S-SPC") 'magit-diff-show-or-scroll-down)
349349 (define-key map (kbd "DEL") 'magit-diff-show-or-scroll-down)
350350 (define-key map "+" 'magit-diff-more-context)
351351 (define-key map "-" 'magit-diff-less-context)
399399 (define-key map (kbd "C-c C-e") 'magit-edit-thing)
400400 (define-key map (kbd "C-c C-o") 'magit-browse-thing)
401401 (define-key map (kbd "C-c C-w") 'magit-browse-thing)
402 (define-key map (kbd "C-x a") 'magit-add-change-log-entry)
403 (define-key map (kbd "C-x 4 a") 'magit-add-change-log-entry-other-window)
404402 (define-key map (kbd "C-w") 'magit-copy-section-value)
405403 (define-key map (kbd "M-w") 'magit-copy-buffer-revision)
406404 (define-key map [remap previous-line] 'magit-previous-line)
422420 Where applicable, section-specific keymaps bind another command
423421 which visits the thing at point."
424422 (interactive)
425 (if (eq current-transient-command 'magit-dispatch)
423 (if (eq transient-current-command 'magit-dispatch)
426424 (call-interactively (key-binding (this-command-keys)))
427425 (user-error "There is no thing at point that could be visited")))
428426
431429 Where applicable, section-specific keymaps bind another command
432430 which lets you edit the thing at point, likely in another buffer."
433431 (interactive)
434 (if (eq current-transient-command 'magit-dispatch)
432 (if (eq transient-current-command 'magit-dispatch)
435433 (call-interactively (key-binding (this-command-keys)))
436434 (user-error "There is no thing at point that could be edited")))
437435
471469 ["Cherry pick" magit-cherry-pick t]
472470 ["Revert commit" magit-revert t]
473471 "---"
474 ["Ignore globally" magit-gitignore-globally t]
475 ["Ignore locally" magit-gitignore-locally t]
472 ["Ignore at toplevel" magit-gitignore-in-topdir t]
473 ["Ignore in subdirectory" magit-gitignore-in-subdir t]
476474 ["Discard" magit-discard t]
477475 ["Reset head and index" magit-reset-mixed t]
478476 ["Stash" magit-stash-both t]
512510 Magit is documented in info node `(magit)'."
513511 :group 'magit
514512 (hack-dir-local-variables-non-file-buffer)
513 (face-remap-add-relative 'header-line 'magit-header-line)
515514 (setq mode-line-process (magit-repository-local-get 'mode-line-process))
516 (setq-local bookmark-make-record-function 'magit--make-bookmark))
517
518 ;;; Highlighting
515 (setq-local bookmark-make-record-function 'magit--make-bookmark)
516 (setq-local isearch-filter-predicate 'magit-section--open-temporarily))
519517
520518 ;;; Local Variables
521519
693691 (display-buffer
694692 buffer (if (with-current-buffer buffer
695693 (derived-mode-p 'magit-diff-mode 'magit-process-mode))
696 nil ; display in another window
694 '(nil (inhibit-same-window . t))
697695 '(display-buffer-same-window))))
698696
699697 (defun magit--display-buffer-fullframe (buffer alist)
827825 \(or nil if there is no such buffer) unless VALUE is non-nil, in
828826 which case return the buffer that has been looked to that value.
829827
830 If FRAME nil or omitted, then consider all buffers. Otherwise
828 If FRAME is nil or omitted, then consider all buffers. Otherwise
831829 only consider buffers that are displayed in some live window
832830 on some frame.
833831 If `all', then consider all buffers on all frames.
848846 (w (window)
849847 (b (window-buffer window)))
850848 (f (frame)
851 (-some #'w (window-list frame 'no-minibuf))))
849 (seq-some #'w (window-list frame 'no-minibuf))))
852850 (pcase-exhaustive frame
853 (`nil (-some #'b (buffer-list)))
854 (`all (-some #'f (frame-list)))
855 (`visible (-some #'f (visible-frame-list)))
856 ((or `selected `t) (-some #'w (window-list (selected-frame))))
857 ((guard (framep frame)) (-some #'w (window-list frame)))))
851 (`nil (seq-some #'b (buffer-list)))
852 (`all (seq-some #'f (frame-list)))
853 (`visible (seq-some #'f (visible-frame-list)))
854 ((or `selected `t) (seq-some #'w (window-list (selected-frame))))
855 ((guard (framep frame)) (seq-some #'w (window-list frame)))))
858856 (magit--not-inside-repository-error)))
859857
860858 (defun magit-mode-get-buffer (mode &optional create frame value)
995993
996994 ;;; Refresh Buffers
997995
998 (defvar inhibit-magit-refresh nil)
996 (defvar magit-inhibit-refresh nil)
999997
1000998 (defun magit-refresh ()
1001999 "Refresh some buffers belonging to the current repository.
10051003
10061004 Run hooks `magit-pre-refresh-hook' and `magit-post-refresh-hook'."
10071005 (interactive)
1008 (unless inhibit-magit-refresh
1006 (unless magit-inhibit-refresh
10091007 (unwind-protect
10101008 (let ((start (current-time))
10111009 (magit--refresh-cache (or magit--refresh-cache
10331031 (magit-run-hook-with-benchmark 'magit-post-unstage-hook)))
10341032 (magit-run-hook-with-benchmark 'magit-post-refresh-hook)
10351033 (when magit-refresh-verbose
1036 (message "Refreshing magit...done (%.3fs, cached %s/%s)"
1037 (float-time (time-subtract (current-time) start))
1038 (caar magit--refresh-cache)
1039 (+ (caar magit--refresh-cache)
1040 (cdar magit--refresh-cache)))))
1034 (let* ((c (caar magit--refresh-cache))
1035 (a (+ c (cdar magit--refresh-cache))))
1036 (message "Refreshing magit...done (%.3fs, cached %s/%s (%.0f%%))"
1037 (float-time (time-subtract (current-time) start))
1038 c a (* (/ c (* a 1.0)) 100)))))
10411039 (run-hooks 'magit-unwind-refresh-hook))))
10421040
10431041 (defun magit-refresh-all ()
10671065 (when magit-refresh-verbose
10681066 (message "Refreshing buffer `%s'..." (buffer-name)))
10691067 (let* ((buffer (current-buffer))
1070 (windows
1071 (--mapcat (with-selected-window it
1072 (with-current-buffer buffer
1073 (when-let ((section (magit-current-section)))
1074 (list
1075 (nconc (list it section)
1076 (magit-refresh-get-relative-position))))))
1077 (or (get-buffer-window-list buffer nil t)
1078 (list (selected-window))))))
1068 (windows (cl-mapcan
1069 (lambda (window)
1070 (with-selected-window window
1071 (with-current-buffer buffer
1072 (when-let ((section (magit-current-section)))
1073 `(( ,window
1074 ,section
1075 ,@(magit-refresh-get-relative-position)))))))
1076 ;; If it qualifies, then the selected window
1077 ;; comes first, but we want to handle it last
1078 ;; so that its `magit-section-movement-hook'
1079 ;; run can override the effects of other runs.
1080 (or (nreverse (get-buffer-window-list buffer nil t))
1081 (list (selected-window))))))
10791082 (deactivate-mark)
10801083 (setq magit-section-highlight-overlays nil)
10811084 (setq magit-section-highlighted-section nil)
10871090 (save-excursion
10881091 (apply refresh (with-no-warnings magit-refresh-args))))
10891092 (pcase-dolist (`(,window . ,args) windows)
1090 (with-selected-window window
1093 (if (eq buffer (window-buffer window))
1094 (with-selected-window window
1095 (apply #'magit-section-goto-successor args))
10911096 (with-current-buffer buffer
1092 (apply #'magit-section-goto-successor args))))
1097 (let ((magit-section-movement-hook nil))
1098 (apply #'magit-section-goto-successor args)))))
10931099 (run-hooks 'magit-refresh-buffer-hook)
10941100 (magit-section-update-highlight)
10951101 (set-buffer-modified-p nil))
12611267
12621268 (defun magit-insert-xref-buttons ()
12631269 "Insert xref buttons."
1264 (when (or help-xref-stack help-xref-forward-stack)
1270 (when (and (not magit-buffer-locked-p)
1271 (or help-xref-stack help-xref-forward-stack))
12651272 (when help-xref-stack
12661273 (magit-xref-insert-button help-back-label 'magit-xref-backward))
12671274 (when help-xref-forward-stack
13431350 (defun magit-repository-local-exists-p (key &optional repository)
13441351 "Non-nil when a repository-local value exists for KEY.
13451352
1346 Returns a (KEY . value) cons cell.
1353 Return a (KEY . VALUE) cons cell.
13471354
13481355 The KEY is matched using `equal'.
13491356
13501357 Unless specified, REPOSITORY is the current buffer's repository."
1351 (let* ((repokey (or repository (magit-repository-local-repository)))
1352 (cache (assoc repokey magit-repository-local-cache)))
1353 (and cache
1354 (assoc key (cdr cache)))))
1358 (when-let ((cache (assoc (or repository
1359 (magit-repository-local-repository))
1360 magit-repository-local-cache)))
1361 (assoc key (cdr cache))))
13551362
13561363 (defun magit-repository-local-get (key &optional default repository)
13571364 "Return the repository-local value for KEY.
13611368 The KEY is matched using `equal'.
13621369
13631370 Unless specified, REPOSITORY is the current buffer's repository."
1364 (let ((keyvalue (magit-repository-local-exists-p key repository)))
1365 (if keyvalue
1366 (cdr keyvalue)
1367 default)))
1371 (if-let ((keyvalue (magit-repository-local-exists-p key repository)))
1372 (cdr keyvalue)
1373 default))
13681374
13691375 (defun magit-repository-local-delete (key &optional repository)
13701376 "Delete the repository-local value for KEY.
13711377
13721378 Unless specified, REPOSITORY is the current buffer's repository."
1373 (let* ((repokey (or repository (magit-repository-local-repository)))
1374 (cache (assoc repokey magit-repository-local-cache)))
1375 (when cache
1376 ;; There is no `assoc-delete-all'.
1377 (setf (cdr cache)
1378 (cl-delete key (cdr cache) :key #'car :test #'equal)))))
1379 (when-let ((cache (assoc (or repository
1380 (magit-repository-local-repository))
1381 magit-repository-local-cache)))
1382 ;; There is no `assoc-delete-all'.
1383 (setf (cdr cache)
1384 (cl-delete key (cdr cache) :key #'car :test #'equal))))
1385
1386 (defmacro magit--with-repository-local-cache (key &rest body)
1387 (declare (indent 1) (debug (form body)))
1388 (let ((k (cl-gensym)))
1389 `(let ((,k ,key))
1390 (if-let ((kv (magit-repository-local-exists-p ,k)))
1391 (cdr kv)
1392 (let ((v ,(macroexp-progn body)))
1393 (magit-repository-local-set ,k v)
1394 v)))))
13791395
13801396 (defun magit-preserve-section-visibility-cache ()
13811397 (when (derived-mode-p 'magit-status-mode 'magit-refs-mode)
00 ;;; magit-notes.el --- notes support -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2010-2020 The Magit Project Contributors
2 ;; Copyright (C) 2010-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
77 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9
10 ;; SPDX-License-Identifier: GPL-3.0-or-later
911
1012 ;; Magit is free software; you can redistribute it and/or modify it
1113 ;; under the terms of the GNU General Public License as published by
3133 ;;; Commands
3234
3335 ;;;###autoload (autoload 'magit-notes "magit" nil t)
34 (define-transient-command magit-notes ()
36 (transient-define-prefix magit-notes ()
3537 "Edit notes attached to commits."
3638 :man-page "git-notes"
3739 ["Configure local settings"
6567 (and (file-directory-p dir)
6668 (directory-files dir nil "^[^.]"))))
6769
68 (define-infix-command magit-core.notesRef ()
70 (transient-define-infix magit-core.notesRef ()
6971 :class 'magit--git-variable
7072 :variable "core.notesRef"
7173 :reader 'magit-notes-read-ref
7274 :prompt "Set local core.notesRef")
7375
74 (define-infix-command magit-notes.displayRef ()
76 (transient-define-infix magit-notes.displayRef ()
7577 :class 'magit--git-variable
7678 :variable "notes.displayRef"
7779 :multi-value t
7880 :reader 'magit-notes-read-refs
7981 :prompt "Set local notes.displayRef")
8082
81 (define-infix-command magit-global-core.notesRef ()
83 (transient-define-infix magit-global-core.notesRef ()
8284 :class 'magit--git-variable
8385 :variable "core.notesRef"
8486 :reader 'magit-notes-read-ref
8587 :prompt "Set global core.notesRef")
8688
87 (define-infix-command magit-global-notes.displayRef ()
89 (transient-define-infix magit-global-notes.displayRef ()
8890 :class 'magit--git-variable
8991 :variable "notes.displayRef"
9092 :multi-value t
9193 :reader 'magit-notes-read-refs
9294 :prompt "Set global notes.displayRef")
9395
94 (define-infix-argument magit-notes:--ref ()
95 :description "Merge strategy"
96 (transient-define-argument magit-notes:--ref ()
97 :description "Manipulate ref"
9698 :class 'transient-option
9799 :key "-r"
98100 :argument "--ref="
99101 :reader 'magit-notes-read-ref)
100102
101 (define-infix-argument magit-notes:--strategy ()
103 (transient-define-argument magit-notes:--strategy ()
102104 :description "Merge strategy"
103105 :class 'transient-option
104106 :shortarg "-s"
00 ;;; magit-obsolete.el --- obsolete definitions -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2010-2020 The Magit Project Contributors
2 ;; Copyright (C) 2010-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
77 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9
10 ;; SPDX-License-Identifier: GPL-3.0-or-later
911
1012 ;; Magit is free software; you can redistribute it and/or modify it
1113 ;; under the terms of the GNU General Public License as published by
5052
5153 (define-obsolete-variable-alias 'magit-disable-line-numbers
5254 'magit-section-disable-line-numbers "Magit 3.0.0")
55
56 (define-obsolete-variable-alias 'inhibit-magit-refresh
57 'magit-inhibit-refresh "Magit 3.0.0")
5358
5459 (defun magit--magit-popup-warning ()
5560 (display-warning 'magit "\
00 ;;; magit-patch.el --- creating and applying patches -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2008-2020 The Magit Project Contributors
2 ;; Copyright (C) 2008-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
77 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9
10 ;; SPDX-License-Identifier: GPL-3.0-or-later
911
1012 ;; Magit is free software; you can redistribute it and/or modify it
1113 ;; under the terms of the GNU General Public License as published by
2527 ;; This library implements patch commands.
2628
2729 ;;; Code:
28
29 (eval-when-compile
30 (require 'subr-x))
3130
3231 (require 'magit)
3332
5453 ;;; Commands
5554
5655 ;;;###autoload (autoload 'magit-patch "magit-patch" nil t)
57 (define-transient-command magit-patch ()
56 (transient-define-prefix magit-patch ()
5857 "Create or apply patches."
5958 ["Actions"
6059 ("c" "Create patches" magit-patch-create)
6362 ("r" "Request pull" magit-request-pull)])
6463
6564 ;;;###autoload (autoload 'magit-patch-create "magit-patch" nil t)
66 (define-transient-command magit-patch-create (range args files)
65 (transient-define-prefix magit-patch-create (range args files)
6766 "Create patches for the commits in RANGE.
6867 When a single commit is given for RANGE, create a patch for the
6968 changes introduced by that commit (unlike 'git format-patch'
9998 ["Actions"
10099 ("c" "Create patches" magit-patch-create)]
101100 (interactive
102 (if (not (eq current-transient-command 'magit-patch-create))
101 (if (not (eq transient-current-command 'magit-patch-create))
103102 (list nil nil nil)
104103 (cons (if-let ((revs (magit-region-values 'commit t)))
105104 (concat (car (last revs)) "^.." (car revs))
118117 (save-match-data
119118 (find-file
120119 (expand-file-name
121 (concat (--some (and (string-match "\\`--reroll-count=\\(.+\\)" it)
122 (format "v%s-" (match-string 1 it)))
123 args)
120 (concat (when-let ((v (transient-arg-value "--reroll-count=" args)))
121 (format "v%s-" v))
124122 "0000-cover-letter.patch")
125123 (let ((topdir (magit-toplevel)))
126 (or (--some (and (string-match "\\`--output-directory=\\(.+\\)" it)
127 (expand-file-name (match-string 1 it) topdir))
128 args)
129 topdir))))))))
130
131 (define-infix-argument magit-format-patch:--in-reply-to ()
124 (if-let ((dir (transient-arg-value "--output-directory=" args)))
125 (expand-file-name dir topdir)
126 topdir))))))))
127
128 (transient-define-argument magit-format-patch:--in-reply-to ()
132129 :description "In reply to"
133130 :class 'transient-option
134131 :key "C-m C-r"
135132 :argument "--in-reply-to=")
136133
137 (define-infix-argument magit-format-patch:--thread ()
134 (transient-define-argument magit-format-patch:--thread ()
138135 :description "Thread style"
139136 :class 'transient-option
140137 :key "C-m s "
146143 (?d "[d]eep" "deep")
147144 (?s "[s]hallow" "shallow")))
148145
149 (define-infix-argument magit-format-patch:--base ()
146 (transient-define-argument magit-format-patch:--base ()
150147 :description "Insert base commit"
151148 :class 'transient-option
152149 :key "C-m b "
158155 nil nil initial-input history "auto")
159156 (user-error "Nothing selected")))
160157
161 (define-infix-argument magit-format-patch:--reroll-count ()
158 (transient-define-argument magit-format-patch:--reroll-count ()
162159 :description "Reroll count"
163160 :class 'transient-option
164161 :key "C-m v "
166163 :argument "--reroll-count="
167164 :reader 'transient-read-number-N+)
168165
169 (define-infix-argument magit-format-patch:--interdiff ()
166 (transient-define-argument magit-format-patch:--interdiff ()
170167 :description "Insert interdiff"
171168 :class 'transient-option
172169 :key "C-m d i"
173170 :argument "--interdiff="
174171 :reader #'magit-transient-read-revision)
175172
176 (define-infix-argument magit-format-patch:--range-diff ()
173 (transient-define-argument magit-format-patch:--range-diff ()
177174 :description "Insert range-diff"
178175 :class 'transient-option
179176 :key "C-m d r"
183180 (defun magit-format-patch-select-range-diff (prompt _initial-input _history)
184181 (magit-read-range-or-commit prompt))
185182
186 (define-infix-argument magit-format-patch:--subject-prefix ()
183 (transient-define-argument magit-format-patch:--subject-prefix ()
187184 :description "Subject Prefix"
188185 :class 'transient-option
189186 :key "C-m p "
190187 :argument "--subject-prefix=")
191188
192 (define-infix-argument magit-format-patch:--cover-from-description ()
189 (transient-define-argument magit-format-patch:--cover-from-description ()
193190 :description "Use branch description"
194191 :class 'transient-option
195192 :key "C-m D "
203200 (?a "[a]uto" "auto")
204201 (?n "[n]othing" "none")))
205202
206 (define-infix-argument magit-format-patch:--notes ()
203 (transient-define-argument magit-format-patch:--notes ()
207204 :description "Insert commentary from notes"
208205 :class 'transient-option
209206 :key "C-m n "
210207 :argument "--notes="
211208 :reader #'magit-notes-read-ref)
212209
213 (define-infix-argument magit-format-patch:--from ()
210 (transient-define-argument magit-format-patch:--from ()
214211 :description "From"
215212 :class 'transient-option
216213 :key "C-m C-f"
217214 :argument "--from="
218215 :reader 'magit-transient-read-person)
219216
220 (define-infix-argument magit-format-patch:--to ()
217 (transient-define-argument magit-format-patch:--to ()
221218 :description "To"
222219 :class 'transient-option
223220 :key "C-m C-t"
224221 :argument "--to="
225222 :reader 'magit-transient-read-person)
226223
227 (define-infix-argument magit-format-patch:--cc ()
224 (transient-define-argument magit-format-patch:--cc ()
228225 :description "CC"
229226 :class 'transient-option
230227 :key "C-m C-c"
231228 :argument "--cc="
232229 :reader 'magit-transient-read-person)
233230
234 (define-infix-argument magit-format-patch:--output-directory ()
231 (transient-define-argument magit-format-patch:--output-directory ()
235232 :description "Output directory"
236233 :class 'transient-option
237234 :key "C-m o "
240237 :reader 'transient-read-existing-directory)
241238
242239 ;;;###autoload (autoload 'magit-patch-apply "magit-patch" nil t)
243 (define-transient-command magit-patch-apply (file &rest args)
240 (transient-define-prefix magit-patch-apply (file &rest args)
244241 "Apply the patch file FILE."
245242 :man-page "git-apply"
246243 ["Arguments"
250247 ["Actions"
251248 ("a" "Apply patch" magit-patch-apply)]
252249 (interactive
253 (if (not (eq current-transient-command 'magit-patch-apply))
250 (if (not (eq transient-current-command 'magit-patch-apply))
254251 (list nil)
255252 (list (expand-file-name
256253 (read-file-name "Apply patch: "
307304
308305 ;;;###autoload
309306 (defun magit-request-pull (url start end)
310 "Request upstream to pull from you public repository.
307 "Request upstream to pull from your public repository.
311308
312309 URL is the url of your publicly accessible repository.
313310 START is a commit that already is in the upstream repository.
0 (define-package "magit" "2.90.1"
0 (define-package "magit" "3.0.0"
11 "A Git porcelain inside Emacs."
22 '((emacs "25.1")
3 (async "20180527")
4 (dash "20180910")
5 (git-commit "20181104")
6 (transient "20190812")
7 (with-editor "20181103"))
8 :keywords
9 '("git" "tools" "vc"))
3 (dash "2.18.1")
4 (git-commit "3.0.0")
5 (magit-section "3.0.0")
6 (transient "0.3.3")
7 (with-editor "3.0.4"))
8 :homepage "https://magit.vc"
9 :keywords '("git" "tools" "vc"))
00 ;;; magit-process.el --- process functionality -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2010-2020 The Magit Project Contributors
2 ;; Copyright (C) 2010-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
77 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9
10 ;; SPDX-License-Identifier: GPL-3.0-or-later
911
1012 ;; Magit is free software; you can redistribute it and/or modify it
1113 ;; under the terms of the GNU General Public License as published by
3032
3133 ;;; Code:
3234
33 (require 'ansi-color)
34 (require 'cl-lib)
35 (require 'dash)
36
37 (eval-when-compile
38 (require 'subr-x))
39
40 (require 'with-editor)
4135 (require 'magit-utils)
4236 (require 'magit-section)
4337 (require 'magit-git)
4438 (require 'magit-mode)
39
40 (require 'ansi-color)
41 (require 'with-editor)
4542
4643 (declare-function auth-source-search "auth-source"
4744 (&rest spec &key max require create delete &allow-other-keys))
9794 :package-version '(magit . "2.1.0")
9895 :group 'magit-process
9996 :type '(choice (const :tag "Never remove old sections" nil) integer))
97
98 (defvar magit-process-extreme-logging nil
99 "Whether `magit-process-file' logs to *Messages* buffer.
100 Only intended for temporary use when you try to figure out how
101 Magit uses Git behind the scene. Output that normally goes to
102 the magit-process buffer continues to go there. Not all output
103 goes to either of these two buffers.")
100104
101105 (defcustom magit-process-error-tooltip-max-lines 20
102106 "The number of lines for `magit-process-error-lines' to return.
155159 "\\([Nn]o?\\)"
156160 ;; OpenSSH v8 prints this. See #3969.
157161 "\\(?:/\\[fingerprint\\]\\)?"
158 "[\])] ?[?:] ?$")
162 "[\])] ?[?:]? ?$")
159163 "Regexp matching Yes-or-No prompts of Git and its subprocesses."
160164 :package-version '(magit . "2.1.0")
161165 :group 'magit-process
168172 "Please enter the passphrase for the ssh key"
169173 "Please enter the passphrase to unlock the OpenPGP secret key"
170174 "^.*'s password: ?$"
175 "^Token: $" ; For git-credential-manager-core (#4318).
171176 "^Yubikey for .*: ?$"
172177 "^Enter PIN for .*: ?$")
173178 "List of regexps matching password prompts of Git and its subprocesses.
174179 Also see `magit-process-find-password-functions'."
175 :package-version '(magit . "2.8.0")
180 :package-version '(magit . "3.0.0")
176181 :group 'magit-process
177182 :type '(repeat (regexp)))
178183
397402 Identical to `process-file' but temporarily enable Cygwin's
398403 \"noglob\" option during the call and ensure unix eol
399404 conversion."
405 (when magit-process-extreme-logging
406 (let ((inhibit-message t))
407 (message "$ %s" (magit-process--format-arguments process args))))
400408 (let ((process-environment (magit-process-environment))
401409 (default-process-coding-system (magit--process-coding-system)))
402410 (apply #'process-file process infile buffer display args)))
425433 "Call Git in a separate process.
426434 ARGS is flattened and then used as arguments to Git.
427435
428 The current buffer's content is used as the process' standard
429 input.
436 The current buffer's content is used as the process's standard
437 input. The buffer is assumed to be temporary and thus OK to
438 modify.
430439
431440 Option `magit-git-executable' specifies the Git executable and
432441 option `magit-git-global-arguments' specifies constant arguments.
569578 (when (eq system-type 'windows-nt)
570579 ;; On w32, git expects UTF-8 encoded input, ignore any user
571580 ;; configuration telling us otherwise.
572 (set-process-coding-system process 'utf-8-unix))
581 (set-process-coding-system process nil 'utf-8-unix))
573582 (process-put process 'section section)
574583 (process-put process 'command-buf (current-buffer))
575584 (process-put process 'default-dir default-directory)
576 (when inhibit-magit-refresh
585 (when magit-inhibit-refresh
577586 (process-put process 'inhibit-refresh t))
578587 (oset section process process)
579588 (with-current-buffer process-buf
629638 (unless (equal (expand-file-name pwd)
630639 (expand-file-name default-directory))
631640 (insert (file-relative-name pwd default-directory) ?\s))
632 (cond
633 ((and args (equal program magit-git-executable))
634 (setq args (-split-at (length magit-git-global-arguments) args))
635 (insert (propertize (file-name-nondirectory program)
636 'font-lock-face 'magit-section-heading) " ")
637 (insert (propertize (char-to-string magit-ellipsis)
638 'font-lock-face 'magit-section-heading
639 'help-echo (mapconcat #'identity (car args) " ")))
640 (insert " ")
641 (insert (propertize (mapconcat #'shell-quote-argument (cadr args) " ")
642 'font-lock-face 'magit-section-heading)))
643 ((and args (equal program shell-file-name))
644 (insert (propertize (cadr args)
645 'font-lock-face 'magit-section-heading)))
646 (t
647 (insert (propertize (file-name-nondirectory program)
648 'font-lock-face 'magit-section-heading) " ")
649 (insert (propertize (mapconcat #'shell-quote-argument args " ")
650 'font-lock-face 'magit-section-heading))))
641 (insert (magit-process--format-arguments program args))
651642 (magit-insert-heading)
652643 (when errlog
653644 (if (bufferp errlog)
656647 (insert-file-contents errlog)
657648 (goto-char (1- (point-max)))))
658649 (insert "\n"))))
650
651 (defun magit-process--format-arguments (program args)
652 (cond
653 ((and args (equal program magit-git-executable))
654 (setq args (-split-at (length magit-git-global-arguments) args))
655 (concat (propertize (file-name-nondirectory program)
656 'font-lock-face 'magit-section-heading)
657 " "
658 (propertize (if (stringp magit-ellipsis)
659 magit-ellipsis
660 ;; For backward compatibility.
661 (char-to-string magit-ellipsis))
662 'font-lock-face 'magit-section-heading
663 'help-echo (mapconcat #'identity (car args) " "))
664 " "
665 (propertize (mapconcat #'shell-quote-argument (cadr args) " ")
666 'font-lock-face 'magit-section-heading)))
667 ((and args (equal program shell-file-name))
668 (propertize (cadr args)
669 'font-lock-face 'magit-section-heading))
670 (t
671 (concat (propertize (file-name-nondirectory program)
672 'font-lock-face 'magit-section-heading)
673 " "
674 (propertize (mapconcat #'shell-quote-argument args " ")
675 'font-lock-face 'magit-section-heading)))))
659676
660677 (defun magit-process-truncate-log ()
661678 (let* ((head nil)
774791 'magit-process-password-auth-source)
775792
776793 KEY typically derives from a prompt such as:
777 Password for 'https://tarsius@bitbucket.org'
794 Password for 'https://yourname@github.com'
778795 in which case it would be the string
779 tarsius@bitbucket.org
796 yourname@github.com
780797 which matches the ~/.authinfo.gpg entry
781 machine bitbucket.org login tarsius password 12345
798 machine github.com login yourname password 12345
782799 or iff that is undefined, for backward compatibility
783 machine tarsius@bitbucket.org password 12345"
800 machine yourname@github.com password 12345
801
802 On github.com you should not use your password but a
803 personal access token, see [1]. For information about
804 the peculiarities of other forges, please consult the
805 respective documentation.
806
807 After manually editing ~/.authinfo.gpg you must reset
808 the cache using
809 M-x auth-source-forget-all-cached RET
810
811 The above will save you from having to repeatedly type
812 your token or password, but you might still repeatedly
813 be asked for your username. To prevent that, change an
814 URL like
815 https://github.com/foo/bar.git
816 to
817 https://yourname@github.com/foo/bar.git
818
819 Instead of changing all such URLs manually, they can
820 be translated on the fly by doing this once
821 git config --global \
822 url.https://yourname@github.com.insteadOf \
823 https://github.com
824
825 [1]: https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token."
784826 (require 'auth-source)
785827 (and (string-match "\\`\\(.+\\)@\\([^@]+\\)\\'" key)
786828 (let* ((user (match-string 1 key))
793835 (if (functionp secret)
794836 (funcall secret)
795837 secret))))
838
839 (defun magit-process-git-credential-manager-core (process string)
840 "Authenticate using `git-credential-manager-core'.
841
842 To use this function add it to the appropriate hook
843 (add-hook 'magit-process-prompt-functions
844 'magit-process-git-credential-manager-core)"
845 (and (string-match "^option (enter for default): $" string)
846 (progn
847 (magit-process-buffer)
848 (process-send-string
849 process
850 (format "%c" (read-char-choice "Option: " '(?\r ?\j ?1 ?2)))))))
796851
797852 (defun magit-process-password-prompt (process string)
798853 "Find a password based on prompt STRING and send it to git.
9551010 ;; The following closure captures the repokey value, and is
9561011 ;; added to `pre-command-hook'.
9571012 (cl-labels ((enable-magit-process-unset-mode-line
958 () ;; Remove ourself from the hook variable, so
959 ;; that we only run once.
1013 () ;;; Remove ourself from the hook variable, so
1014 ;;; that we only run once.
9601015 (remove-hook 'pre-command-hook
9611016 #'enable-magit-process-unset-mode-line)
9621017 ;; Clear the inhibit flag for the repository in
00 ;;; magit-pull.el --- update local objects and refs -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2008-2020 The Magit Project Contributors
2 ;; Copyright (C) 2008-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
77 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9
10 ;; SPDX-License-Identifier: GPL-3.0-or-later
911
1012 ;; Magit is free software; you can redistribute it and/or modify it
1113 ;; under the terms of the GNU General Public License as published by
3941 ;;; Commands
4042
4143 ;;;###autoload (autoload 'magit-pull "magit-pull" nil t)
42 (define-transient-command magit-pull ()
44 (transient-define-prefix magit-pull ()
4345 "Pull from another repository."
4446 :man-page "git-pull"
4547 [:description
7678 (transient-args 'magit-pull))
7779
7880 ;;;###autoload (autoload 'magit-pull-from-pushremote "magit-pull" nil t)
79 (define-suffix-command magit-pull-from-pushremote (args)
81 (transient-define-suffix magit-pull-from-pushremote (args)
8082 "Pull from the push-remote of the current branch.
8183
8284 With a prefix argument or when the push-remote is either not
106108 (format "%s, setting that" v)))))
107109
108110 ;;;###autoload (autoload 'magit-pull-from-upstream "magit-pull" nil t)
109 (define-suffix-command magit-pull-from-upstream (args)
111 (transient-define-suffix magit-pull-from-upstream (args)
110112 "Pull from the upstream of the current branch.
111113
112114 With a prefix argument or when the upstream is either not
00 ;;; magit-push.el --- update remote objects and refs -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2008-2020 The Magit Project Contributors
2 ;; Copyright (C) 2008-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
77 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9
10 ;; SPDX-License-Identifier: GPL-3.0-or-later
911
1012 ;; Magit is free software; you can redistribute it and/or modify it
1113 ;; under the terms of the GNU General Public License as published by
2628
2729 ;;; Code:
2830
29 (eval-when-compile
30 (require 'subr-x))
31
3231 (require 'magit)
3332
3433 ;;; Commands
3534
3635 ;;;###autoload (autoload 'magit-push "magit-push" nil t)
37 (define-transient-command magit-push ()
36 (transient-define-prefix magit-push ()
3837 "Push to another repository."
3938 :man-page "git-push"
4039 ["Arguments"
7776 (format "%s:%s%s" branch namespace target))))
7877
7978 ;;;###autoload (autoload 'magit-push-current-to-pushremote "magit-push" nil t)
80 (define-suffix-command magit-push-current-to-pushremote (args)
79 (transient-define-suffix magit-push-current-to-pushremote (args)
8180 "Push the current branch to its push-remote.
8281
8382 When the push-remote is not configured, then read the push-remote
8685 :if 'magit-get-current-branch
8786 :description 'magit-push--pushbranch-description
8887 (interactive (list (magit-push-arguments)))
89 (pcase-let ((`(,branch ,remote)
88 (pcase-let ((`(,branch ,remote ,changed)
9089 (magit--select-push-remote "push there")))
90 (when changed
91 (magit-confirm 'set-and-push
92 (format "Really use \"%s\" as push-remote and push \"%s\" there"
93 remote branch)))
9194 (run-hooks 'magit-credential-hook)
9295 (magit-run-git-async "push" "-v" args remote
9396 (format "refs/heads/%s:refs/heads/%s"
110113 (format "%s, setting that" v)))))
111114
112115 ;;;###autoload (autoload 'magit-push-current-to-upstream "magit-push" nil t)
113 (define-suffix-command magit-push-current-to-upstream (args)
116 (transient-define-suffix magit-push-current-to-upstream (args)
114117 "Push the current branch to its upstream branch.
115118
116119 With a prefix argument or when the upstream is either not
135138 branches nil nil nil 'magit-revision-history
136139 (or (car (member (magit-remote-branch-at-point) branches))
137140 (car (member "origin/master" branches)))))
138 (upstream (or (magit-get-tracked upstream)
139 (magit-split-branch-name upstream))))
140 (setq remote (car upstream))
141 (setq merge (cdr upstream))
141 (upstream* (or (magit-get-tracked upstream)
142 (magit-split-branch-name upstream))))
143 (setq remote (car upstream*))
144 (setq merge (cdr upstream*))
142145 (unless (string-prefix-p "refs/" merge)
143146 ;; User selected a non-existent remote-tracking branch.
144147 ;; It is very likely, but not certain, that this is the
145148 ;; correct thing to do. It is even more likely that it
146149 ;; is what the user wants to happen.
147 (setq merge (concat "refs/heads/" merge))))
150 (setq merge (concat "refs/heads/" merge)))
151 (magit-confirm 'set-and-push
152 (format "Really use \"%s\" as upstream and push \"%s\" there"
153 upstream branch)))
148154 (cl-pushnew "--set-upstream" args :test #'equal))
149155 (run-hooks 'magit-credential-hook)
150156 (magit-run-git-async "push" "-v" args remote (concat branch ":" merge))))
261267 (run-hooks 'magit-credential-hook)
262268 (magit-run-git-async "push" remote ref args))
263269
264 ;;;###autoload
265 (defun magit-push-implicitly (args)
270 ;;;###autoload (autoload 'magit-push-implicitly "magit-push" nil t)
271 (transient-define-suffix magit-push-implicitly (args)
266272 "Push somewhere without using an explicit refspec.
267273
268274 This command simply runs \"git push -v [ARGS]\". ARGS are the
272278 `branch.<branch>.pushRemote', `branch.<branch>.remote',
273279 `branch.<branch>.merge', and `remote.<remote>.push'.
274280
275 The function `magit-push-implicitly--desc' attempts to predict
276 what this command will do. The value it returns is displayed in
277 the popup buffer."
281 If you add this suffix to a transient prefix without explicitly
282 specifying the description, then an attempt is made to predict
283 what this command will do. For example:
284
285 (transient-insert-suffix 'magit-push \"p\"
286 '(\"i\" magit-push-implicitly))"
287 :description 'magit-push-implicitly--desc
278288 (interactive (list (magit-push-arguments)))
279289 (run-hooks 'magit-credential-hook)
280290 (magit-run-git-async "push" "-v" args))
283293 (let ((default (magit-get "push.default")))
284294 (unless (equal default "nothing")
285295 (or (when-let ((remote (or (magit-get-remote)
286 (magit-remote-p "origin")))
296 (magit-primary-remote)))
287297 (refspec (magit-get "remote" remote "push")))
288298 (format "%s using %s"
289299 (magit--propertize-face remote 'magit-branch-remote)
00 ;;; magit-reflog.el --- inspect ref history -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2010-2020 The Magit Project Contributors
2 ;; Copyright (C) 2010-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
77 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9
10 ;; SPDX-License-Identifier: GPL-3.0-or-later
911
1012 ;; Magit is free software; you can redistribute it and/or modify it
1113 ;; under the terms of the GNU General Public License as published by
2830
2931 (require 'magit-core)
3032 (require 'magit-log)
31
32 (eval-when-compile
33 (require 'subr-x))
3433
3534 ;;; Options
3635
00 ;;; magit-refs.el --- listing references -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2010-2020 The Magit Project Contributors
2 ;; Copyright (C) 2010-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
77 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9
10 ;; SPDX-License-Identifier: GPL-3.0-or-later
911
1012 ;; Magit is free software; you can redistribute it and/or modify it
1113 ;; under the terms of the GNU General Public License as published by
2527 ;; This library implements support for listing references in a buffer.
2628
2729 ;;; Code:
28
29 (eval-when-compile
30 (require 'subr-x))
3130
3231 (require 'magit)
3332
326325 ;;; Commands
327326
328327 ;;;###autoload (autoload 'magit-show-refs "magit-refs" nil t)
329 (define-transient-command magit-show-refs (&optional transient)
328 (transient-define-prefix magit-show-refs (&optional transient)
330329 "List and compare references in a dedicated buffer."
331330 :man-page "git-branch"
332331 :value (lambda ()
333332 (magit-show-refs-arguments magit-prefix-use-buffer-arguments))
334333 ["Arguments"
335334 (magit-for-each-ref:--contains)
336 ("=m" "Merged" "--merged=" magit-transient-read-revision)
335 ("-M" "Merged" "--merged=" magit-transient-read-revision)
337336 ("-m" "Merged to HEAD" "--merged")
338 ("-M" "Merged to master" "--merged=master")
339 ("=n" "Not merged" "--no-merged=" magit-transient-read-revision)
337 ("-N" "Not merged" "--no-merged=" magit-transient-read-revision)
340338 ("-n" "Not merged to HEAD" "--no-merged")
341 ("-N" "Not merged to master" "--no-merged=master")
342339 (magit-for-each-ref:--sort)]
343340 ["Actions"
344341 ("y" "Show refs, comparing them with HEAD" magit-show-refs-head)
355352 (setq use-buffer-args magit-direct-use-buffer-arguments))
356353 (let (args)
357354 (cond
358 ((eq current-transient-command 'magit-show-refs)
355 ((eq transient-current-command 'magit-show-refs)
359356 (setq args (transient-args 'magit-show-refs)))
360357 ((eq major-mode 'magit-refs-mode)
361358 (setq args magit-buffer-arguments))
369366 (setq args (alist-get 'magit-show-refs transient-values))))
370367 args))
371368
372 (define-infix-argument magit-for-each-ref:--contains ()
369 (transient-define-argument magit-for-each-ref:--contains ()
373370 :description "Contains"
374371 :class 'transient-option
375372 :key "-c"
376373 :argument "--contains="
377374 :reader 'magit-transient-read-revision)
378375
379 (define-infix-argument magit-for-each-ref:--sort ()
376 (transient-define-argument magit-for-each-ref:--sort ()
380377 :description "Sort"
381378 :class 'transient-option
382379 :key "-s"
00 ;;; magit-remote.el --- transfer Git commits -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2008-2020 The Magit Project Contributors
2 ;; Copyright (C) 2008-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
77 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9
10 ;; SPDX-License-Identifier: GPL-3.0-or-later
911
1012 ;; Magit is free software; you can redistribute it and/or modify it
1113 ;; under the terms of the GNU General Public License as published by
6365 ;;; Commands
6466
6567 ;;;###autoload (autoload 'magit-remote "magit-remote" nil t)
66 (define-transient-command magit-remote (remote)
68 (transient-define-prefix magit-remote (remote)
6769 "Add, configure or remove a remote."
6870 :man-page "git-remote"
6971 :value '("-f")
9799 ;;;###autoload
98100 (defun magit-remote-add (remote url &optional args)
99101 "Add a remote named REMOTE and fetch it."
100 (interactive (list (magit-read-string-ns "Remote name")
101 (magit-read-url "Remote url")
102 (transient-args 'magit-remote)))
102 (interactive
103 (let ((origin (magit-get "remote.origin.url"))
104 (remote (magit-read-string-ns "Remote name")))
105 (list remote
106 (magit-read-url
107 "Remote url"
108 (and origin
109 (string-match "\\([^:/]+\\)/[^/]+\\(\\.git\\)?\\'" origin)
110 (replace-match remote t t origin 1)))
111 (transient-args 'magit-remote))))
103112 (if (pcase (list magit-remote-add-set-remote.pushDefault
104113 (magit-get "remote.pushDefault"))
105114 (`(,(pred stringp) ,_) t)
250259 ;;; Configure
251260
252261 ;;;###autoload (autoload 'magit-remote-configure "magit-remote" nil t)
253 (define-transient-command magit-remote-configure (remote)
262 (transient-define-prefix magit-remote-configure (remote)
254263 "Configure a remote."
255264 :man-page "git-remote"
256265 [:description
266275 (interactive
267276 (list (or (and (not current-prefix-arg)
268277 (not (and magit-remote-direct-configure
269 (eq current-transient-command 'magit-remote)))
278 (eq transient-current-command 'magit-remote)))
270279 (magit-get-current-remote))
271280 (magit--read-remote-scope))))
272281 (transient-setup 'magit-remote-configure nil nil :scope remote))
278287 (format (oref obj variable) "<name>"))
279288 "Configure remote")))
280289
281 (define-infix-command magit-remote.<remote>.url ()
290 (transient-define-infix magit-remote.<remote>.url ()
282291 :class 'magit--git-variable:urls
283292 :scope 'magit--read-remote-scope
284293 :variable "remote.%s.url"
285294 :multi-value t
286295 :history-key 'magit-remote.<remote>.*url)
287296
288 (define-infix-command magit-remote.<remote>.fetch ()
297 (transient-define-infix magit-remote.<remote>.fetch ()
289298 :class 'magit--git-variable
290299 :scope 'magit--read-remote-scope
291300 :variable "remote.%s.fetch"
292301 :multi-value t)
293302
294 (define-infix-command magit-remote.<remote>.pushurl ()
303 (transient-define-infix magit-remote.<remote>.pushurl ()
295304 :class 'magit--git-variable:urls
296305 :scope 'magit--read-remote-scope
297306 :variable "remote.%s.pushurl"
299308 :history-key 'magit-remote.<remote>.*url
300309 :seturl-arg "--push")
301310
302 (define-infix-command magit-remote.<remote>.push ()
311 (transient-define-infix magit-remote.<remote>.push ()
303312 :class 'magit--git-variable
304313 :scope 'magit--read-remote-scope
305314 :variable "remote.%s.push")
306315
307 (define-infix-command magit-remote.<remote>.tagopt ()
316 (transient-define-infix magit-remote.<remote>.tagopt ()
308317 :class 'magit--git-variable:choices
309318 :scope 'magit--read-remote-scope
310319 :variable "remote.%s.tagOpt"
324333 (defun magit--select-push-remote (prompt-suffix)
325334 (let* ((branch (or (magit-get-current-branch)
326335 (user-error "No branch is checked out")))
327 (remote (magit-get-push-remote branch)))
336 (remote (magit-get-push-remote branch))
337 (changed nil))
328338 (when (or current-prefix-arg
329339 (not remote)
330340 (not (member remote (magit-list-remotes))))
341 (setq changed t)
331342 (setq remote
332343 (magit-read-remote (format "Set %s and %s"
333344 (magit--push-remote-variable)
334345 prompt-suffix)))
335346 (setf (magit-get (magit--push-remote-variable branch)) remote))
336 (list branch remote)))
347 (list branch remote changed)))
337348
338349 ;;; _
339350 (provide 'magit-remote)
00 ;;; magit-repos.el --- listing repositories -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2010-2020 The Magit Project Contributors
2 ;; Copyright (C) 2010-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
77 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9
10 ;; SPDX-License-Identifier: GPL-3.0-or-later
911
1012 ;; Magit is free software; you can redistribute it and/or modify it
1113 ;; under the terms of the GNU General Public License as published by
2729 ;; mode for listing repositories in a buffer.
2830
2931 ;;; Code:
30
31 (eval-when-compile
32 (require 'subr-x))
3332
3433 (require 'magit-core)
3534
156155 "Major mode for browsing a list of Git repositories."
157156 (setq-local x-stretch-cursor nil)
158157 (setq tabulated-list-padding 0)
159 (setq tabulated-list-sort-key (cons "Path" nil))
158 (setq tabulated-list-sort-key
159 (cons (or (car (assoc "Path" magit-repolist-columns))
160 (caar magit-repolist-columns))
161 nil))
160162 (setq tabulated-list-format
161163 (vconcat (mapcar (pcase-lambda (`(,title ,width ,_fn ,props))
162164 (nconc (list title width t)
221223 - U if there is at least one unstaged file.
222224 - S if there is at least one staged file.
223225 Only one letter is shown, the first that applies."
224 (-some (pcase-lambda (`(,fun . ,flag))
225 (and (funcall fun) flag))
226 magit-repolist-column-flag-alist))
226 (seq-some (pcase-lambda (`(,fun . ,flag))
227 (and (funcall fun) flag))
228 magit-repolist-column-flag-alist))
227229
228230 (defun magit-repolist-column-unpulled-from-upstream (_id)
229231 "Insert number of upstream commits not in the current branch."
00 ;;; magit-reset.el --- reset fuctionality -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2010-2020 The Magit Project Contributors
2 ;; Copyright (C) 2010-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
77 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9
10 ;; SPDX-License-Identifier: GPL-3.0-or-later
911
1012 ;; Magit is free software; you can redistribute it and/or modify it
1113 ;; under the terms of the GNU General Public License as published by
2931 (require 'magit)
3032
3133 ;;;###autoload (autoload 'magit-reset "magit" nil t)
32 (define-transient-command magit-reset ()
34 (transient-define-prefix magit-reset ()
3335 "Reset the `HEAD', index and/or worktree to a previous state."
3436 :man-page "git-reset"
3537 ["Reset"
3638 ("m" "mixed (HEAD and index)" magit-reset-mixed)
3739 ("s" "soft (HEAD only)" magit-reset-soft)
3840 ("h" "hard (HEAD, index and files)" magit-reset-hard)
41 ("k" "keep (HEAD and index, keeping uncommitted)" magit-reset-keep)
3942 ("i" "index (only)" magit-reset-index)
4043 ("w" "worktree (only)" magit-reset-worktree)
4144 ""
6366 (concat (magit--propertize-face "Hard" 'bold)
6467 " reset %s to"))))
6568 (magit-reset-internal "--hard" commit))
69
70 ;;;###autoload
71 (defun magit-reset-keep (commit)
72 "Reset the `HEAD' and index to COMMIT, while keeping uncommitted changes.
73 \n(git reset --keep REVISION)"
74 (interactive (list (magit-reset-read-branch-or-commit "Reset %s to")))
75 (magit-reset-internal "--keep" commit))
6676
6777 ;;;###autoload
6878 (defun magit-reset-index (commit)
00 ;;; magit-section.el --- Sections for read-only buffers -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2010-2020 The Magit Project Contributors
2 ;; Copyright (C) 2010-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
77 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
99
10 ;; Package-Requires: ((emacs "25.1") (dash "20180910"))
1110 ;; Keywords: tools
1211 ;; Homepage: https://github.com/magit/magit
12 ;; Package-Requires: ((emacs "25.1") (dash "2.18.1"))
13 ;; Package-Version: 3.0.0
14 ;; SPDX-License-Identifier: GPL-3.0-or-later
1315
1416 ;; Magit-Section is free software; you can redistribute it and/or modify
1517 ;; it under the terms of the GNU General Public License as published by
3638 (require 'cl-lib)
3739 (require 'dash)
3840 (require 'eieio)
39
40 (eval-when-compile
41 (require 'benchmark)
42 (require 'subr-x))
41 (require 'seq)
42 (require 'subr-x)
43
44 (eval-when-compile (require 'benchmark))
4345
4446 ;;; Hooks
4547
136138 (defcustom magit-section-visibility-indicator
137139 (if (window-system)
138140 '(magit-fringe-bitmap> . magit-fringe-bitmapv)
139 '("…" . t))
141 (cons (if (char-displayable-p ?…) "…" "...")
142 t))
140143 "Whether and how to indicate that a section can be expanded/collapsed.
141144
142145 If nil, then don't show any indicators.
683686 (cond ((and (--any-p (oref it hidden) children)
684687 (--any-p (oref it children) children))
685688 (magit-section-show-headings section))
686 ((-any-p 'magit-section-hidden-body children)
689 ((seq-some 'magit-section-hidden-body children)
687690 (magit-section-show-children section))
688691 (t
689692 (magit-section-hide section))))))
695698 (cond ((and (--any-p (oref it hidden) children)
696699 (--any-p (oref it children) children))
697700 (magit-section-show-headings magit-root-section))
698 ((-any-p 'magit-section-hidden-body children)
701 ((seq-some 'magit-section-hidden-body children)
699702 (magit-section-show-children magit-root-section))
700703 (t
701704 (mapc 'magit-section-hide children)))))
780783 With a prefix argument show the section identity instead of the
781784 section lineage. This command is intended for debugging purposes."
782785 (interactive (list (magit-current-section) current-prefix-arg))
783 (let ((str (format "#<%s %S %S %s-%s>"
786 (let ((str (format "#<%s %S %S %s-%s%s>"
784787 (eieio-object-class section)
785788 (let ((val (oref section value)))
786789 (cond ((stringp val)
795798 (apply #'vector (magit-section-lineage section)))
796799 (when-let ((m (oref section start)))
797800 (marker-position m))
801 (if-let ((m (oref section content)))
802 (format "[%s-]" (marker-position m))
803 "")
798804 (when-let ((m (oref section end)))
799805 (marker-position m)))))
800806 (if (called-interactively-p 'any)
970976
971977 (defun magit-section-match-assoc (section alist)
972978 "Return the value associated with SECTION's type or lineage in ALIST."
973 (-some (pcase-lambda (`(,key . ,val))
974 (and (magit-section-match-1 key section) val))
975 alist))
979 (seq-some (pcase-lambda (`(,key . ,val))
980 (and (magit-section-match-1 key section) val))
981 alist))
976982
977983 ;;; Create
978984
984990 (defmacro magit-insert-section (&rest args)
985991 "Insert a section at point.
986992
987 TYPE is the section type, a symbol which is prefixed with the
988 name of the package. (For historic reasons the types used by
989 Magit and Forge do not use a package prefix.) Many commands
990 that act on the current section behave differently depending
991 on its type.
992
993 Optional VALUE is the value of the section, usually a string
994 that is required when acting on the section.
993 Create a section object of type CLASS, storing VALUE in its
994 `value' slot, and insert the section at point. CLASS is a
995 subclass of `magit-section' or has the form `(eval FORM)', in
996 which case FORM is evaluated at runtime and should return a
997 subclass. In other places a sections class is oftern referred
998 to as its \"type\".
999
1000 Many commands behave differently depending on the class of the
1001 current section and sections of a certain class can have their
1002 own keymap, which is specified using the `keymap' class slot.
1003 The value of that slot should be a variable whose value is a
1004 keymap.
1005
1006 For historic reasons Magit and Forge in most cases use symbols
1007 as CLASS that don't actually identify a class and that lack the
1008 appropriate package prefix. This works due to some undocumented
1009 kludges, which are not available to other packages.
9951010
9961011 When optional HIDE is non-nil collapse the section body by
9971012 default, i.e. when first creating the section, but not when
10171032 a section by washing Git's output and Git didn't actually output
10181033 anything this time around.
10191034
1020 For historic reasons, if a variable `magit-TYPE-section-map'
1021 or `forge-TYPE-section-map' exists, then use that as the
1022 text-property `keymap' of all text belonging to the section (but
1023 this may be overwritten in subsections). TYPE can also have the
1024 form `(eval FORM)' in which case FORM is evaluated at runtime.
1025
1026 \(fn [NAME] (TYPE &optional VALUE HIDE) &rest BODY)"
1035 \(fn [NAME] (CLASS &optional VALUE HIDE) &rest BODY)"
10271036 (declare (indent defun)
10281037 (debug ([&optional symbolp]
1029 (&or [("eval" symbolp) &optional form form]
1038 (&or [("eval" form) &optional form form]
10301039 [symbolp &optional form form])
10311040 body)))
10321041 (let ((tp (cl-gensym "type"))
10421051 (or (cdr (assq ,tp magit--section-type-alist))
10431052 'magit-section))
10441053 :type
1045 (if (class-p ,tp)
1046 (or (car (rassq ,tp magit--section-type-alist))
1047 (error "BUG: No entry for %s in %s" ,tp
1048 'magit--section-type-alist))
1049 ,tp)
1054 (or (and (class-p ,tp)
1055 (car (rassq ,tp magit--section-type-alist)))
1056 ,tp)
10501057 :value ,(nth 1 (car args))
10511058 :start (point-marker)
10521059 :parent magit-insert-section--parent)))
10531060 (oset ,s hidden
1054 (if-let ((value (run-hook-with-args-until-success
1055 'magit-section-set-visibility-hook ,s)))
1056 (eq value 'hide)
1057 (if-let ((incarnation (and magit-insert-section--oldroot
1058 (magit-get-section
1059 (magit-section-ident ,s)
1060 magit-insert-section--oldroot))))
1061 (oref incarnation hidden)
1062 (if-let ((value (magit-section-match-assoc
1063 ,s magit-section-initial-visibility-alist)))
1064 (progn
1065 (when (functionp value)
1066 (setq value (funcall value ,s)))
1067 (eq value 'hide))
1068 ,(nth 2 (car args))))))
1061 (let ((value (run-hook-with-args-until-success
1062 'magit-section-set-visibility-hook ,s)))
1063 (if value
1064 (eq value 'hide)
1065 (let ((incarnation (and magit-insert-section--oldroot
1066 (magit-get-section
1067 (magit-section-ident ,s)
1068 magit-insert-section--oldroot))))
1069 (if incarnation
1070 (oref incarnation hidden)
1071 (let ((value (magit-section-match-assoc
1072 ,s magit-section-initial-visibility-alist)))
1073 (if value
1074 (progn
1075 (when (functionp value)
1076 (setq value (funcall value ,s)))
1077 (eq value 'hide))
1078 ,(nth 2 (car args)))))))))
10691079 (let ((magit-insert-section--current ,s)
10701080 (magit-insert-section--parent ,s)
10711081 (magit-insert-section--oldroot
14321442 (if (oref section hidden)
14331443 (car magit-section-visibility-indicator)
14341444 (cdr magit-section-visibility-indicator))
1435 (face-foreground 'fringe))))))
1445 'fringe)))))
14361446 ((stringp (car-safe magit-section-visibility-indicator))
14371447 (let ((ov (magit--overlay-at (1- eoh) 'magit-vis-indicator 'eoh)))
14381448 (cond ((oref section hidden)
14901500 (1+ (line-end-position)))))
14911501 (when (overlay-get o 'magit-vis-indicator)
14921502 (delete-overlay o)))))
1503
1504 (defvar-local magit-section--opened-sections nil)
1505
1506 (defun magit-section--open-temporarily (beg end)
1507 (save-excursion
1508 (goto-char beg)
1509 (let ((section (magit-current-section)))
1510 (while section
1511 (let ((content (oref section content)))
1512 (if (and (magit-section-invisible-p section)
1513 (<= (or content (oref section start))
1514 beg
1515 (oref section end)))
1516 (progn
1517 (when content
1518 (magit-section-show section)
1519 (push section magit-section--opened-sections))
1520 (setq section (oref section parent)))
1521 (setq section nil))))))
1522 (or (eq search-invisible t)
1523 (not (isearch-range-invisible beg end))))
1524
1525 (defun isearch-clean-overlays@magit-mode (fn)
1526 (if (derived-mode-p 'magit-mode)
1527 (let ((pos (point)))
1528 (dolist (section magit-section--opened-sections)
1529 (unless (<= (oref section content) pos (oref section end))
1530 (magit-section-hide section)))
1531 (setq magit-section--opened-sections nil))
1532 (funcall fn)))
1533
1534 (advice-add 'isearch-clean-overlays :around
1535 'isearch-clean-overlays@magit-mode)
14931536
14941537 ;;; Utilities
14951538
17131756 magit--current-section-hook)))
17141757 (unless (memq entry magit-disabled-section-inserters)
17151758 (if (bound-and-true-p magit-refresh-verbose)
1716 (message " %-50s %s" entry
1717 (benchmark-elapse (apply entry args)))
1759 (let ((time (benchmark-elapse (apply entry args))))
1760 (message " %-50s %s %s" entry time
1761 (cond ((> time 0.03) "!!")
1762 ((> time 0.01) "!")
1763 (t ""))))
17181764 (apply entry args)))))))
17191765
17201766 (cl-defun magit--overlay-at (pos prop &optional (val nil sval) testfn)
17271773 val)))))
17281774 (overlays-at pos t)))
17291775
1776 ;;; Bitmaps
1777
1778 (when (fboundp 'define-fringe-bitmap)
1779 (define-fringe-bitmap 'magit-fringe-bitmap+
1780 [#b00000000
1781 #b00011000
1782 #b00011000
1783 #b01111110
1784 #b01111110
1785 #b00011000
1786 #b00011000
1787 #b00000000])
1788 (define-fringe-bitmap 'magit-fringe-bitmap-
1789 [#b00000000
1790 #b00000000
1791 #b00000000
1792 #b01111110
1793 #b01111110
1794 #b00000000
1795 #b00000000
1796 #b00000000])
1797
1798 (define-fringe-bitmap 'magit-fringe-bitmap>
1799 [#b01100000
1800 #b00110000
1801 #b00011000
1802 #b00001100
1803 #b00011000
1804 #b00110000
1805 #b01100000
1806 #b00000000])
1807 (define-fringe-bitmap 'magit-fringe-bitmapv
1808 [#b00000000
1809 #b10000010
1810 #b11000110
1811 #b01101100
1812 #b00111000
1813 #b00010000
1814 #b00000000
1815 #b00000000])
1816
1817 (define-fringe-bitmap 'magit-fringe-bitmap-bold>
1818 [#b11100000
1819 #b01110000
1820 #b00111000
1821 #b00011100
1822 #b00011100
1823 #b00111000
1824 #b01110000
1825 #b11100000])
1826 (define-fringe-bitmap 'magit-fringe-bitmap-boldv
1827 [#b10000001
1828 #b11000011
1829 #b11100111
1830 #b01111110
1831 #b00111100
1832 #b00011000
1833 #b00000000
1834 #b00000000])
1835 )
1836
17301837 ;;; _
17311838 (provide 'magit-section)
17321839 ;;; magit-section.el ends here
00 ;;; magit-sequence.el --- history manipulation in Magit -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2011-2020 The Magit Project Contributors
2 ;; Copyright (C) 2011-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
77 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9
10 ;; SPDX-License-Identifier: GPL-3.0-or-later
911
1012 ;; Magit is free software; you can redistribute it and/or modify it
1113 ;; under the terms of the GNU General Public License as published by
2830
2931 ;;; Code:
3032
31 (eval-when-compile
32 (require 'subr-x))
33
3433 (require 'magit)
3534
3635 ;; For `magit-rebase--todo'.
130129 "The Perl executable.")
131130
132131 ;;;###autoload (autoload 'magit-cherry-pick "magit-sequence" nil t)
133 (define-transient-command magit-cherry-pick ()
132 (transient-define-prefix magit-cherry-pick ()
134133 "Apply or transplant commits."
135134 :man-page "git-cherry-pick"
136135 :value '("--ff")
159158 ("s" "Skip" magit-sequencer-skip)
160159 ("a" "Abort" magit-sequencer-abort)])
161160
162 (define-infix-argument magit-cherry-pick:--mainline ()
161 (transient-define-argument magit-cherry-pick:--mainline ()
163162 :description "Replay merge relative to parent"
164163 :class 'transient-option
165164 :shortarg "-m"
350349 ;;; Revert
351350
352351 ;;;###autoload (autoload 'magit-revert "magit-sequence" nil t)
353 (define-transient-command magit-revert ()
352 (transient-define-prefix magit-revert ()
354353 "Revert existing commits, with or without creating new commits."
355354 :man-page "git-revert"
356355 :value '("--edit")
402401 ;;; Patch
403402
404403 ;;;###autoload (autoload 'magit-am "magit-sequence" nil t)
405 (define-transient-command magit-am ()
404 (transient-define-prefix magit-am ()
406405 "Apply patches received by email."
407406 :man-page "git-am"
408407 :value '("--3way")
431430 (defun magit-am-arguments ()
432431 (transient-args 'magit-am))
433432
434 (define-infix-argument magit-apply:-p ()
433 (transient-define-argument magit-apply:-p ()
435434 :description "Remove leading slashes from paths"
436435 :class 'transient-option
437436 :argument "-p"
494493 ;;; Rebase
495494
496495 ;;;###autoload (autoload 'magit-rebase "magit-sequence" nil t)
497 (define-transient-command magit-rebase ()
496 (transient-define-prefix magit-rebase ()
498497 "Transplant commits and/or modify existing commits."
499498 :man-page "git-rebase"
500499 ["Arguments"
502501 ("-k" "Keep empty commits" "--keep-empty")
503502 ("-p" "Preserve merges" ("-p" "--preserve-merges"))
504503 (7 magit-merge:--strategy)
504 (7 magit-merge:--strategy-option)
505 (7 "=X" magit-diff:--diff-algorithm :argument "-Xdiff-algorithm=")
505506 ("-d" "Lie about committer date" "--committer-date-is-author-date")
506507 ("-a" "Autosquash" "--autosquash")
507508 ("-A" "Autostash" "--autostash")
534535 ("e" "Edit" magit-rebase-edit)
535536 ("a" "Abort" magit-rebase-abort)])
536537
537 (define-infix-argument magit-rebase:--exec ()
538 (transient-define-argument magit-rebase:--exec ()
538539 :description "Run command after commits"
539540 :class 'transient-option
540541 :shortarg "-x"
553554 (magit-run-git-sequencer "rebase" args target))
554555
555556 ;;;###autoload (autoload 'magit-rebase-onto-pushremote "magit-sequence" nil t)
556 (define-suffix-command magit-rebase-onto-pushremote (args)
557 (transient-define-suffix magit-rebase-onto-pushremote (args)
557558 "Rebase the current branch onto its push-remote branch.
558559
559560 With a prefix argument or when the push-remote is either not
567568 (magit-git-rebase (concat remote "/" branch) args)))
568569
569570 ;;;###autoload (autoload 'magit-rebase-onto-upstream "magit-sequence" nil t)
570 (define-suffix-command magit-rebase-onto-upstream (args)
571 (transient-define-suffix magit-rebase-onto-upstream (args)
571572 "Rebase the current branch onto its upstream branch.
572573
573574 With a prefix argument or when the upstream is either not
666667 (unless (member "--root" args) commit)))
667668 (magit-log-select
668669 `(lambda (commit)
669 (magit-rebase-interactive-1 commit (list ,@args)
670 ,message ,editor ,delay-edit-confirm ,noassert))
670 ;; In some cases (currently just magit-rebase-remove-commit), "-c
671 ;; commentChar=#" is added to the global arguments for git. Ensure
672 ;; that the same happens when we chose the commit via
673 ;; magit-log-select, below.
674 (let ((magit-git-global-arguments (list ,@magit-git-global-arguments)))
675 (magit-rebase-interactive-1 commit (list ,@args)
676 ,message ,editor ,delay-edit-confirm ,noassert)))
671677 message)))
672678
673679 (defvar magit--rebase-published-symbol nil)
752758 "Remove a single older commit using rebase."
753759 (interactive (list (magit-commit-at-point)
754760 (magit-rebase-arguments)))
755 (magit-rebase-interactive-1 commit args
756 "Type %p on a commit to remove it,"
757 (apply-partially #'magit-rebase--perl-editor 'remove)
758 nil nil t))
761 ;; magit-rebase--perl-editor assumes that the comment character is "#".
762 (let ((magit-git-global-arguments
763 (nconc (list "-c" "core.commentChar=#")
764 magit-git-global-arguments)))
765 (magit-rebase-interactive-1 commit args
766 "Type %p on a commit to remove it,"
767 (apply-partially #'magit-rebase--perl-editor 'remove)
768 nil nil t)))
759769
760770 (defun magit-rebase--perl-editor (action since)
761771 (let ((commit (magit-rev-abbrev (magit-rebase--target-commit since))))
764774 commit
765775 (cl-case action
766776 (edit "edit")
767 (remove "# pick")
777 (remove "noop\n# pick")
768778 (reword "reword")
769779 (t (error "unknown action: %s" action)))
770780 commit)))
782792 (file-exists-p (magit-git-dir "rebase-merge"))
783793 (not (member (magit-toplevel)
784794 magit--rebase-public-edit-confirmed)))
785 (magit-commit-amend-assert))
795 (magit-commit-amend-assert
796 (magit-file-line (magit-git-dir "rebase-merge/orig-head"))))
786797 (if noedit
787798 (let ((process-environment process-environment))
788799 (push "GIT_EDITOR=true" process-environment)
898909 (when (magit-rebase-in-progress-p)
899910 (let* ((interactive (file-directory-p (magit-git-dir "rebase-merge")))
900911 (dir (if interactive "rebase-merge/" "rebase-apply/"))
901 (name (-> (concat dir "head-name") magit-git-dir magit-file-line))
902 (onto (-> (concat dir "onto") magit-git-dir magit-file-line))
912 (name (thread-first (concat dir "head-name")
913 magit-git-dir
914 magit-file-line))
915 (onto (thread-first (concat dir "onto")
916 magit-git-dir
917 magit-file-line))
903918 (onto (or (magit-rev-name onto name)
904919 (magit-rev-name onto "refs/heads/*") onto))
905920 (name (or (magit-rev-name name "refs/heads/*") name)))
00 ;;; magit-stash.el --- stash support for Magit -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2008-2020 The Magit Project Contributors
2 ;; Copyright (C) 2008-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
77 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9
10 ;; SPDX-License-Identifier: GPL-3.0-or-later
911
1012 ;; Magit is free software; you can redistribute it and/or modify it
1113 ;; under the terms of the GNU General Public License as published by
2628
2729 ;;; Code:
2830
29 (eval-when-compile
30 (require 'subr-x))
31
3231 (require 'magit)
3332 (require 'magit-reflog)
33
34 ;; For `magit-stash-drop'.
35 (defvar helm-comp-read-use-marked)
3436
3537 ;;; Options
3638
8587 ;;; Commands
8688
8789 ;;;###autoload (autoload 'magit-stash "magit-stash" nil t)
88 (define-transient-command magit-stash ()
90 (transient-define-prefix magit-stash ()
8991 "Stash uncommitted changes."
9092 :man-page "git-stash"
9193 ["Arguments"
230232 (interactive
231233 (list (--if-let (magit-region-values 'stash)
232234 (magit-confirm 'drop-stashes nil "Drop %i stashes" nil it)
233 (magit-read-stash "Drop stash"))))
235 (let ((helm-comp-read-use-marked t))
236 (magit-read-stash "Drop stash")))))
234237 (dolist (stash (if (listp stash)
235238 (nreverse (prog1 stash (setq stash (car stash))))
236239 (list stash)))
268271 current branch or `HEAD' as the start-point."
269272 (interactive (list (magit-read-stash "Branch stash")
270273 (magit-read-string-ns "Branch name")))
271 (let ((inhibit-magit-refresh t))
274 (let ((magit-inhibit-refresh t))
272275 (magit-branch-and-checkout branch (or (magit-get-current-branch) "HEAD")))
273276 (magit-stash-apply stash))
274277
374377 (let ((verified (magit-rev-verify ref))
375378 (autostash
376379 (and (magit-rebase-in-progress-p)
377 (magit-file-line
378 (magit-git-dir
379 (-> (if (file-directory-p (magit-git-dir "rebase-merge"))
380 "rebase-merge/autostash"
381 "rebase-apply/autostash")))))))
380 (thread-first
381 (if (file-directory-p (magit-git-dir "rebase-merge"))
382 "rebase-merge/autostash"
383 "rebase-apply/autostash")
384 magit-git-dir
385 magit-file-line))))
382386 (when (or autostash verified)
383387 (magit-insert-section (stashes ref)
384388 (magit-insert-heading heading)
00 ;;; magit-status.el --- the grand overview -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2010-2020 The Magit Project Contributors
2 ;; Copyright (C) 2010-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
77 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9
10 ;; SPDX-License-Identifier: GPL-3.0-or-later
911
1012 ;; Magit is free software; you can redistribute it and/or modify it
1113 ;; under the terms of the GNU General Public License as published by
2527 ;; This library implements the status buffer.
2628
2729 ;;; Code:
28
29 (eval-when-compile
30 (require 'subr-x))
3130
3231 (require 'magit)
3332
175174 :set-after '(magit-log-margin)
176175 :set (apply-partially #'magit-margin-set-variable 'magit-status-mode))
177176
177 (defcustom magit-status-use-buffer-arguments 'selected
178 "Whether `magit-status' reuses arguments when the buffer already exists.
179
180 This option has no effect when merely refreshing the status
181 buffer using `magit-refresh'.
182
183 Valid values are:
184
185 `always': Always use the set of arguments that is currently
186 active in the status buffer, provided that buffer exists
187 of course.
188 `selected': Use the set of arguments from the status
189 buffer, but only if it is displayed in a window of the
190 current frame. This is the default.
191 `current': Use the set of arguments from the status buffer,
192 but only if it is the current buffer.
193 `never': Never use the set of arguments from the status
194 buffer."
195 :package-version '(magit . "3.0.0")
196 :group 'magit-buffers
197 :group 'magit-commands
198 :type '(choice
199 (const :tag "always use args from buffer" always)
200 (const :tag "use args from buffer if displayed in frame" selected)
201 (const :tag "use args from buffer if it is current" current)
202 (const :tag "never use args from buffer" never)))
203
178204 ;;; Commands
179205
180206 ;;;###autoload
241267 (interactive
242268 (let ((magit--refresh-cache (list (cons 0 0))))
243269 (list (and (or current-prefix-arg (not (magit-toplevel)))
244 (magit-read-repository
245 (>= (prefix-numeric-value current-prefix-arg) 16)))
270 (progn (magit--assert-usable-git)
271 (magit-read-repository
272 (>= (prefix-numeric-value current-prefix-arg) 16))))
246273 magit--refresh-cache)))
247274 (let ((magit--refresh-cache (or cache (list (cons 0 0)))))
248275 (if directory
289316 (if-let ((version (let ((default-directory directory))
290317 (magit-git-version))))
291318 (if (version<= magit--minimal-git version)
292 (push version magit--remotes-using-recent-git)
319 (push remote magit--remotes-using-recent-git)
293320 (display-warning 'magit (format "\
294321 Magit requires Git >= %s, but on %s the version is %s.
295322
326353 map)
327354 "Keymap for `magit-status-mode'.")
328355
329 (define-transient-command magit-status-jump ()
356 (transient-define-prefix magit-status-jump ()
330357 "In a Magit-Status buffer, jump to a section."
331358 ["Jump to"
332359 [("z " "Stashes" magit-jump-to-stashes
343370 :if (lambda () (memq 'magit-insert-unpulled-from-upstream magit-status-sections-hook)))
344371 ("fp" "Unpulled from pushremote" magit-jump-to-unpulled-from-pushremote
345372 :if (lambda () (memq 'magit-insert-unpulled-from-pushremote magit-status-sections-hook)))
346 ("pu" "Unpushed to upstream" magit-jump-to-unpushed-to-upstream
373 ("pu" magit-jump-to-unpushed-to-upstream
347374 :if (lambda ()
348375 (or (memq 'magit-insert-unpushed-to-upstream-or-recent magit-status-sections-hook)
349 (memq 'magit-insert-unpushed-to-upstream magit-status-sections-hook))))
376 (memq 'magit-insert-unpushed-to-upstream magit-status-sections-hook)))
377 :description (lambda ()
378 (let ((upstream (magit-get-upstream-branch)))
379 (if (or (not upstream)
380 (magit-rev-ancestor-p "HEAD" upstream))
381 "Recent commits"
382 "Unmerged into upstream"))))
350383 ("pp" "Unpushed to pushremote" magit-jump-to-unpushed-to-pushremote
351384 :if (lambda () (memq 'magit-insert-unpushed-to-pushremote magit-status-sections-hook)))
352385 ("a " "Assumed unstaged" magit-jump-to-assume-unchanged
396429 (setq directory default-directory))
397430 (magit--tramp-asserts directory)
398431 (let* ((default-directory directory)
399 (d (magit-diff--get-value 'magit-status-mode))
400 (l (magit-log--get-value 'magit-status-mode))
432 (d (magit-diff--get-value 'magit-status-mode
433 magit-status-use-buffer-arguments))
434 (l (magit-log--get-value 'magit-status-mode
435 magit-status-use-buffer-arguments))
401436 (file (and magit-status-goto-file-position
402437 (magit-file-relative-name)))
403438 (line (and file (line-number-at-pos)))
00 ;;; magit-submodule.el --- submodule support for Magit -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2011-2020 The Magit Project Contributors
2 ;; Copyright (C) 2011-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
77 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9
10 ;; SPDX-License-Identifier: GPL-3.0-or-later
911
1012 ;; Magit is free software; you can redistribute it and/or modify it
1113 ;; under the terms of the GNU General Public License as published by
2224
2325 ;;; Code:
2426
25 (eval-when-compile
26 (require 'subr-x))
27
2827 (require 'magit)
2928
3029 (defvar x-stretch-cursor)
30
3131 ;;; Options
3232
3333 (defcustom magit-module-sections-hook
113113 ;;; Popup
114114
115115 ;;;###autoload (autoload 'magit-submodule "magit-submodule" nil t)
116 (define-transient-command magit-submodule ()
116 (transient-define-prefix magit-submodule ()
117117 "Act on a submodule."
118118 :man-page "git-submodule"
119119 ["Arguments"
160160 (cl-call-next-method obj))))
161161
162162 ;;;###autoload (autoload 'magit-submodule-add "magit-submodule" nil t)
163 (define-suffix-command magit-submodule-add (url &optional path name args)
163 (transient-define-suffix magit-submodule-add (url &optional path name args)
164164 "Add the repository at URL as a module.
165165
166166 Optional PATH is the path to the module relative to the root of
224224 (if prefer-short name path)))))
225225
226226 ;;;###autoload (autoload 'magit-submodule-register "magit-submodule" nil t)
227 (define-suffix-command magit-submodule-register (modules)
227 (transient-define-suffix magit-submodule-register (modules)
228228 "Register MODULES.
229229
230230 With a prefix argument act on all suitable modules. Otherwise,
243243 (magit-run-git-async "submodule" "init" "--" modules)))
244244
245245 ;;;###autoload (autoload 'magit-submodule-populate "magit-submodule" nil t)
246 (define-suffix-command magit-submodule-populate (modules)
246 (transient-define-suffix magit-submodule-populate (modules)
247247 "Create MODULES working directories, checking out the recorded commits.
248248
249249 With a prefix argument act on all suitable modules. Otherwise,
260260 (magit-run-git-async "submodule" "update" "--init" "--" modules)))
261261
262262 ;;;###autoload (autoload 'magit-submodule-update "magit-submodule" nil t)
263 (define-suffix-command magit-submodule-update (modules args)
263 (transient-define-suffix magit-submodule-update (modules args)
264264 "Update MODULES by checking out the recorded commits.
265265
266266 With a prefix argument act on all suitable modules. Otherwise,
283283 (magit-run-git-async "submodule" "update" args "--" modules)))
284284
285285 ;;;###autoload (autoload 'magit-submodule-synchronize "magit-submodule" nil t)
286 (define-suffix-command magit-submodule-synchronize (modules args)
286 (transient-define-suffix magit-submodule-synchronize (modules args)
287287 "Synchronize url configuration of MODULES.
288288
289289 With a prefix argument act on all suitable modules. Otherwise,
299299 (magit-run-git-async "submodule" "sync" args "--" modules)))
300300
301301 ;;;###autoload (autoload 'magit-submodule-unpopulate "magit-submodule" nil t)
302 (define-suffix-command magit-submodule-unpopulate (modules args)
302 (transient-define-suffix magit-submodule-unpopulate (modules args)
303303 "Remove working directories of MODULES.
304304
305305 With a prefix argument act on all suitable modules. Otherwise,
326326 "Unregister MODULES and remove their working directories.
327327
328328 For safety reasons, do not remove the gitdirs and if a module has
329 uncomitted changes, then do not remove it at all. If a module's
329 uncommitted changes, then do not remove it at all. If a module's
330330 gitdir is located inside the working directory, then move it into
331331 the gitdir of the superproject first.
332332
00 ;;; magit-subtree.el --- subtree support for Magit -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2011-2020 The Magit Project Contributors
2 ;; Copyright (C) 2011-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
77 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9
10 ;; SPDX-License-Identifier: GPL-3.0-or-later
911
1012 ;; Magit is free software; you can redistribute it and/or modify it
1113 ;; under the terms of the GNU General Public License as published by
2729 ;;; Commands
2830
2931 ;;;###autoload (autoload 'magit-subtree "magit-subtree" nil t)
30 (define-transient-command magit-subtree ()
32 (transient-define-prefix magit-subtree ()
3133 "Import or export subtrees."
3234 :man-page "git-subtree"
3335 ["Actions"
3537 ("e" "Export" magit-subtree-export)])
3638
3739 ;;;###autoload (autoload 'magit-subtree-import "magit-subtree" nil t)
38 (define-transient-command magit-subtree-import ()
40 (transient-define-prefix magit-subtree-import ()
3941 "Import subtrees."
4042 :man-page "git-subtree"
4143 ["Arguments"
4951 ("f" "Pull" magit-subtree-pull)]])
5052
5153 ;;;###autoload (autoload 'magit-subtree-export "magit-subtree" nil t)
52 (define-transient-command magit-subtree-export ()
54 (transient-define-prefix magit-subtree-export ()
5355 "Export subtrees."
5456 :man-page "git-subtree"
5557 ["Arguments"
6365 ("p" "Push" magit-subtree-push)
6466 ("s" "Split" magit-subtree-split)])
6567
66 (define-infix-argument magit-subtree:--prefix ()
68 (transient-define-argument magit-subtree:--prefix ()
6769 :description "Prefix"
6870 :class 'transient-option
6971 :shortarg "-P"
8183 (user-error "%s isn't inside the repository at %s" prefix topdir))
8284 prefix)))
8385
84 (define-infix-argument magit-subtree:--message ()
86 (transient-define-argument magit-subtree:--message ()
8587 :description "Message"
8688 :class 'transient-option
8789 :shortarg "-m"
8890 :argument "--message=")
8991
90 (define-infix-argument magit-subtree:--annotate ()
92 (transient-define-argument magit-subtree:--annotate ()
9193 :description "Annotate"
9294 :class 'transient-option
9395 :key "-a"
9496 :argument "--annotate=")
9597
96 (define-infix-argument magit-subtree:--branch ()
98 (transient-define-argument magit-subtree:--branch ()
9799 :description "Branch"
98100 :class 'transient-option
99101 :shortarg "-b"
100102 :argument "--branch=")
101103
102 (define-infix-argument magit-subtree:--onto ()
104 (transient-define-argument magit-subtree:--onto ()
103105 :description "Onto"
104106 :class 'transient-option
105107 :key "-o"
00 ;;; magit-tag.el --- tag functionality -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2010-2020 The Magit Project Contributors
2 ;; Copyright (C) 2010-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
77 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9
10 ;; SPDX-License-Identifier: GPL-3.0-or-later
911
1012 ;; Magit is free software; you can redistribute it and/or modify it
1113 ;; under the terms of the GNU General Public License as published by
2830
2931 (require 'magit)
3032
33 ;; For `magit-tag-delete'.
34 (defvar helm-comp-read-use-marked)
35
3136 ;;;###autoload (autoload 'magit-tag "magit" nil t)
32 (define-transient-command magit-tag ()
37 (transient-define-prefix magit-tag ()
3338 "Create or delete a tag."
3439 :man-page "git-tag"
3540 ["Arguments"
4752 (defun magit-tag-arguments ()
4853 (transient-args 'magit-tag))
4954
50 (define-infix-argument magit-tag:--local-user ()
55 (transient-define-argument magit-tag:--local-user ()
5156 :description "Sign as"
5257 :class 'transient-option
5358 :shortarg "-u"
5459 :argument "--local-user="
55 :reader 'magit-read-gpg-secret-key
60 :reader 'magit-read-gpg-signing-key
5661 :history-key 'magit:--gpg-sign)
5762
5863 ;;;###autoload
7782 \n(git tag -d TAGS)"
7883 (interactive (list (--if-let (magit-region-values 'tag)
7984 (magit-confirm t nil "Delete %i tags" nil it)
80 (magit-read-tag "Delete tag" t))))
85 (let ((helm-comp-read-use-marked t))
86 (magit-read-tag "Delete tag" t)))))
8187 (magit-run-git "tag" "-d" tags))
8288
8389 ;;;###autoload
110116 (magit-run-git-async "push" remote (--map (concat ":" it) remote-tags))))
111117
112118 (defvar magit-tag-version-regexp-alist
113 '(("^[-._+ ]?alpha\\.?$" . -3)
119 '(("^[-._+ ]?snapshot\\.?$" . -4)
120 ("^[-._+]$" . -4)
121 ("^[-._+ ]?\\(cvs\\|git\\|bzr\\|svn\\|hg\\|darcs\\)\\.?$" . -4)
122 ("^[-._+ ]?unknown\\.?$" . -4)
123 ("^[-._+ ]?alpha\\.?$" . -3)
114124 ("^[-._+ ]?beta\\.?$" . -2)
115125 ("^[-._+ ]?\\(pre\\|rc\\)\\.?$" . -1))
116 "Value to use for `version-regexp-alist' when parsing and sorting versions.
117 The default value matches some common SemVer pre-release formats.
126 "Overrides `version-regexp-alist' for `magit-tag-release'.
118127 See also `magit-release-tag-regexp'.")
119128
120129 (defvar magit-release-tag-regexp "\\`\
121130 \\(?1:\\(?:v\\(?:ersion\\)?\\|r\\(?:elease\\)?\\)?[-_]?\\)?\
122131 \\(?2:[0-9]+\\(?:\\.[0-9]+\\)*\
123132 \\(?:-[a-zA-Z0-9-]+\\(?:\\.[a-zA-Z0-9-]+\\)*\\)?\\)\\'"
124 "Regexp used to parse release tag names.
125 The first submatch must match the prefix, if any.
126 The second submatch must match the version string.
127 The default value matches SemVer version numbers, including
128 pre-release versions.
129
130 If this will match versions that are not dot separated numbers, you
131 also need to set `magit-tag-version-regexp-alist' to recognize them
132 and give them a sorting order.")
133
134 ;;;###autoload
135 (defun magit-tag-release (tag msg)
136 "Create an annotated release tag.
133 "Regexp used by `magit-tag-release' to parse release tags.
134
135 The first submatch must match the prefix, if any. The second
136 submatch must match the version string.
137
138 If this matches versions that are not dot separated numbers,
139 then `magit-tag-version-regexp-alist' has to contain entries
140 for the separators allowed here.")
141
142 ;;;###autoload
143 (defun magit-tag-release (tag msg &optional args)
144 "Create a release tag.
137145
138146 Assume that release tags match `magit-release-tag-regexp'.
139147
141149 existing tag as initial input and leaving it to the user to
142150 increment the desired part of the version string.
143151
144 Then prompt for the message of the new tag. Base the proposed
145 tag message on the message of the highest tag, provided that
146 that contains the corresponding version string and substituting
147 the new version string for that. Otherwise propose something
148 like \"Foo-Bar 1.2.3\", given, for example, a TAG \"v1.2.3\" and a
149 repository located at something like \"/path/to/foo-bar\".
150
151 Then call \"git tag --annotate --sign -m MSG TAG\" to create the,
152 tag, regardless of whether these arguments are enabled in the
153 popup. Finally show the refs buffer to let the user quickly
154 review the result."
152 If `--annotate' is enabled, then prompt for the message of the
153 new tag. Base the proposed tag message on the message of the
154 highest tag, provided that that contains the corresponding
155 version string and substituting the new version string for that.
156 Otherwise propose something like \"Foo-Bar 1.2.3\", given, for
157 example, a TAG \"v1.2.3\" and a repository located at something
158 like \"/path/to/foo-bar\"."
155159 (interactive
156160 (save-match-data
157161 (pcase-let*
159163 (tag (read-string "Create release tag: " ptag))
160164 (ver (and (string-match magit-release-tag-regexp tag)
161165 (match-string 2 tag)))
162 (msg (cond ((and pver (string-match (regexp-quote pver) pmsg))
163 (replace-match ver t t pmsg))
164 ((and ptag (string-match (regexp-quote ptag) pmsg))
165 (replace-match tag t t pmsg))
166 (t (format "%s %s"
167 (capitalize
168 (file-name-nondirectory
169 (directory-file-name (magit-toplevel))))
170 ver)))))
171 (list tag (read-string (format "Message for %S: " tag) msg)))))
172 (magit-run-git-async "tag" "--annotate" "--sign" "-m" msg tag)
166 (args (magit-tag-arguments)))
167 (list tag
168 (and (member "--annotate" args)
169 (read-string
170 (format "Message for %S: " tag)
171 (cond ((and pver (string-match (regexp-quote pver) pmsg))
172 (replace-match ver t t pmsg))
173 ((and ptag (string-match (regexp-quote ptag) pmsg))
174 (replace-match tag t t pmsg))
175 (t (format "%s %s"
176 (capitalize
177 (file-name-nondirectory
178 (directory-file-name (magit-toplevel))))
179 ver)))))
180 args))))
181 (magit-run-git-async "tag" args (and msg (list "-m" msg)) tag)
173182 (set-process-sentinel
174183 magit-this-process
175184 (lambda (process event)
00 ;;; magit-transient.el --- support for transients -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2008-2020 The Magit Project Contributors
2 ;; Copyright (C) 2008-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
77 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9
10 ;; SPDX-License-Identifier: GPL-3.0-or-later
911
1012 ;; Magit is free software; you can redistribute it and/or modify it
1113 ;; under the terms of the GNU General Public License as published by
2729
2830 ;;; Code:
2931
30 (eval-when-compile
31 (require 'subr-x))
32
33 (require 'transient)
34
3532 (require 'magit-git)
3633 (require 'magit-mode)
3734 (require 'magit-process)
35
36 (require 'transient)
3837
3938 ;;; Classes
4039
00 ;;; magit-utils.el --- various utilities -*- lexical-binding: t; coding: utf-8 -*-
11
2 ;; Copyright (C) 2010-2020 The Magit Project Contributors
2 ;; Copyright (C) 2010-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
99
1010 ;; Contains code from GNU Emacs https://www.gnu.org/software/emacs,
1111 ;; released under the GNU General Public License version 3 or later.
12
13 ;; SPDX-License-Identifier: GPL-3.0-or-later
1214
1315 ;; Magit is free software; you can redistribute it and/or modify it
1416 ;; under the terms of the GNU General Public License as published by
3941
4042 (require 'cl-lib)
4143 (require 'dash)
42
43 (eval-when-compile
44 (require 'subr-x))
44 (require 'eieio)
45 (require 'seq)
46 (require 'subr-x)
4547
4648 (require 'crm)
4749
99101 (forge-browse-pullreq nil t)
100102 (forge-edit-topic-title nil t)
101103 (forge-edit-topic-state nil t)
104 (forge-edit-topic-milestone nil t)
102105 (forge-edit-topic-labels nil t)
103106 (forge-edit-topic-marks nil t)
104107 (forge-edit-topic-assignees nil t)
105108 (forge-edit-topic-review-requests nil t)
109 (forge-edit-topic-note nil t)
106110 (forge-pull-pullreq nil t)
107111 (forge-visit-issue nil t)
108 (forge-visit-pullreq nil t))
112 (forge-visit-pullreq nil t)
113 (forge-visit-topic nil t))
109114 "When not to offer alternatives and ask for confirmation.
110115
111116 Many commands by default ask the user to select from a list of
144149 (const :tag "use default without confirmation" t)))))
145150
146151 (defconst magit--confirm-actions
147 '((const reverse) (const discard)
148 (const rename) (const resurrect)
149 (const untrack) (const trash)
150 (const delete) (const abort-rebase)
151 (const abort-merge) (const merge-dirty)
152 (const drop-stashes) (const reset-bisect)
153 (const kill-process) (const delete-unmerged-branch)
154 (const delete-pr-branch) (const remove-modules)
155 (const stage-all-changes) (const unstage-all-changes)
152 '((const discard)
153 (const reverse)
154 (const stage-all-changes)
155 (const unstage-all-changes)
156 (const delete)
157 (const trash)
158 (const resurrect)
159 (const untrack)
160 (const rename)
161 (const reset-bisect)
162 (const abort-rebase)
163 (const abort-merge)
164 (const merge-dirty)
165 (const delete-unmerged-branch)
166 (const delete-branch-on-remote)
167 (const delete-pr-remote)
168 (const drop-stashes)
169 (const set-and-push)
170 (const amend-published)
171 (const rebase-published)
172 (const edit-published)
173 (const remove-modules)
174 (const remove-dirty-modules)
175 (const trash-module-gitdirs)
176 (const kill-process)
156177 (const safe-with-wip)))
157178
158 (defcustom magit-no-confirm nil
179 (defcustom magit-no-confirm '(set-and-push)
159180 "A list of symbols for actions Magit should not confirm, or t.
160181
161182 Many potentially dangerous commands by default ask the user for
222243 to confirm the deletion of a branch by accepting the default
223244 choice (or selecting another branch), but when a branch has
224245 not been merged yet, also make sure the user is aware of that.
246
247 `delete-branch-on-remote' Deleting a \"remote branch\" may mean
248 deleting the (local) \"remote-tracking\" branch only, or also
249 removing it from the remote itself. The latter often makes more
250 sense because otherwise simply fetching from the remote would
251 restore the remote-tracking branch, but doing that can be
252 surprising and hard to recover from, so we ask.
225253
226254 `delete-pr-remote' When deleting a branch that was created from
227255 a pull-request and if no other branches still exist on that
237265 to confirm by accepting the default (or selecting another).
238266 This action only concerns the deletion of multiple stashes at
239267 once.
268
269 Publishing:
270
271 `set-and-push' When pushing to the upstream or the push-remote
272 and that isn't actually configured yet, then the user can first
273 set the target. If s/he confirms the default too quickly, then
274 s/he might end up pushing to the wrong branch and if the remote
275 repository is configured to disallow fixing such mistakes, then
276 that can be quite embarrassing and annoying.
240277
241278 Edit published history:
242279
352389 :group 'magit-miscellaneous
353390 :type '(repeat string))
354391
355 (defcustom magit-ellipsis ?…
356 "Character used to abbreviate text.
357
358 Currently this is used to abbreviate author names in the margin
359 and in process buffers to elide `magit-git-global-arguments'."
360 :package-version '(magit . "2.1.0")
392 (defcustom magit-ellipsis (if (char-displayable-p ?…) "…" "...")
393 "String used to abbreviate text in process buffers.
394
395 Currently this is only used to elide `magit-git-global-arguments'
396 in process buffers. In the future it may be used in other places
397 as well, but not the following:
398
399 - Author names in the log margin are always abbreviated using
400 \"…\" or if that is not displayable, then \">\".
401
402 - Whether collapsed sections are indicated using ellipsis is
403 controlled by `magit-section-visibility-indicator'."
404 :package-version '(magit . "3.0.0")
361405 :group 'magit-miscellaneous
362 :type 'character)
406 :type 'string)
363407
364408 (defcustom magit-update-other-window-delay 0.2
365409 "Delay before automatically updating the other window.
399443 ;;; User Input
400444
401445 (defvar helm-completion-in-region-default-sort-fn)
446 (defvar helm-crm-default-separator)
402447 (defvar ivy-sort-functions-alist)
448 (defvar ivy-sort-matches-functions-alist)
403449
404450 (defvar magit-completing-read--silent-default nil)
405451
473519 predicate
474520 require-match initial-input hist def)))
475521 (setq this-command command)
476 (if (string= reply "")
522 ;; Note: Avoid `string=' to support `helm-comp-read-use-marked'.
523 (if (equal reply "")
477524 (if require-match
478525 (user-error "Nothing selected")
479526 nil)
520567 (minibuffer-completion-table #'crm--collection-fn)
521568 (minibuffer-completion-confirm t)
522569 (helm-completion-in-region-default-sort-fn nil)
570 (helm-crm-default-separator nil)
571 (ivy-sort-matches-functions-alist nil)
523572 (input
524573 (cl-letf (((symbol-function 'completion-pcm--all-completions)
525574 #'magit-completion-pcm--all-completions))
554603 crm-local-must-match-map
555604 crm-local-completion-map))
556605 (helm-completion-in-region-default-sort-fn nil)
606 (ivy-sort-matches-functions-alist nil)
557607 ;; If the user enters empty input, `read-from-minibuffer'
558608 ;; returns the empty string, not DEF.
559609 (input (read-from-minibuffer
654704 (debug (form form &rest (characterp form body))))
655705 `(prog1 (pcase (read-char-choice
656706 (concat ,prompt
657 ,(concat (mapconcat 'cadr clauses ", ")
658 (and verbose ", or [C-g] to abort") " "))
659 ',(mapcar 'car clauses))
707 (mapconcat #'identity
708 (list ,@(mapcar #'cadr clauses))
709 ", ")
710 ,(if verbose ", or [C-g] to abort " " "))
711 ',(mapcar #'car clauses))
660712 ,@(--map `(,(car it) ,@(cddr it)) clauses))
661713 (message "")))
662714
779831 (i 0))
780832 `(let ((,s ,string))
781833 (let ,(save-match-data
782 (--map (list it (list 'match-string (cl-incf i) s)) varlist))
834 (cl-mapcan (lambda (sym)
835 (cl-incf i)
836 (and (not (eq (aref (symbol-name sym) 0) ?_))
837 (list (list sym (list 'match-string i s)))))
838 varlist))
783839 ,@body))))
784840
785841 (defun magit-delete-line ()
812868 "Set the header-line using STRING.
813869 Propertize STRING with the `magit-header-line'. If the `face'
814870 property of any part of STRING is already set, then that takes
815 precedence. Also pad the left and right sides of STRING so that
816 it aligns with the text area."
871 precedence. Also pad the left side of STRING so that it aligns
872 with the text area."
817873 (setq header-line-format
818 (concat
819 (propertize " " 'display '(space :align-to 0))
820 string
821 (propertize " " 'display
822 `(space :width
823 (+ left-fringe
824 left-margin
825 ,@(and (eq (car (window-current-scroll-bars))
826 'left)
827 '(scroll-bar)))))))
828 (magit--add-face-text-property 0 (1- (length header-line-format))
829 'magit-header-line t header-line-format))
874 (concat (propertize " " 'display '(space :align-to 0))
875 string)))
830876
831877 (defun magit-face-property-all (face string)
832878 "Return non-nil if FACE is present in all of STRING."
833 (cl-loop for pos = 0 then (next-single-property-change
834 pos 'font-lock-face string)
835 unless pos
836 return t
837 for current = (get-text-property pos 'font-lock-face string)
838 unless (if (consp current)
839 (memq face current)
840 (eq face current))
841 return nil))
879 (catch 'missing
880 (let ((pos 0))
881 (while (setq pos (next-single-property-change pos 'font-lock-face string))
882 (let ((val (get-text-property pos 'font-lock-face string)))
883 (unless (if (consp val)
884 (memq face val)
885 (eq face val))
886 (throw 'missing nil))))
887 (not pos))))
842888
843889 (defun magit--add-face-text-property (beg end face &optional append object)
844890 "Like `add-face-text-property' but for `font-lock-face'."
845 (cl-loop for pos = (next-single-property-change
846 beg 'font-lock-face object end)
847 for current = (get-text-property beg 'font-lock-face object)
848 for newface = (if (listp current)
849 (if append
850 (append current (list face))
851 (cons face current))
852 (if append
853 (list current face)
854 (list face current)))
855 do (progn (put-text-property beg pos 'font-lock-face newface object)
856 (setq beg pos))
857 while (< beg end)))
891 (while (< beg end)
892 (let* ((pos (next-single-property-change beg 'font-lock-face object end))
893 (val (get-text-property beg 'font-lock-face object))
894 (val (if (listp val) val (list val))))
895 (put-text-property beg pos 'font-lock-face
896 (if append
897 (append val (list face))
898 (cons face val))
899 object)
900 (setq beg pos))))
858901
859902 (defun magit--propertize-face (string face)
860903 (propertize string 'face face 'font-lock-face face))
11031146 (advice-add 'org-man-export :around
11041147 'org-man-export--magit-gitman)
11051148
1106 ;;; Bitmaps
1107
1108 (when (fboundp 'define-fringe-bitmap)
1109 (define-fringe-bitmap 'magit-fringe-bitmap+
1110 [#b00000000
1111 #b00011000
1112 #b00011000
1113 #b01111110
1114 #b01111110
1115 #b00011000
1116 #b00011000
1117 #b00000000])
1118 (define-fringe-bitmap 'magit-fringe-bitmap-
1119 [#b00000000
1120 #b00000000
1121 #b00000000
1122 #b01111110
1123 #b01111110
1124 #b00000000
1125 #b00000000
1126 #b00000000])
1127
1128 (define-fringe-bitmap 'magit-fringe-bitmap>
1129 [#b01100000
1130 #b00110000
1131 #b00011000
1132 #b00001100
1133 #b00011000
1134 #b00110000
1135 #b01100000
1136 #b00000000])
1137 (define-fringe-bitmap 'magit-fringe-bitmapv
1138 [#b00000000
1139 #b10000010
1140 #b11000110
1141 #b01101100
1142 #b00111000
1143 #b00010000
1144 #b00000000
1145 #b00000000])
1146
1147 (define-fringe-bitmap 'magit-fringe-bitmap-bold>
1148 [#b11100000
1149 #b01110000
1150 #b00111000
1151 #b00011100
1152 #b00011100
1153 #b00111000
1154 #b01110000
1155 #b11100000])
1156 (define-fringe-bitmap 'magit-fringe-bitmap-boldv
1157 [#b10000001
1158 #b11000011
1159 #b11100111
1160 #b01111110
1161 #b00111100
1162 #b00011000
1163 #b00000000
1164 #b00000000])
1165 )
1149 ;;; Kludges for Package Managers
1150
1151 (defun magit--straight-chase-links (filename)
1152 "Chase links in FILENAME until a name that is not a link.
1153
1154 This is the same as `file-chase-links', except that it also
1155 handles fake symlinks that are created by the package manager
1156 straight.el on Windows.
1157
1158 See <https://github.com/raxod502/straight.el/issues/520>."
1159 (when (and (bound-and-true-p straight-symlink-emulation-mode)
1160 (fboundp 'straight-chase-emulated-symlink))
1161 (when-let ((target (straight-chase-emulated-symlink filename)))
1162 (unless (eq target 'broken)
1163 (setq filename target))))
1164 (file-chase-links filename))
11661165
11671166 ;;; Miscellaneous
11681167
11861185 (save-excursion
11871186 (save-restriction
11881187 (widen)
1189 (goto-char ,pos)
1188 (goto-char (or ,pos 1))
11901189 ,@body))))
11911190
11921191 ;;; _
00 ;;; magit-wip.el --- commit snapshots to work-in-progress refs -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2010-2020 The Magit Project Contributors
2 ;; Copyright (C) 2010-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
77 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9
10 ;; SPDX-License-Identifier: GPL-3.0-or-later
911
1012 ;; Magit is free software; you can redistribute it and/or modify it
1113 ;; under the terms of the GNU General Public License as published by
2931
3032 ;;; Code:
3133
32 (eval-when-compile
33 (require 'subr-x))
34
3534 (require 'magit-core)
3635 (require 'magit-log)
3736
106105
107106 ;;; Modes
108107
108 ;;;###autoload
109109 (define-minor-mode magit-wip-mode
110110 "Save uncommitted changes to work-in-progress refs.
111111
00 ;;; magit-worktree.el --- worktree support -*- lexical-binding: t -*-
11
2 ;; Copyright (C) 2010-2020 The Magit Project Contributors
2 ;; Copyright (C) 2010-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
77 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
88 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9
10 ;; SPDX-License-Identifier: GPL-3.0-or-later
911
1012 ;; Magit is free software; you can redistribute it and/or modify it
1113 ;; under the terms of the GNU General Public License as published by
4244 ;;; Commands
4345
4446 ;;;###autoload (autoload 'magit-worktree "magit-worktree" nil t)
45 (define-transient-command magit-worktree ()
47 (transient-define-prefix magit-worktree ()
4648 "Act on a worktree."
4749 :man-page "git-worktree"
4850 [["Create new"
161163 (pcase-lambda (`(,path ,barep ,commit ,branch))
162164 (cons (cond
163165 (branch (propertize
164 branch 'font-lock-face 'magit-branch-local))
166 branch 'font-lock-face
167 (if (equal branch (magit-get-current-branch))
168 'magit-branch-current
169 'magit-branch-local)))
165170 (commit (propertize (magit-rev-abbrev commit)
166171 'font-lock-face 'magit-hash))
167172 (barep "(bare)"))
171176 (pcase-dolist (`(,head . ,path) cols)
172177 (magit-insert-section (worktree path)
173178 (insert head)
174 (indent-to align)
179 (insert (make-string (- align (length head)) ?\s))
175180 (insert (let ((r (file-relative-name path))
176181 (a (abbreviate-file-name path)))
177182 (if (< (string-width r) (string-width a)) r a)))
00 ;;; magit.el --- A Git porcelain inside Emacs -*- lexical-binding: t; coding: utf-8 -*-
11
2 ;; Copyright (C) 2008-2020 The Magit Project Contributors
2 ;; Copyright (C) 2008-2021 The Magit Project Contributors
33 ;;
44 ;; You should have received a copy of the AUTHORS.md file which
55 ;; lists all contributors. If not, see http://magit.vc/authors.
66
77 ;; Author: Marius Vollmer <marius.vollmer@gmail.com>
8 ;; Jonas Bernoulli <jonas@bernoul.li>
89 ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
9 ;; Kyle Meyer <kyle@kyleam.com>
10 ;; Noam Postavsky <npostavs@users.sourceforge.net>
10 ;; Kyle Meyer <kyle@kyleam.com>
11 ;; Noam Postavsky <npostavs@users.sourceforge.net>
1112 ;; Former-Maintainers:
12 ;; Nicolas Dudebout <nicolas.dudebout@gatech.edu>
13 ;; Peter J. Weisberg <pj@irregularexpressions.net>
14 ;; Phil Jackson <phil@shellarchive.co.uk>
15 ;; Rémi Vanicat <vanicat@debian.org>
16 ;; Yann Hodique <yann.hodique@gmail.com>
13 ;; Nicolas Dudebout <nicolas.dudebout@gatech.edu>
14 ;; Peter J. Weisberg <pj@irregularexpressions.net>
15 ;; Phil Jackson <phil@shellarchive.co.uk>
16 ;; Rémi Vanicat <vanicat@debian.org>
17 ;; Yann Hodique <yann.hodique@gmail.com>
1718
1819 ;; Keywords: git tools vc
1920 ;; Homepage: https://github.com/magit/magit
20
21 ;; Magit requires at least GNU Emacs 25.1 and Git 2.2.0.
21 ;; SPDX-License-Identifier: GPL-3.0-or-later
2222
2323 ;; Magit is free software; you can redistribute it and/or modify it
2424 ;; under the terms of the GNU General Public License as published by
3333 ;; You should have received a copy of the GNU General Public License
3434 ;; along with Magit. If not, see http://www.gnu.org/licenses.
3535
36 ;; Magit requires at least GNU Emacs 25.1 and Git 2.2.0.
37
3638 ;;; Commentary:
3739
38 ;; Magit is an interface to the version control system Git,
39 ;; implemented as an Emacs package. Magit aspires to be a complete
40 ;; Git porcelain. While we cannot (yet) claim, that Magit wraps and
41 ;; improves upon each and every Git command, it is complete enough to
42 ;; allow even experienced Git users to perform almost all of their
43 ;; daily version control tasks directly from within Emacs. While many
44 ;; fine Git clients exist, only Magit and Git itself deserve to be
45 ;; called porcelains.
40 ;; Magit is a text-based Git user interface that puts an unmatched focus
41 ;; on streamlining workflows. Commands are invoked using short mnemonic
42 ;; key sequences that take the cursor’s position in the highly actionable
43 ;; interface into account to provide context-sensitive behavior.
44
45 ;; With Magit you can do nearly everything that you can do when using Git
46 ;; on the command-line, but at greater speed and while taking advantage
47 ;; of advanced features that previously seemed too daunting to use on a
48 ;; daily basis. Many users will find that by using Magit they can become
49 ;; more effective Git user.
4650
4751 ;;; Code:
4852
49 (require 'cl-lib)
50 (require 'dash)
51
52 (require 'subr-x)
53
54 (require 'with-editor)
55 (require 'git-commit)
5653 (require 'magit-core)
5754 (require 'magit-diff)
5855 (require 'magit-log)
5956 (require 'magit-wip)
6057 (require 'magit-apply)
6158 (require 'magit-repos)
59 (require 'git-commit)
6260
6361 (require 'format-spec)
6462 (require 'package nil t) ; used in `magit-version'
63 (require 'with-editor)
6564
6665 (defconst magit--minimal-git "2.2.0")
6766 (defconst magit--minimal-emacs "25.1")
179178 :group 'magit-faces)
180179
181180 (defface magit-signature-untrusted
182 '((t :foreground "cyan"))
181 '((t :foreground "medium aquamarine"))
183182 "Face for good untrusted signatures."
184183 :group 'magit-faces)
185184
199198 :group 'magit-faces)
200199
201200 (defface magit-signature-error
202 '((t :foreground "firebrick3"))
201 '((t :foreground "light blue"))
203202 "Face for signatures that cannot be checked (e.g. missing key)."
204203 :group 'magit-faces)
205204
218217 "Face for filenames."
219218 :group 'magit-faces)
220219
220 ;;; Global Bindings
221
222 ;;;###autoload
223 (define-obsolete-variable-alias 'global-magit-file-mode
224 'magit-define-global-key-bindings "Magit 3.0.0")
225
226 ;;;###autoload
227 (defcustom magit-define-global-key-bindings t
228 "Whether to bind some Magit commands in the global keymap.
229
230 If this variable is non-nil, then the following bindings may
231 be added to the global keymap. The default is t.
232
233 key binding
234 --- -------
235 C-x g magit-status
236 C-x M-g magit-dispatch
237 C-c M-g magit-file-dispatch
238
239 These bindings may be added when `after-init-hook' is called.
240 Each binding is added if and only if at that time no other key
241 is bound to the same command and no other command is bound to
242 the same key. In other words we try to avoid adding bindings
243 that are unnecessary, as well as bindings that conflict with
244 other bindings.
245
246 Adding the above bindings is delayed until `after-init-hook'
247 is called to allow users to set the variable anywhere in their
248 init file (without having to make sure to do so before `magit'
249 is loaded or autoloaded) and to increase the likelihood that
250 all the potentially conflicting user bindings have already
251 been added.
252
253 Setting this variable after the hook has already been called
254 has no effect.
255
256 We recommend that you bind \"C-c g\" instead of \"C-c M-g\" to
257 `magit-file-dispatch'. The former is a much better binding
258 but the \"C-c <letter>\" namespace is strictly reserved for
259 users; preventing Magit from using it by default.
260
261 Also see info node `(magit)Commands for Buffers Visiting Files'."
262 :package-version '(magit . "3.0.0")
263 :group 'magit-essentials
264 :type 'boolean)
265
266 ;;;###autoload
267 (progn
268 (defun magit-maybe-define-global-key-bindings ()
269 (when magit-define-global-key-bindings
270 (let ((map (current-global-map)))
271 (dolist (elt '(("C-x g" . magit-status)
272 ("C-x M-g" . magit-dispatch)
273 ("C-c M-g" . magit-file-dispatch)))
274 (let ((key (kbd (car elt)))
275 (def (cdr elt)))
276 (unless (or (lookup-key map key)
277 (where-is-internal def (make-sparse-keymap) t))
278 (define-key map key def)))))))
279 (if after-init-time
280 (magit-maybe-define-global-key-bindings)
281 (add-hook 'after-init-hook 'magit-maybe-define-global-key-bindings t)))
282
221283 ;;; Dispatch Popup
222284
223285 ;;;###autoload (autoload 'magit-dispatch "magit" nil t)
224 (define-transient-command magit-dispatch ()
286 (transient-define-prefix magit-dispatch ()
225287 "Invoke a Magit command from a list of available commands."
288 :info-manual "(magit)Top"
226289 ["Transient and dwim commands"
227290 [("A" "Apply" magit-cherry-pick)
228291 ("b" "Branch" magit-branch)
235298 ("E" "Ediff" magit-ediff)]
236299 [("f" "Fetch" magit-fetch)
237300 ("F" "Pull" magit-pull)
301 ("I" "Init" magit-init)
238302 ("l" "Log" magit-log)
239303 ("L" "Log (change)" magit-log-refresh)
240304 ("m" "Merge" magit-merge)
283347 (defvar magit-git-command-history nil)
284348
285349 ;;;###autoload (autoload 'magit-run "magit" nil t)
286 (define-transient-command magit-run ()
350 (transient-define-prefix magit-run ()
287351 "Run git or another command, or launch a graphical utility."
352
353
288354 [["Run git subcommand"
289355 ("!" "in repository root" magit-git-command-topdir)
290356 ("p" "in working directory" magit-git-command)]
349415 (magit-process-buffer))
350416
351417 (defun magit-read-shell-command (&optional toplevel initial-input)
352 (let ((dir (abbreviate-file-name
353 (if (or toplevel current-prefix-arg)
354 (or (magit-toplevel)
355 (magit--not-inside-repository-error))
356 default-directory))))
418 (let ((default-directory
419 (if (or toplevel current-prefix-arg)
420 (or (magit-toplevel)
421 (magit--not-inside-repository-error))
422 default-directory)))
357423 (read-shell-command (if magit-shell-command-verbose-prompt
358 (format "Async shell command in %s: " dir)
424 (format "Async shell command in %s: "
425 (abbreviate-file-name default-directory))
359426 "Async shell command: ")
360427 initial-input 'magit-git-command-history)))
361428
399466 (unless (and toplib
400467 (equal (file-name-nondirectory toplib) "magit.el"))
401468 (setq toplib (locate-library "magit.el")))
402 (setq toplib (and toplib (file-chase-links toplib)))
469 (setq toplib (and toplib (magit--straight-chase-links toplib)))
403470 (push toplib debug)
404471 (when toplib
405472 (let* ((topdir (file-name-directory toplib))
407474 ".git" (file-name-directory
408475 (directory-file-name topdir))))
409476 (static (locate-library "magit-version.el" nil (list topdir)))
410 (static (and static (file-chase-links static))))
477 (static (and static (magit--straight-chase-links static))))
411478 (or (progn
412479 (push 'repo debug)
413480 (when (and (file-exists-p gitdir)
421488 (ignore-errors (delete-file static)))
422489 (setq magit-version
423490 (let ((default-directory topdir))
424 (magit-git-string "describe" "--tags" "--dirty")))))
491 (magit-git-string "describe"
492 "--tags" "--dirty" "--always")))))
425493 (progn
426494 (push 'static debug)
427495 (when (and static (file-exists-p static))
441509 (push 'dirname debug)
442510 (let ((dirname (file-name-nondirectory
443511 (directory-file-name topdir))))
444 (when (string-match "\\`magit-\\([0-9]\\{8\\}\\.[0-9]*\\)"
445 dirname)
446 (setq magit-version (match-string 1 dirname))))))))
512 (when (string-match "\\`magit-\\([0-9].*\\)" dirname)
513 (setq magit-version (match-string 1 dirname)))))
514 ;; If all else fails, just report the commit hash. It's
515 ;; better than nothing and we cannot do better in the case
516 ;; of e.g. a shallow clone.
517 (progn
518 (push 'hash debug)
519 ;; Same check as above to see if it's really the Magit repo.
520 (when (and (file-exists-p gitdir)
521 (file-exists-p
522 (expand-file-name "../lisp/magit.el" gitdir)))
523 (setq magit-version
524 (let ((default-directory topdir))
525 (magit-git-string "rev-parse" "HEAD"))))))))
447526 (if (stringp magit-version)
448527 (when print-dest
449528 (princ (format "Magit %s, Git %s, Emacs %s, %s"
461540 (setq magit-version 'error)
462541 (when magit-version
463542 (push magit-version debug))
464 (unless (equal (getenv "TRAVIS") "true")
543 (unless (equal (getenv "CI") "true")
465544 ;; The repository is a sparse clone.
466545 (message "Cannot determine Magit's version %S" debug)))
467546 magit-version))
516595 (let ((version (magit-git-version)))
517596 (when (and version
518597 (version< version magit--minimal-git)
519 (not (equal (getenv "TRAVIS") "true")))
598 (not (equal (getenv "CI") "true")))
520599 (display-warning 'magit (format "\
521600 Magit requires Git >= %s, you are using %s.
522601
583662 (require 'magit-imenu)
584663 (require 'magit-bookmark)))
585664
586 (eval-after-load 'bookmark
587 '(require 'magit-bookmark))
665 (with-eval-after-load 'bookmark
666 (require 'magit-bookmark))
588667
589668 (if after-init-time
590669 (progn (magit-startup-asserts)
0 let
1 emacs-overlay = import (builtins.fetchTarball { url = https://github.com/nix-community/emacs-overlay/archive/master.tar.gz; });
2 emacs-ci = import (builtins.fetchTarball { url = https://github.com/purcell/nix-emacs-ci/archive/master.tar.gz; });
3
4 pkgs = import <nixpkgs> { overlays = [ emacs-overlay ]; };
5 in
6 builtins.mapAttrs
7 (version: emacs:
8 (pkgs.emacsPackagesGen emacs).emacsWithPackages
9 (emacsPackages: [
10 emacsPackages.dash
11 emacsPackages.transient
12 ] ++ (with emacsPackages.melpaPackages; [
13 libgit
14 with-editor
15 ])
16 ))
17 emacs-ci
00 ;;; magit-tests.el --- tests for Magit
11
2 ;; Copyright (C) 2011-2018 The Magit Project Contributors
2 ;; Copyright (C) 2011-2021 The Magit Project Contributors
33 ;;
44 ;; License: GPLv3
55
1212 (require 'tramp-sh)
1313
1414 (require 'magit)
15
16 (defun magit-test-init-repo (dir &rest args)
17 (let ((magit-git-global-arguments
18 (nconc (list "-c" "init.defaultBranch=master")
19 magit-git-global-arguments)))
20 (magit-git "init" args dir)))
1521
1622 (defmacro magit-with-test-directory (&rest body)
1723 (declare (indent 0) (debug t))
2228 (push "GIT_AUTHOR_EMAIL=a.u.thor@example.com" process-environment)
2329 (condition-case err
2430 (cl-letf (((symbol-function #'message) (lambda (&rest _))))
25 (let ((default-directory ,dir))
31 (let ((default-directory (file-truename ,dir)))
2632 ,@body))
2733 (error (message "Keeping test directory:\n %s" ,dir)
2834 (signal (car err) (cdr err))))
3036
3137 (defmacro magit-with-test-repository (&rest body)
3238 (declare (indent 0) (debug t))
33 `(magit-with-test-directory (magit-git "init" ".") ,@body))
39 `(magit-with-test-directory (magit-test-init-repo ".") ,@body))
40
41 (defmacro magit-with-bare-test-repository (&rest body)
42 (declare (indent 1) (debug t))
43 `(magit-with-test-directory (magit-test-init-repo "." "--bare") ,@body))
3444
3545 ;;; Git
3646
4555 (ert-deftest magit-toplevel:basic ()
4656 (let ((find-file-visit-truename nil))
4757 (magit-with-test-directory
48 (magit-git "init" "repo")
58 (magit-test-init-repo "repo")
4959 (magit-test-magit-toplevel)
5060 (should (equal (magit-toplevel "repo/.git/")
5161 (expand-file-name "repo/")))
6777 ;; require a functioning `sudo'.
6878 (sudo-method (cdr (assoc "sudo" tramp-methods)))
6979 ((cdr (assq 'tramp-login-program sudo-method))
70 (list shell-file-name))
80 (list (if (file-executable-p "/bin/sh")
81 "/bin/sh"
82 shell-file-name)))
7183 ((cdr (assq 'tramp-login-args sudo-method)) nil))
7284 (magit-with-test-directory
7385 (setq default-directory
7486 (concat (format "/sudo:%s@localhost:" (user-login-name))
7587 default-directory))
76 (magit-git "init" "repo")
88 (magit-test-init-repo "repo")
7789 (magit-test-magit-toplevel)
7890 (should (equal (magit-toplevel "repo/.git/")
7991 (expand-file-name "repo/")))
8799 (ert-deftest magit-toplevel:submodule ()
88100 (let ((find-file-visit-truename nil))
89101 (magit-with-test-directory
90 (magit-git "init" "remote")
102 (magit-test-init-repo "remote")
91103 (let ((default-directory (expand-file-name "remote/")))
92104 (magit-git "commit" "-m" "init" "--allow-empty"))
93 (magit-git "init" "super")
105 (magit-test-init-repo "super")
94106 (setq default-directory (expand-file-name "super/"))
95107 (magit-git "submodule" "add" "../remote" "repo/")
96108 (magit-test-magit-toplevel)
132144 (should (equal (magit-toplevel "subdir-link-indirect")
133145 (expand-file-name "repo/")))
134146 ;; wrap/*link
135 (magit-git "init" "wrap")
147 (magit-test-init-repo "wrap")
136148 (make-symbolic-link "../repo" "wrap/repo-link")
137149 (make-symbolic-link "../repo/subdir" "wrap/subdir-link")
138150 (make-symbolic-link "../repo/subdir/subsubdir" "wrap/subsubdir-link")
153165
154166 (ert-deftest magit-get ()
155167 (magit-with-test-directory
156 (magit-git "init" "remote")
168 (magit-test-init-repo "remote")
157169 (let ((default-directory (expand-file-name "remote/")))
158170 (magit-git "commit" "-m" "init" "--allow-empty")
159171 (magit-git "config" "a.b" "remote-value"))
160 (magit-git "init" "super")
172 (magit-test-init-repo "super")
161173 (setq default-directory (expand-file-name "super/"))
162174 ;; Some tricky cases:
163175 ;; Multiple config values.
323335 '(unpushed . "@{upstream}..")
324336 (magit-rev-parse "--short" "master")))))
325337
338 ;;; libgit
339
340 (ert-deftest magit-in-bare-repo ()
341 "Test `magit-bare-repo-p' in a bare repository."
342 (magit-with-bare-test-repository
343 (should (magit-bare-repo-p))))
344
345 (ert-deftest magit-in-non-bare-repo ()
346 "Test `magit-bare-repo-p' in a non-bare repository."
347 (magit-with-test-repository
348 (should-not (magit-bare-repo-p))))
349
326350 ;;; Utils
327351
328352 (ert-deftest magit-utils:add-face-text-property ()