From 93ea61cd294236cb71e80ac93bef2b42688d5fa7 Mon Sep 17 00:00:00 2001 From: Jonas Bernoulli Date: Thu, 7 Dec 2017 21:46:00 +0100 Subject: [PATCH] magit-branch-maybe-delete-pr-remote: new function --- Documentation/RelNotes/2.12.0.txt | 5 +++++ Documentation/magit.org | 22 ++++++++++++++++++-- Documentation/magit.texi | 24 ++++++++++++++++++++-- lisp/magit-branch.el | 34 +++++++++++++++++++++++++++---- lisp/magit-utils.el | 8 ++++++++ 5 files changed, 85 insertions(+), 8 deletions(-) diff --git a/Documentation/RelNotes/2.12.0.txt b/Documentation/RelNotes/2.12.0.txt index 7f405dc9..cf9e1269 100644 --- a/Documentation/RelNotes/2.12.0.txt +++ b/Documentation/RelNotes/2.12.0.txt @@ -195,6 +195,11 @@ Changes since v2.11.0 support Github, but other Git forges will be supported in the future. #3134 +* The command `magit-branch-delete' now offers to also delete the + corresponding remote after deleting a local branch that was created + with `magit-branch-pull-request' or magit-checkout-pull-request', + provided that remote has no other tracking branches. #3134 + Fixes since v2.11.0 ------------------- diff --git a/Documentation/magit.org b/Documentation/magit.org index da2e10ae..14f65cf1 100644 --- a/Documentation/magit.org +++ b/Documentation/magit.org @@ -7,7 +7,7 @@ #+TEXINFO_DIR_CATEGORY: Emacs #+TEXINFO_DIR_TITLE: Magit: (magit). #+TEXINFO_DIR_DESC: Using Git from Emacs with Magit. -#+SUBTITLE: for version 2.11.0 (2.11.0-301-gce31549d7+1) +#+SUBTITLE: for version 2.11.0 (2.11.0-302-gac281d7f1+1) #+BIND: ox-texinfo+-before-export-hook ox-texinfo+-update-version-strings #+TEXINFO_DEFFN: t @@ -22,7 +22,7 @@ directly from within Emacs. While many fine Git clients exist, only Magit and Git itself deserve to be called porcelains. #+BEGIN_QUOTE -This manual is for Magit version 2.11.0 (2.11.0-301-gce31549d7+1). +This manual is for Magit version 2.11.0 (2.11.0-302-gac281d7f1+1). Copyright (C) 2015-2017 Jonas Bernoulli @@ -1275,6 +1275,13 @@ telling Magit to ask fewer questions. (or selecting another branch), but when a branch has not been merged yet, also make sure the user is aware of that. + - ~delete-pr-branch~ When deleting a branch that was created from a + pull request and if no other branches still exist on that + remote, then `magit-branch-delete' offers to delete the remote + as well. This should be safe because it only happens if no + other refs exist in the remotes namespace, and you can recreate + the remote if necessary. + - ~drop-stashes~ Dropping a stash is dangerous because Git stores stashes in the reflog. Once a stash is removed, there is no going back without using low-level recovery tools provided by @@ -4125,6 +4132,17 @@ features are available from separate popups. the variable ~branch..pullRequestRemote~ is set to the fork remote. + When you later delete the local pull-request branch, then you are + offered to also delete the corresponding remote, provided it is not + the upstream remote and that the tracking branch that corresponds to + the deleted branch is the only remaining tracked branch. If you + don't confirm, then only the tracking branch itself is deleted in + addition to the local branch. + + Do not delete the tracking branch instead of the local branch. The + cleanup mentioned in the previous paragraph is not performed if you + do that. + - Key: b p, magit-checkout-pull-request This command creates and configures a new branch from a pull diff --git a/Documentation/magit.texi b/Documentation/magit.texi index 070511b6..d2ba89ac 100644 --- a/Documentation/magit.texi +++ b/Documentation/magit.texi @@ -30,7 +30,7 @@ General Public License for more details. @finalout @titlepage @title Magit User Manual -@subtitle for version 2.11.0 (2.11.0-301-gce31549d7+1) +@subtitle for version 2.11.0 (2.11.0-302-gac281d7f1+1) @author Jonas Bernoulli @page @vskip 0pt plus 1filll @@ -52,7 +52,7 @@ directly from within Emacs. While many fine Git clients exist, only Magit and Git itself deserve to be called porcelains. @quotation -This manual is for Magit version 2.11.0 (2.11.0-301-gce31549d7+1). +This manual is for Magit version 2.11.0 (2.11.0-302-gac281d7f1+1). Copyright (C) 2015-2017 Jonas Bernoulli @@ -1805,6 +1805,15 @@ confirm the deletion of a branch by accepting the default choice merged yet, also make sure the user is aware of that. +@item +@code{delete-pr-branch} When deleting a branch that was created from a +pull request and if no other branches still exist on that +remote, then `magit-branch-delete' offers to delete the remote +as well. This should be safe because it only happens if no +other refs exist in the remotes namespace, and you can recreate +the remote if necessary. + + @item @code{drop-stashes} Dropping a stash is dangerous because Git stores stashes in the reflog. Once a stash is removed, there is no @@ -5597,6 +5606,17 @@ the variable @code{branch..pullRequestRemote} is set to the fork remote. @end itemize +When you later delete the local pull-request branch, then you are +offered to also delete the corresponding remote, provided it is not +the upstream remote and that the tracking branch that corresponds to +the deleted branch is the only remaining tracked branch. If you +don't confirm, then only the tracking branch itself is deleted in +addition to the local branch. + +Do not delete the tracking branch instead of the local branch. The +cleanup mentioned in the previous paragraph is not performed if you +do that. + @kindex b p @cindex magit-checkout-pull-request @item @kbd{b p} @tie{}@tie{}@tie{}@tie{}(@code{magit-checkout-pull-request}) diff --git a/lisp/magit-branch.el b/lisp/magit-branch.el index 85c801f8..274aa4e1 100644 --- a/lisp/magit-branch.el +++ b/lisp/magit-branch.el @@ -537,8 +537,7 @@ those, otherwise prompt for a single branch to be deleted, defaulting to the branch at point." ;; One would expect this to be a command as simple as, for example, ;; `magit-branch-rename'; but it turns out everyone wants to squeeze - ;; a bit of extra functionality into this one. And once it's there, - ;; you cannot remove it anymore. (I tried, it causes protests.) + ;; a bit of extra functionality into this one, including myself. (interactive (let ((branches (magit-region-values 'branch t)) (force current-prefix-arg)) @@ -582,8 +581,9 @@ defaulting to the branch at point." magit-this-process (apply-partially 'magit-delete-remote-branch-sentinel refs)))) ((> (length branches) 1) - (magit-run-git "branch" (if force "-D" "-d") - (delete (magit-get-current-branch) branches))) + (setq branches (delete (magit-get-current-branch) branches)) + (mapc 'magit-branch-maybe-delete-pr-remote branches) + (magit-run-git "branch" (if force "-D" "-d") branches)) (t ; And now for something completely different. (let* ((branch (car branches)) (prompt (format "Branch %s is checked out. " branch))) @@ -615,10 +615,36 @@ defaulting to the branch at point." (magit-call-git "checkout" "master")) (`abort (user-error "Abort"))) (setq force t)) + (magit-branch-maybe-delete-pr-remote branch) (magit-run-git "branch" (if force "-D" "-d") branch)))))) (put 'magit-branch-delete 'interactive-only t) +(defun magit-branch-maybe-delete-pr-remote (branch) + (-when-let (remote (magit-get "branch" branch "pullRequestRemote")) + (let* ((variable (format "remote.%s.fetch" remote)) + (refspecs (magit-get-all variable))) + (unless (member (format "+refs/heads/*:refs/remotes/%s/*" remote) + refspecs) + (let ((refspec + (if (equal (magit-get "branch" branch "pushRemote") remote) + (format "+refs/heads/%s:refs/remotes/%s/%s" + branch remote branch) + (let ((merge (magit-get "branch" branch "merge"))) + (and merge + (string-prefix-p "refs/heads/" merge) + (setq merge (substring merge 11)) + (format "+refs/heads/%s:refs/remotes/%s/%s" + merge remote merge)))))) + (when (member refspec refspecs) + (if (and (= (length refspecs) 1) + (magit-confirm 'delete-pr-remote + (format "Also delete remote %s (%s)" remote + "no pull-request branch remains"))) + (magit-call-git "remote" "rm" remote) + (magit-call-git "config" "--unset" variable + (regexp-quote refspec))))))))) + (defun magit-delete-remote-branch-sentinel (refs process event) (when (memq (process-status process) '(exit signal)) (if (= (process-exit-status process) 0) diff --git a/lisp/magit-utils.el b/lisp/magit-utils.el index 675a7e95..f6cd1a24 100644 --- a/lisp/magit-utils.el +++ b/lisp/magit-utils.el @@ -142,6 +142,7 @@ The value has the form ((COMMAND nil|PROMPT DEFAULT)...). (const abort-merge) (const merge-dirty) (const drop-stashes) (const resect-bisect) (const kill-process) (const delete-unmerged-branch) + (const delete-pr-branch) (const stage-all-changes) (const unstage-all-changes) (const safe-with-wip))) @@ -213,6 +214,13 @@ References: choice (or selecting another branch), but when a branch has not been merged yet, also make sure the user is aware of that. + `delete-pr-branch' When deleting a branch that was created from + a pull request and if no other branches still exist on that + remote, then `magit-branch-delete' offers to delete the remote + as well. This should be safe because it only happens if no + other refs exist in the remotes namespace, and you can recreate + the remote if necessary. + `drop-stashes' Dropping a stash is dangerous because Git stores stashes in the reflog. Once a stash is removed, there is no going back without using low-level recovery tools provided by -- 2.20.1