mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-02-16 09:14:18 +00:00
New delete-revision VC backend API function (bug#79408)
* lisp/vc/vc-git.el (vc-git--assert-revision-on-branch): New function, factored out. (vc-git-revision-published-p): Use it. (vc-git-delete-revision): * lisp/vc/vc-hg.el (vc-hg-delete-revision): New functions. * lisp/vc/vc.el: Specify delete-revision backend API function (bug#79408).
This commit is contained in:
parent
bf02d7e19b
commit
3dc022a023
3 changed files with 103 additions and 5 deletions
|
|
@ -2208,15 +2208,19 @@ This requires git 1.8.4 or later, for the \"-L\" option of \"git log\"."
|
|||
(format "Summary: %s\n(cherry picked from commit %s)\n"
|
||||
comment rev))))
|
||||
|
||||
(defun vc-git--assert-revision-on-branch (rev branch)
|
||||
"Signal an error unless REV is on BRANCH."
|
||||
;; 'git branch --contains' is a porcelain command whose output could
|
||||
;; change in the future.
|
||||
(unless (zerop (vc-git-command nil 1 nil "merge-base"
|
||||
"--is-ancestor" rev branch))
|
||||
(error "Revision %s does not exist on branch %s" rev branch)))
|
||||
|
||||
(defun vc-git-revision-published-p (rev)
|
||||
"Whether we think REV has been pushed such that it is public history.
|
||||
Considers only the current branch. Does not fetch."
|
||||
(let ((branch (vc-git--current-branch)))
|
||||
;; 'git branch --contains' is a porcelain command whose output could
|
||||
;; change in the future.
|
||||
(unless (zerop (vc-git-command nil 1 nil "merge-base"
|
||||
"--is-ancestor" rev branch))
|
||||
(error "Revision %s does not exist on branch %s" rev branch))
|
||||
(vc-git--assert-revision-on-branch rev branch)
|
||||
(and
|
||||
;; BRANCH has an upstream.
|
||||
(with-temp-buffer
|
||||
|
|
@ -2311,6 +2315,23 @@ Rebase may --autosquash your other squash!/fixup!/amend!; proceed?")))
|
|||
(vc-git-command nil 0 nil "rebase" "--autostash" "--autosquash" "-i"
|
||||
(format "%s~1" rev))))
|
||||
|
||||
(defun vc-git-delete-revision (rev)
|
||||
"Rebase current branch to remove REV."
|
||||
(vc-git--assert-revision-on-branch rev (vc-git--current-branch))
|
||||
(with-temp-buffer
|
||||
(vc-git-command t 0 nil "log" "--merges" (format "%s~1.." rev))
|
||||
(unless (bobp)
|
||||
(error "There have been merges since %s; cannot delete revision"
|
||||
rev)))
|
||||
(unless (zerop (vc-git-command nil 1 nil "rebase"
|
||||
rev "--onto" (format "%s~1" rev)))
|
||||
;; FIXME: Ideally we would leave some sort of conflict for the user
|
||||
;; to resolve, instead of just giving up. We would want C-x v v to
|
||||
;; do 'git rebase --continue' like how it can currently be used to
|
||||
;; conclude a merge after resolving conflicts.
|
||||
(vc-git-command nil 0 nil "rebase" "--abort")
|
||||
(error "Merge conflicts while trying to delete %s; aborting" rev)))
|
||||
|
||||
(defvar vc-git-extra-menu-map
|
||||
(let ((map (make-sparse-keymap)))
|
||||
(define-key map [git-grep]
|
||||
|
|
|
|||
|
|
@ -1839,6 +1839,73 @@ Always has to fetch, like `vc-hg-incoming-revision' does."
|
|||
(vc-hg-command t 0 nil "log" (format "--rev=outgoing() and %s" rev))
|
||||
(bobp)))
|
||||
|
||||
(defun vc-hg-delete-revision (rev)
|
||||
"Use `hg histedit' to delete REV from the history of the current branch.
|
||||
|
||||
`hg histedit' will fail unless
|
||||
- REV is an ancestor of the working directory;
|
||||
- all commits back to REV are not yet public; and
|
||||
- there aren't any merges in the history to be edited."
|
||||
(with-temp-buffer
|
||||
;; Resolve REV to a full changeset hash.
|
||||
(vc-hg-command t 0 nil "log" "--limit=1"
|
||||
(format "--rev=%s" rev) "--template={node}")
|
||||
(when (bobp)
|
||||
;; If REV is not found, hg exits 255, so this should never happen.
|
||||
(error "'hg log' unexpectedly gave no output"))
|
||||
(setq rev (buffer-string)))
|
||||
(let ((repo default-directory)
|
||||
(commands (make-nearby-temp-file "hg-commands")))
|
||||
(unwind-protect
|
||||
(let ((coding-system-for-write
|
||||
;; On MS-Windows, we must encode command-line arguments
|
||||
;; in the system codepage.
|
||||
(if (eq system-type 'windows-nt)
|
||||
locale-coding-system
|
||||
coding-system-for-write)))
|
||||
(with-temp-file commands
|
||||
(let ((default-directory repo))
|
||||
(vc-hg-command t 0 nil "log" (format "--rev=.:%s" rev)
|
||||
"--template=pick {node}\n"))
|
||||
(goto-char (point-min))
|
||||
(unless (re-search-forward (format "^pick %s\n\\'" rev) nil t)
|
||||
(error "'hg log' output parse failure"))
|
||||
(replace-match (format "drop %s\n" rev)))
|
||||
(unless (zerop
|
||||
(vc-hg-command
|
||||
nil 1 nil
|
||||
"--config=extensions.histedit="
|
||||
|
||||
;; Without this, --commands is ignored and histedit
|
||||
;; starts a curses interface. (Actually redundant
|
||||
;; with the HGPLAIN=1 set by vc-hg--command-1.)
|
||||
"--config=ui.interface=text"
|
||||
|
||||
;; Request validation of the commands file:
|
||||
;; stop if any commits in the history back to REV
|
||||
;; are missing, somehow.
|
||||
"--config=histedit.dropmissing=False"
|
||||
|
||||
;; Prevent Mercurial trying to open Meld or similar.
|
||||
;; FIXME: According to
|
||||
;; <https://repo.mercurial-scm.org/hg/help/merge-tools>,
|
||||
;; this can be overridden by user's "merge-patterns"
|
||||
;; settings.
|
||||
"--config=ui.merge=internal:fail"
|
||||
|
||||
"histedit"
|
||||
(format "--rev=%s" rev) "--commands" commands))
|
||||
;; FIXME: Ideally we would leave some sort of conflict for
|
||||
;; the user to resolve, instead of just giving up.
|
||||
;; We would want C-x v v to do 'hg histedit --continue' like
|
||||
;; how it can currently be used to conclude a merge after
|
||||
;; resolving conflicts.
|
||||
(vc-hg-command nil 0 nil "--config=extensions.histedit="
|
||||
"histedit" "--abort")
|
||||
(error "Merge conflicts while trying to delete %s; aborting"
|
||||
rev)))
|
||||
(delete-file commands))))
|
||||
|
||||
(provide 'vc-hg)
|
||||
|
||||
;;; vc-hg.el ends here
|
||||
|
|
|
|||
|
|
@ -398,6 +398,16 @@
|
|||
;; Relocate the working tree, assumed to be one that uses the same
|
||||
;; backing repository as this working tree, at FROM to TO.
|
||||
;; Callers must ensure that FROM is not the current working tree.
|
||||
;;
|
||||
;; - delete-revision (rev)
|
||||
;;
|
||||
;; Remove REV from the revision history of the current branch.
|
||||
;; For a distributed VCS, this means a rebase operation to rewrite the
|
||||
;; history of the current branch so that it no longer contains REV (or
|
||||
;; its changes). For a centralized VCS this may mean something
|
||||
;; different; for example CVS has true undos (not yet implemented in
|
||||
;; Emacs). A distributed VCS that implements this must also implement
|
||||
;; revision-published-p.
|
||||
|
||||
;; HISTORY FUNCTIONS
|
||||
;;
|
||||
|
|
|
|||
Loading…
Reference in a new issue