fordon_greeman / voidfiles

Branch: main
Switch branches/tags
main
theidioticdev add emacs 2079ec5 1d ago
222 lines · 8.6 KB Raw Blame History
1 ;;; magit-pull.el --- Update local objects and refs -*- lexical-binding:t -*-
2
3 ;; Copyright (C) 2008-2026 The Magit Project Contributors
4
5 ;; Author: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
6 ;; Maintainer: Jonas Bernoulli <emacs.magit@jonas.bernoulli.dev>
7
8 ;; SPDX-License-Identifier: GPL-3.0-or-later
9
10 ;; Magit is free software: you can redistribute it and/or modify it
11 ;; under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation, either version 3 of the License, or
13 ;; (at your option) any later version.
14 ;;
15 ;; Magit is distributed in the hope that it will be useful, but WITHOUT
16 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
18 ;; License for more details.
19 ;;
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with Magit. If not, see <https://www.gnu.org/licenses/>.
22
23 ;;; Commentary:
24
25 ;; This library implements pull commands.
26
27 ;;; Code:
28
29 (require 'magit)
30
31 ;;; Options
32
33 (defcustom magit-pull-or-fetch nil
34 "Whether `magit-pull' also offers some fetch suffixes."
35 :package-version '(magit . "3.0.0")
36 :group 'magit-commands
37 :type 'boolean)
38
39 ;;; Commands
40
41 ;;;###autoload(autoload 'magit-pull "magit-pull" nil t)
42 (transient-define-prefix magit-pull ()
43 "Pull from another repository."
44 :man-page "git-pull"
45 :incompatible
46 '(("--ff-only" "--rebase=true" "--rebase=merges" "--rebase=interactive"))
47 [:description
48 (lambda () (if magit-pull-or-fetch "Pull arguments" "Arguments"))
49 ("-f" "Fast-forward only" "--ff-only")
50 ("-r" magit-pull:--rebase)
51 ("-A" "Autostash" "--autostash" :level 7)
52 ("-F" "Force" ("-f" "--force"))]
53 [:description
54 (lambda ()
55 (if-let ((branch (magit-get-current-branch)))
56 (concat
57 (propertize "Pull into " 'face 'transient-heading)
58 (propertize branch 'face 'magit-branch-local)
59 (propertize " from" 'face 'transient-heading))
60 (propertize "Pull from" 'face 'transient-heading)))
61 ("p" magit-pull-from-pushremote)
62 ("u" magit-pull-from-upstream)
63 ("e" "elsewhere" magit-pull-branch)]
64 [:description
65 (lambda ()
66 (format (propertize "Pull into %s from" 'face 'transient-heading)
67 (magit-get-upstream-branch)))
68 ("U" magit-pull-into-upstream :level 7)]
69 ["Fetch from"
70 :if-non-nil magit-pull-or-fetch
71 ("f" "remotes" magit-fetch-all-no-prune)
72 ("F" "remotes and prune" magit-fetch-all-prune)]
73 ["Fetch"
74 :if-non-nil magit-pull-or-fetch
75 ("o" "another branch" magit-fetch-branch)
76 ("s" "explicit refspec" magit-fetch-refspec)
77 ("m" "submodules" magit-fetch-modules)]
78 ["Configure"
79 ("r" magit-branch.<branch>.rebase :if magit-get-current-branch)
80 ("C" "variables..." magit-branch-configure)]
81 (interactive)
82 (transient-setup 'magit-pull nil nil :scope (magit-get-current-branch)))
83
84 (defun magit-pull-arguments ()
85 (transient-args 'magit-pull))
86
87 (transient-define-infix magit-pull:--rebase ()
88 :class 'transient-option
89 :description "Rebase local commits"
90 :argument "--rebase="
91 :shortarg "-r"
92 :choices '("true" "merges" "interactive" "false"))
93
94 ;;;###autoload(autoload 'magit-pull-from-pushremote "magit-pull" nil t)
95 (transient-define-suffix magit-pull-from-pushremote (args)
96 "Pull from the push-remote of the current branch.
97
98 With a prefix argument or when the push-remote is either not
99 configured or unusable, then let the user first configure the
100 push-remote."
101 :if #'magit-get-current-branch
102 :description #'magit-pull--pushbranch-description
103 (interactive (list (magit-pull-arguments)))
104 (pcase-let ((`(,branch ,remote)
105 (magit--select-push-remote "pull from there")))
106 (run-hooks 'magit-credential-hook)
107 (magit-run-git-with-editor "pull" args remote branch)))
108
109 (defun magit-pull--pushbranch-description ()
110 ;; Also used by `magit-rebase-onto-pushremote'.
111 (let* ((branch (magit-get-current-branch))
112 (target (magit-get-push-branch branch t))
113 (remote (magit-get-push-remote branch))
114 (v (magit--push-remote-variable branch t)))
115 (cond (target)
116 ((member remote (magit-list-remotes))
117 (format "%s, replacing non-existent" v))
118 (remote
119 (format "%s, replacing invalid" v))
120 ((format "%s, setting that" v)))))
121
122 ;;;###autoload(autoload 'magit-pull-from-upstream "magit-pull" nil t)
123 (transient-define-suffix magit-pull-from-upstream (args)
124 "Pull from the upstream of the current branch.
125
126 With a prefix argument or when the upstream is either not
127 configured or unusable, then let the user first configure
128 the upstream."
129 :if #'magit-get-current-branch
130 :description #'magit-pull--upstream-description
131 (interactive (list (magit-pull-arguments)))
132 (let* ((branch (or (magit-get-current-branch)
133 (user-error "No branch is checked out")))
134 (remote (magit-get "branch" branch "remote"))
135 (merge (magit-get "branch" branch "merge")))
136 (when (or current-prefix-arg
137 (not (or (magit-get-upstream-branch branch)
138 (magit--unnamed-upstream-p remote merge))))
139 (magit-set-upstream-branch
140 branch (magit-read-upstream-branch
141 branch (format "Set upstream of %s and pull from there" branch)))
142 (setq remote (magit-get "branch" branch "remote"))
143 (setq merge (magit-get "branch" branch "merge")))
144 (run-hooks 'magit-credential-hook)
145 (magit-run-git-with-editor "pull" args remote merge)))
146
147 (defun magit-pull--upstream-description ()
148 (and-let ((branch (magit-get-current-branch)))
149 (or (magit-get-upstream-branch branch)
150 (let ((remote (magit-get "branch" branch "remote"))
151 (merge (magit-get "branch" branch "merge"))
152 (u (magit--propertize-face "@{upstream}" 'bold)))
153 (cond
154 ((magit--unnamed-upstream-p remote merge)
155 (format "%s of %s"
156 (magit--propertize-face merge 'magit-branch-remote)
157 (magit--propertize-face remote 'bold)))
158 ((magit--valid-upstream-p remote merge)
159 (concat u ", replacing non-existent"))
160 ((or remote merge)
161 (concat u ", replacing invalid"))
162 ((concat u ", setting that")))))))
163
164 ;;;###autoload(autoload 'magit-pull-into-upstream "magit-pull" nil t)
165 (transient-define-suffix magit-pull-into-upstream ()
166 "Update the upstream of the current branch from its own upstream.
167
168 If the upstream of the current branch is a local branch, and the
169 upstream of that is a remote branch, then update the local upstream.
170 This makes it possible to update the upstream branch, without having
171 to first check it out."
172 :if #'magit-pull--upstreams
173 :description (##cdr (magit-pull--upstreams))
174 (interactive)
175 (if-let ((upstreams (magit-pull--upstreams)))
176 (pcase-let* ((`(,up1 . ,up2) upstreams)
177 (`(,remote . ,branch) (magit-split-branch-name up2)))
178 (magit-run-git-async "fetch" remote branch)
179 (set-process-sentinel
180 magit-this-process
181 (lambda (process _event)
182 (when (memq (process-status process) '(exit signal))
183 (magit-run-git-async "update-ref" (concat "refs/heads/" up1)
184 "FETCH_HEAD")))))
185 (user-error "Cannot perform background update of upstream branch")))
186
187 (defun magit-pull--upstreams ()
188 (and-let* ((up1 (magit-get-upstream-branch))
189 (_ (magit-local-branch-p up1))
190 (up2 (magit-get-upstream-branch up1))
191 (_ (magit-remote-branch-p up2)))
192 (cons up1 up2)))
193
194 ;;;###autoload
195 (defun magit-pull-branch (source args)
196 "Pull from a branch read in the minibuffer."
197 (interactive (list (magit-read-remote-branch "Pull" nil nil nil t)
198 (magit-pull-arguments)))
199 (run-hooks 'magit-credential-hook)
200 (pcase-let ((`(,remote . ,branch)
201 (magit-get-tracked source)))
202 (magit-run-git-with-editor "pull" args remote branch)))
203
204 ;;; _
205 (provide 'magit-pull)
206 ;; Local Variables:
207 ;; read-symbol-shorthands: (
208 ;; ("and$" . "cond-let--and$")
209 ;; ("thread$" . "cond-let--thread$")
210 ;; ("when$" . "cond-let--when$")
211 ;; ("and-let*" . "cond-let--and-let*")
212 ;; ("and-let" . "cond-let--and-let")
213 ;; ("if-let*" . "cond-let--if-let*")
214 ;; ("if-let" . "cond-let--if-let")
215 ;; ("when-let*" . "cond-let--when-let*")
216 ;; ("when-let" . "cond-let--when-let")
217 ;; ("while-let*" . "cond-let--while-let*")
218 ;; ("while-let" . "cond-let--while-let")
219 ;; ("match-string" . "match-string")
220 ;; ("match-str" . "match-string-no-properties"))
221 ;; End:
222 ;;; magit-pull.el ends here