mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-02-16 09:14:18 +00:00
VC: Use symbolic names for the working revision
* lisp/vc/vc-hg.el (vc-hg-diff): When OLDVERS is ".", behave the same as if OLDVERS was the actual working revision. (vc-hg-previous-revision): Return ".~1" for input ".", ".~3" for input ".^^" et cetera. Also, when passed non-symbolic revisions, use "REV~1" instead of "REV^" for MS-Windows compatibility. (vc-hg-working-revision-symbol): * lisp/vc/vc-git.el (vc-git-working-revision-symbol): * lisp/vc/vc-hooks.el (vc-symbolic-working-revision): New functions. (vc-default-mode-line-string): * lisp/vc/ediff-vers.el (ediff-vc-merge-internal): * test/lisp/vc/vc-tests/vc-tests.el (vc-test--checkin-patch): * lisp/vc/vc.el (vc-diff-build-argument-list-internal) (vc-diff-outgoing, vc-revision-other-window, vc-default-revert): Call vc-symbolic-working-revision. (vc-buffer-revision): Specify that this should always be a revision number/hash, not a symbolic name. * lisp/vc/vc-git.el (vc-git-previous-revision): Return "HEAD~1" for input "HEAD", "HEAD~3" for input "HEAD^^" et cetera.
This commit is contained in:
parent
9ccef794a8
commit
d3c4679acd
6 changed files with 115 additions and 53 deletions
|
|
@ -152,9 +152,9 @@ With prefix argument, prompts for a revision name."
|
|||
(setq buf2 (current-buffer)))
|
||||
(if ancestor-rev
|
||||
(save-excursion
|
||||
(if (string= ancestor-rev "")
|
||||
(setq ancestor-rev (vc-working-revision
|
||||
buffer-file-name)))
|
||||
(if (string-empty-p ancestor-rev)
|
||||
(setq ancestor-rev
|
||||
(vc-symbolic-working-revision buffer-file-name)))
|
||||
(vc-revision-other-window ancestor-rev)
|
||||
(setq ancestor-buf (current-buffer)))))
|
||||
(if ancestor-rev
|
||||
|
|
|
|||
|
|
@ -1140,6 +1140,8 @@ It is based on `log-edit-mode', and has Git-specific extensions."
|
|||
|
||||
(defalias 'vc-git-async-checkins #'always)
|
||||
|
||||
(defalias 'vc-git-working-revision-symbol (cl-constantly "HEAD"))
|
||||
|
||||
(defun vc-git--checkin (comment &optional files patch-string)
|
||||
"Workhorse routine for `vc-git-checkin' and `vc-git-checkin-patch'.
|
||||
COMMENT is the commit message; must be non-nil.
|
||||
|
|
@ -2073,26 +2075,31 @@ This requires git 1.8.4 or later, for the \"-L\" option of \"git log\"."
|
|||
|
||||
(defun vc-git-previous-revision (file rev)
|
||||
"Git-specific version of `vc-previous-revision'."
|
||||
(if file
|
||||
(let* ((fname (file-relative-name file))
|
||||
(prev-rev (with-temp-buffer
|
||||
(and
|
||||
(vc-git--out-ok "rev-list"
|
||||
(vc-git--maybe-abbrev)
|
||||
"-2" rev "--" fname)
|
||||
(goto-char (point-max))
|
||||
(bolp)
|
||||
(zerop (forward-line -1))
|
||||
(not (bobp))
|
||||
(buffer-substring-no-properties
|
||||
(point)
|
||||
(1- (point-max)))))))
|
||||
(or (vc-git-symbolic-commit prev-rev) prev-rev))
|
||||
;; We used to use "^" here, but that fails on MS-Windows if git is
|
||||
;; invoked via a batch file, in which case cmd.exe strips the "^"
|
||||
;; because it is a special character for cmd which process-file
|
||||
;; does not (and cannot) quote.
|
||||
(vc-git--rev-parse (concat rev "~1"))))
|
||||
(cond ((string-match "\\`HEAD\\(\\^*\\)\\'" rev)
|
||||
(format "HEAD~%d" (1+ (length (match-string 1 rev)))))
|
||||
((string-match "\\`HEAD~\\([0-9]+\\)\\'" rev)
|
||||
(format "HEAD~%d" (1+ (string-to-number (match-string 1 rev)))))
|
||||
(file
|
||||
(let* ((fname (file-relative-name file))
|
||||
(prev-rev (with-temp-buffer
|
||||
(and
|
||||
(vc-git--out-ok "rev-list"
|
||||
(vc-git--maybe-abbrev)
|
||||
"-2" rev "--" fname)
|
||||
(goto-char (point-max))
|
||||
(bolp)
|
||||
(zerop (forward-line -1))
|
||||
(not (bobp))
|
||||
(buffer-substring-no-properties
|
||||
(point)
|
||||
(1- (point-max)))))))
|
||||
(or (vc-git-symbolic-commit prev-rev) prev-rev)))
|
||||
(t
|
||||
;; We used to use "^" here, but that fails on MS-Windows if git
|
||||
;; is invoked via a batch file, in which case cmd.exe strips
|
||||
;; the "^" because it is a special character for cmd which
|
||||
;; process-file does not (and cannot) quote.
|
||||
(vc-git--rev-parse (concat rev "~1")))))
|
||||
|
||||
(defun vc-git--rev-parse (rev)
|
||||
(with-temp-buffer
|
||||
|
|
|
|||
|
|
@ -557,7 +557,7 @@ This requires hg 4.4 or later, for the \"-L\" option of \"hg log\"."
|
|||
"Get a difference report using hg between two revisions of FILES."
|
||||
(let* ((firstfile (car files))
|
||||
(working (and firstfile (vc-working-revision firstfile 'Hg))))
|
||||
(when (and (not newvers) (equal oldvers working))
|
||||
(when (and (not newvers) (member oldvers (list working ".")))
|
||||
(setq oldvers nil))
|
||||
(when (and newvers (not oldvers))
|
||||
(setq oldvers working))
|
||||
|
|
@ -1137,13 +1137,22 @@ hg binary."
|
|||
;;; Miscellaneous
|
||||
|
||||
(defun vc-hg-previous-revision (_file rev)
|
||||
;; We can't simply decrement by 1, because that revision might be
|
||||
;; e.g. on a different branch (bug#22032).
|
||||
(with-temp-buffer
|
||||
(and (eq 0
|
||||
(vc-hg-command t nil nil "id" "-n" "-r" (concat rev "^")))
|
||||
;; Trim the trailing newline.
|
||||
(buffer-substring (point-min) (1- (point-max))))))
|
||||
;; Prefer to return values with tildes not carets because that's more
|
||||
;; compatible with MS-Windows (see `vc-git-previous-revision').
|
||||
;;
|
||||
;; See <https://repo.mercurial-scm.org/hg/help/revsets> for reference.
|
||||
(cond ((string-match "\\`\\.\\(\\^*\\)\\'" rev)
|
||||
(format ".~%d" (1+ (length (match-string 1 rev)))))
|
||||
((string-match "\\`\\.~\\([0-9]+\\)\\'" rev)
|
||||
(format ".~%d" (1+ (string-to-number (match-string 1 rev)))))
|
||||
(t
|
||||
;; We can't simply decrement by 1, because that revision might
|
||||
;; be e.g. on a different branch (bug#22032).
|
||||
(with-temp-buffer
|
||||
(and (zerop (vc-hg-command t nil nil "id" "-n"
|
||||
"-r" (concat rev "~1")))
|
||||
;; Trim the trailing newline.
|
||||
(buffer-substring (point-min) (1- (point-max))))))))
|
||||
|
||||
(defun vc-hg-next-revision (_file rev)
|
||||
(let ((newrev (1+ (string-to-number rev)))
|
||||
|
|
@ -1213,6 +1222,8 @@ It is based on `log-edit-mode', and has Hg-specific extensions.")
|
|||
|
||||
(defalias 'vc-hg-async-checkins #'always)
|
||||
|
||||
(defalias 'vc-hg-working-revision-symbol (cl-constantly "."))
|
||||
|
||||
(defun vc-hg--checkin (comment &optional files patch-string)
|
||||
"Workhorse routine for `vc-hg-checkin' and `vc-hg-checkin-patch'.
|
||||
COMMENT is the commit message; nil if it should come from PATCH-STRING.
|
||||
|
|
|
|||
|
|
@ -545,14 +545,42 @@ status of this file. Otherwise, the value returned is one of:
|
|||
|
||||
(defun vc-working-revision (file &optional backend)
|
||||
"Return the repository version from which FILE was checked out.
|
||||
If FILE is not registered, this function always returns nil."
|
||||
If FILE is not registered, this function always returns nil.
|
||||
|
||||
This function does not return nil without first confirming with the
|
||||
underlying VCS that FILE is unregistered; this is in contrast to
|
||||
`vc-symbolic-working-revision'."
|
||||
(or (vc-file-getprop file 'vc-working-revision)
|
||||
(let ((default-directory (file-name-directory file)))
|
||||
(setq backend (or backend (vc-backend file)))
|
||||
(when backend
|
||||
(vc-file-setprop file 'vc-working-revision
|
||||
(vc-call-backend
|
||||
backend 'working-revision file))))))
|
||||
(and (setq backend (or backend (vc-backend file)))
|
||||
(vc-file-setprop file 'vc-working-revision
|
||||
(vc-call-backend backend 'working-revision
|
||||
file))))))
|
||||
|
||||
(defun vc-symbolic-working-revision (file &optional backend)
|
||||
"Return BACKEND's symbolic name for FILE's working revision.
|
||||
If FILE is not registered according to cached information, return nil.
|
||||
If BACKEND does not have a symbolic name for the working revision or
|
||||
Emacs doesn't know what it is, call `vc-working-revision' instead.
|
||||
|
||||
Prefer this function to `vc-working-revision' whenever a symbolic name
|
||||
will do, for it avoids a call out to the underlying VCS."
|
||||
;; Returning nil if the file is unregistered (which is why we call
|
||||
;; `vc-backend' even if BACKEND is non-nil here) makes us closer to a
|
||||
;; drop-in replacement for `vc-working-revision'. Don't actually
|
||||
;; query the VCS because the point of this function is to avoid such
|
||||
;; queries. Code that purely wants to map BACKEND to a symbolic name
|
||||
;; can call the backend API function directly.
|
||||
;; (If we don't check whether FILE is registered, then whether this
|
||||
;; function is sensitive to FILE being registered depends on whether
|
||||
;; BACKEND implements `working-revision-symbol' (because we would be
|
||||
;; sensitive to whether FILE is registered if and only if we defer to
|
||||
;; `vc-working-revision'), which would be a strange interdependence.)
|
||||
(and-let* ((cached-backend (vc-backend file)))
|
||||
(let* ((backend (or backend cached-backend))
|
||||
(fn (vc-find-backend-function backend
|
||||
'working-revision-symbol)))
|
||||
(if fn (funcall fn) (vc-working-revision file backend)))))
|
||||
|
||||
(defvar vc-use-short-revision nil
|
||||
"If non-nil, VC backend functions should return short revisions if possible.
|
||||
|
|
@ -825,12 +853,13 @@ Format:
|
|||
This function assumes that the file is registered."
|
||||
(pcase-let* ((backend-name (symbol-name backend))
|
||||
(state (vc-state file backend))
|
||||
(rev (vc-working-revision file backend))
|
||||
(rev (vc-symbolic-working-revision file backend))
|
||||
(`(,state-echo ,face ,indicator)
|
||||
(vc-mode-line-state state))
|
||||
(state-string (concat (unless (eq vc-display-status 'no-backend)
|
||||
backend-name)
|
||||
indicator rev)))
|
||||
(state-string
|
||||
(concat (and (not (eq vc-display-status 'no-backend))
|
||||
backend-name)
|
||||
indicator rev)))
|
||||
(propertize state-string 'face face 'help-echo
|
||||
(concat state-echo " under the " backend-name
|
||||
" version control system"))))
|
||||
|
|
|
|||
|
|
@ -124,6 +124,16 @@
|
|||
;;
|
||||
;; Takes no arguments. Backends that return non-nil can (and do)
|
||||
;; perform async checkins when `vc-async-checkin' is non-nil.
|
||||
;;
|
||||
;; - working-revision-symbol
|
||||
;;
|
||||
;; Symbolic name for the/a working revision, a constant string. If
|
||||
;; defined, backend API functions that take revision numbers, revision
|
||||
;; hashes or branch names can also take this string in place of those.
|
||||
;; Emacs passes this name without first having to look up the working
|
||||
;; revision, which is a small performance improvement.
|
||||
;; In addition, using a name instead of a number or hash makes it
|
||||
;; easier to edit backend commands with `vc-edit-next-command'.
|
||||
|
||||
;; STATE-QUERYING FUNCTIONS
|
||||
;;
|
||||
|
|
@ -597,8 +607,14 @@
|
|||
;;
|
||||
;; - previous-revision (file rev)
|
||||
;;
|
||||
;; Return the revision number that precedes REV for FILE, or nil if no such
|
||||
;; revision exists.
|
||||
;; Return the revision number/hash that precedes REV for FILE, or nil
|
||||
;; if no such revision exists. If the working-revision-symbol
|
||||
;; function is defined for this backend and that symbol, or a symbolic
|
||||
;; name involving that symbol, is passed to this function as REV, this
|
||||
;; function may return a symbolic name.
|
||||
;;
|
||||
;; Possible future extension: make REV an optional argument, and if
|
||||
;; nil, default it to FILE's working revision.
|
||||
;;
|
||||
;; - file-name-changes (rev)
|
||||
;;
|
||||
|
|
@ -1313,7 +1329,8 @@ STATE-MODEL-ONLY-FILES argument to `vc-deduce-fileset' is nil.")
|
|||
"VCS revision to which this buffer's contents corresponds.
|
||||
Lisp code which sets this should also set `vc-buffer-overriding-fileset'
|
||||
such that the buffer's local variables also specify a VC backend,
|
||||
rendering the value of this variable unambiguous.")
|
||||
rendering the value of this variable unambiguous.
|
||||
Should never be a symbolic name but always a revision number/hash.")
|
||||
|
||||
(defun vc-deduce-backend ()
|
||||
(cond ((car vc-buffer-overriding-fileset))
|
||||
|
|
@ -2584,7 +2601,7 @@ INITIAL-INPUT are passed on to `vc-read-revision' directly."
|
|||
(t
|
||||
(push (ignore-errors ;If `previous-revision' doesn't work.
|
||||
(vc-call-backend backend 'previous-revision first
|
||||
(vc-working-revision first backend)))
|
||||
(vc-symbolic-working-revision first backend)))
|
||||
rev1-default)
|
||||
(when (member (car rev1-default) '("" nil)) (setq rev1-default nil))))
|
||||
;; construct argument list
|
||||
|
|
@ -2806,10 +2823,8 @@ global binding."
|
|||
;; 'revision-granularity)
|
||||
;; 'repository)
|
||||
;; (ignore-errors
|
||||
;; (vc-call-backend backend 'working-revision
|
||||
;; (caadr fileset)))
|
||||
(vc-call-backend backend 'working-revision
|
||||
(caadr fileset))
|
||||
;; (vc-symbolic-working-revision (caadr fileset)))
|
||||
(vc-symbolic-working-revision (caadr fileset))
|
||||
(called-interactively-p 'interactive))))
|
||||
|
||||
;; For the following two commands, the default meaning for
|
||||
|
|
@ -2980,8 +2995,8 @@ If `F.~REV~' already exists, use it instead of checking it out again."
|
|||
(set-buffer (or (buffer-base-buffer) (current-buffer)))
|
||||
(vc-ensure-vc-buffer)
|
||||
(let* ((file buffer-file-name)
|
||||
(revision (if (string-equal rev "")
|
||||
(vc-working-revision file)
|
||||
(revision (if (string-empty-p rev)
|
||||
(vc-symbolic-working-revision file)
|
||||
rev)))
|
||||
(switch-to-buffer-other-window (vc-find-revision file revision))))
|
||||
|
||||
|
|
@ -4522,7 +4537,7 @@ to provide the `find-revision' operation instead."
|
|||
|
||||
(defun vc-default-revert (backend file contents-done)
|
||||
(unless contents-done
|
||||
(let ((rev (vc-working-revision file))
|
||||
(let ((rev (vc-symbolic-working-revision file))
|
||||
(file-buffer (or (get-file-buffer file) (current-buffer))))
|
||||
(message "Checking out %s..." file)
|
||||
(let ((failed t)
|
||||
|
|
|
|||
|
|
@ -815,7 +815,7 @@ This checks also `vc-backend' and `vc-responsible-backend'."
|
|||
(cl-flet
|
||||
((get-patch-string ()
|
||||
"Get patch corresponding to most recent commit to FILE."
|
||||
(let* ((rev (vc-call-backend backend 'working-revision file))
|
||||
(let* ((rev (vc-symbolic-working-revision file backend))
|
||||
(patch (vc-call-backend backend 'prepare-patch rev)))
|
||||
(with-current-buffer (plist-get patch :buffer)
|
||||
(buffer-substring-no-properties (point-min)
|
||||
|
|
|
|||
Loading…
Reference in a new issue