Klimi's new dotfiles with stow.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

319 line
13 KiB

4 年之前
  1. ;;; magit-push.el --- update remote objects and refs -*- lexical-binding: t -*-
  2. ;; Copyright (C) 2008-2019 The Magit Project Contributors
  3. ;;
  4. ;; You should have received a copy of the AUTHORS.md file which
  5. ;; lists all contributors. If not, see http://magit.vc/authors.
  6. ;; Author: Jonas Bernoulli <jonas@bernoul.li>
  7. ;; Maintainer: Jonas Bernoulli <jonas@bernoul.li>
  8. ;; Magit is free software; you can redistribute it and/or modify it
  9. ;; under the terms of the GNU General Public License as published by
  10. ;; the Free Software Foundation; either version 3, or (at your option)
  11. ;; any later version.
  12. ;;
  13. ;; Magit is distributed in the hope that it will be useful, but WITHOUT
  14. ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  15. ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
  16. ;; License for more details.
  17. ;;
  18. ;; You should have received a copy of the GNU General Public License
  19. ;; along with Magit. If not, see http://www.gnu.org/licenses.
  20. ;;; Commentary:
  21. ;; This library implements push commands.
  22. ;;; Code:
  23. (eval-when-compile
  24. (require 'subr-x))
  25. (require 'magit)
  26. ;;; Commands
  27. ;;;###autoload (autoload 'magit-push "magit-push" nil t)
  28. (define-transient-command magit-push ()
  29. "Push to another repository."
  30. :man-page "git-push"
  31. ["Arguments"
  32. ("-f" "Force with lease" (nil "--force-with-lease"))
  33. ("-F" "Force" ("-f" "--force"))
  34. ("-h" "Disable hooks" "--no-verify")
  35. ("-n" "Dry run" ("-n" "--dry-run"))
  36. (5 "-u" "Set upstream" "--set-upstream")
  37. (7 "-t" "Follow tags" "--follow-tags")]
  38. [:if magit-get-current-branch
  39. :description (lambda ()
  40. (format (propertize "Push %s to" 'face 'transient-heading)
  41. (propertize (magit-get-current-branch)
  42. 'face 'magit-branch-local)))
  43. ("p" magit-push-current-to-pushremote)
  44. ("u" magit-push-current-to-upstream)
  45. ("e" "elsewhere" magit-push-current)]
  46. ["Push"
  47. [("o" "another branch" magit-push-other)
  48. ("r" "explicit refspecs" magit-push-refspecs)
  49. ("m" "matching branches" magit-push-matching)]
  50. [("T" "a tag" magit-push-tag)
  51. ("t" "all tags" magit-push-tags)]]
  52. ["Configure"
  53. ("C" "Set variables..." magit-branch-configure)])
  54. (defun magit-push-arguments ()
  55. (transient-args 'magit-push))
  56. (defun magit-git-push (branch target args)
  57. (run-hooks 'magit-credential-hook)
  58. ;; If the remote branch already exists, then we do not have to
  59. ;; qualify the target, which we prefer to avoid doing because
  60. ;; using the default namespace is wrong in obscure cases.
  61. (pcase-let ((namespace (if (magit-get-tracked target) "" "refs/heads/"))
  62. (`(,remote . ,target)
  63. (magit-split-branch-name target)))
  64. (magit-run-git-async "push" "-v" args remote
  65. (format "%s:%s%s" branch namespace target))))
  66. ;;;###autoload (autoload 'magit-push-current-to-pushremote "magit-push" nil t)
  67. (define-suffix-command magit-push-current-to-pushremote (args)
  68. "Push the current branch to its push-remote.
  69. When the push-remote is not configured, then read the push-remote
  70. from the user, set it, and then push to it. With a prefix
  71. argument the push-remote can be changed before pushed to it."
  72. :if 'magit-get-current-branch
  73. :description 'magit-push--pushbranch-description
  74. (interactive (list (magit-push-arguments)))
  75. (pcase-let ((`(,branch ,remote)
  76. (magit--select-push-remote "push there")))
  77. (run-hooks 'magit-credential-hook)
  78. (magit-run-git-async "push" "-v" args remote
  79. (format "refs/heads/%s:refs/heads/%s"
  80. branch branch)))) ; see #3847 and #3872
  81. (defun magit-push--pushbranch-description ()
  82. (let* ((branch (magit-get-current-branch))
  83. (target (magit-get-push-branch branch t))
  84. (remote (magit-get-push-remote branch))
  85. (v (magit--push-remote-variable branch t)))
  86. (cond
  87. (target)
  88. ((member remote (magit-list-remotes))
  89. (format "%s, creating it"
  90. (magit--propertize-face (concat remote "/" branch)
  91. 'magit-branch-remote)))
  92. (remote
  93. (format "%s, replacing invalid" v))
  94. (t
  95. (format "%s, setting that" v)))))
  96. ;;;###autoload (autoload 'magit-push-current-to-upstream "magit-push" nil t)
  97. (define-suffix-command magit-push-current-to-upstream (args)
  98. "Push the current branch to its upstream branch.
  99. With a prefix argument or when the upstream is either not
  100. configured or unusable, then let the user first configure
  101. the upstream."
  102. :if 'magit-get-current-branch
  103. :description 'magit-push--upstream-description
  104. (interactive (list (magit-push-arguments)))
  105. (let* ((branch (or (magit-get-current-branch)
  106. (user-error "No branch is checked out")))
  107. (remote (magit-get "branch" branch "remote"))
  108. (merge (magit-get "branch" branch "merge")))
  109. (when (or current-prefix-arg
  110. (not (or (magit-get-upstream-branch branch)
  111. (magit--unnamed-upstream-p remote merge)
  112. (magit--valid-upstream-p remote merge))))
  113. (let* ((branches (-union (--map (concat it "/" branch)
  114. (magit-list-remotes))
  115. (magit-list-remote-branch-names)))
  116. (upstream (magit-completing-read
  117. (format "Set upstream of %s and push there" branch)
  118. branches nil nil nil 'magit-revision-history
  119. (or (car (member (magit-remote-branch-at-point) branches))
  120. (car (member "origin/master" branches)))))
  121. (upstream (or (magit-get-tracked upstream)
  122. (magit-split-branch-name upstream))))
  123. (setq remote (car upstream))
  124. (setq merge (cdr upstream))
  125. (unless (string-prefix-p "refs/" merge)
  126. ;; User selected a non-existent remote-tracking branch.
  127. ;; It is very likely, but not certain, that this is the
  128. ;; correct thing to do. It is even more likely that it
  129. ;; is what the user wants to happen.
  130. (setq merge (concat "refs/heads/" merge))))
  131. (cl-pushnew "--set-upstream" args :test #'equal))
  132. (run-hooks 'magit-credential-hook)
  133. (magit-run-git-async "push" "-v" args remote (concat branch ":" merge))))
  134. (defun magit-push--upstream-description ()
  135. (when-let ((branch (magit-get-current-branch)))
  136. (or (magit-get-upstream-branch branch)
  137. (let ((remote (magit-get "branch" branch "remote"))
  138. (merge (magit-get "branch" branch "merge"))
  139. (u (magit--propertize-face "@{upstream}" 'bold)))
  140. (cond
  141. ((magit--unnamed-upstream-p remote merge)
  142. (format "%s as %s"
  143. (magit--propertize-face remote 'bold)
  144. (magit--propertize-face merge 'magit-branch-remote)))
  145. ((magit--valid-upstream-p remote merge)
  146. (format "%s creating %s"
  147. (magit--propertize-face remote 'magit-branch-remote)
  148. (magit--propertize-face merge 'magit-branch-remote)))
  149. ((or remote merge)
  150. (concat u ", creating it and replacing invalid"))
  151. (t
  152. (concat u ", creating it")))))))
  153. ;;;###autoload
  154. (defun magit-push-current (target args)
  155. "Push the current branch to a branch read in the minibuffer."
  156. (interactive
  157. (--if-let (magit-get-current-branch)
  158. (list (magit-read-remote-branch (format "Push %s to" it)
  159. nil nil it 'confirm)
  160. (magit-push-arguments))
  161. (user-error "No branch is checked out")))
  162. (magit-git-push (magit-get-current-branch) target args))
  163. ;;;###autoload
  164. (defun magit-push-other (source target args)
  165. "Push an arbitrary branch or commit somewhere.
  166. Both the source and the target are read in the minibuffer."
  167. (interactive
  168. (let ((source (magit-read-local-branch-or-commit "Push")))
  169. (list source
  170. (magit-read-remote-branch
  171. (format "Push %s to" source) nil
  172. (if (magit-local-branch-p source)
  173. (or (magit-get-push-branch source)
  174. (magit-get-upstream-branch source))
  175. (and (magit-rev-ancestor-p source "HEAD")
  176. (or (magit-get-push-branch)
  177. (magit-get-upstream-branch))))
  178. source 'confirm)
  179. (magit-push-arguments))))
  180. (magit-git-push source target args))
  181. (defvar magit-push-refspecs-history nil)
  182. ;;;###autoload
  183. (defun magit-push-refspecs (remote refspecs args)
  184. "Push one or multiple REFSPECS to a REMOTE.
  185. Both the REMOTE and the REFSPECS are read in the minibuffer. To
  186. use multiple REFSPECS, separate them with commas. Completion is
  187. only available for the part before the colon, or when no colon
  188. is used."
  189. (interactive
  190. (list (magit-read-remote "Push to remote")
  191. (split-string (magit-completing-read-multiple
  192. "Push refspec,s"
  193. (cons "HEAD" (magit-list-local-branch-names))
  194. nil nil 'magit-push-refspecs-history)
  195. crm-default-separator t)
  196. (magit-push-arguments)))
  197. (run-hooks 'magit-credential-hook)
  198. (magit-run-git-async "push" "-v" args remote refspecs))
  199. ;;;###autoload
  200. (defun magit-push-matching (remote &optional args)
  201. "Push all matching branches to another repository.
  202. If multiple remotes exist, then read one from the user.
  203. If just one exists, use that without requiring confirmation."
  204. (interactive (list (magit-read-remote "Push matching branches to" nil t)
  205. (magit-push-arguments)))
  206. (run-hooks 'magit-credential-hook)
  207. (magit-run-git-async "push" "-v" args remote ":"))
  208. ;;;###autoload
  209. (defun magit-push-tags (remote &optional args)
  210. "Push all tags to another repository.
  211. If only one remote exists, then push to that. Otherwise prompt
  212. for a remote, offering the remote configured for the current
  213. branch as default."
  214. (interactive (list (magit-read-remote "Push tags to remote" nil t)
  215. (magit-push-arguments)))
  216. (run-hooks 'magit-credential-hook)
  217. (magit-run-git-async "push" remote "--tags" args))
  218. ;;;###autoload
  219. (defun magit-push-tag (tag remote &optional args)
  220. "Push a tag to another repository."
  221. (interactive
  222. (let ((tag (magit-read-tag "Push tag")))
  223. (list tag (magit-read-remote (format "Push %s to remote" tag) nil t)
  224. (magit-push-arguments))))
  225. (run-hooks 'magit-credential-hook)
  226. (magit-run-git-async "push" remote tag args))
  227. ;;;###autoload
  228. (defun magit-push-implicitly (args)
  229. "Push somewhere without using an explicit refspec.
  230. This command simply runs \"git push -v [ARGS]\". ARGS are the
  231. arguments specified in the popup buffer. No explicit refspec
  232. arguments are used. Instead the behavior depends on at least
  233. these Git variables: `push.default', `remote.pushDefault',
  234. `branch.<branch>.pushRemote', `branch.<branch>.remote',
  235. `branch.<branch>.merge', and `remote.<remote>.push'.
  236. The function `magit-push-implicitly--desc' attempts to predict
  237. what this command will do. The value it returns is displayed in
  238. the popup buffer."
  239. (interactive (list (magit-push-arguments)))
  240. (run-hooks 'magit-credential-hook)
  241. (magit-run-git-async "push" "-v" args))
  242. (defun magit-push-implicitly--desc ()
  243. (let ((default (magit-get "push.default")))
  244. (unless (equal default "nothing")
  245. (or (when-let ((remote (or (magit-get-remote)
  246. (magit-remote-p "origin")))
  247. (refspec (magit-get "remote" remote "push")))
  248. (format "%s using %s"
  249. (magit--propertize-face remote 'magit-branch-remote)
  250. (magit--propertize-face refspec 'bold)))
  251. (--when-let (and (not (magit-get-push-branch))
  252. (magit-get-upstream-branch))
  253. (format "%s aka %s\n"
  254. (magit-branch-set-face it)
  255. (magit--propertize-face "@{upstream}" 'bold)))
  256. (--when-let (magit-get-push-branch)
  257. (format "%s aka %s\n"
  258. (magit-branch-set-face it)
  259. (magit--propertize-face "pushRemote" 'bold)))
  260. (--when-let (magit-get-@{push}-branch)
  261. (format "%s aka %s\n"
  262. (magit-branch-set-face it)
  263. (magit--propertize-face "@{push}" 'bold)))
  264. (format "using %s (%s is %s)\n"
  265. (magit--propertize-face "git push" 'bold)
  266. (magit--propertize-face "push.default" 'bold)
  267. (magit--propertize-face default 'bold))))))
  268. ;;;###autoload
  269. (defun magit-push-to-remote (remote args)
  270. "Push to REMOTE without using an explicit refspec.
  271. The REMOTE is read in the minibuffer.
  272. This command simply runs \"git push -v [ARGS] REMOTE\". ARGS
  273. are the arguments specified in the popup buffer. No refspec
  274. arguments are used. Instead the behavior depends on at least
  275. these Git variables: `push.default', `remote.pushDefault',
  276. `branch.<branch>.pushRemote', `branch.<branch>.remote',
  277. `branch.<branch>.merge', and `remote.<remote>.push'."
  278. (interactive (list (magit-read-remote "Push to remote")
  279. (magit-push-arguments)))
  280. (run-hooks 'magit-credential-hook)
  281. (magit-run-git-async "push" "-v" args remote))
  282. (defun magit-push-to-remote--desc ()
  283. (format "using %s\n" (magit--propertize-face "git push <remote>" 'bold)))
  284. ;;; _
  285. (provide 'magit-push)
  286. ;;; magit-push.el ends here