1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-10 00:00:39 -08:00

Extract last source package release from local VCS data

* lisp/emacs-lisp/package-vc.el (package-vc-archive-spec-alist):
Unmention :release-rev
(package-vc-desc->spec): Fall back on other archives if a
specification is missing.
(package-vc-main-file): Add new function, copying the behaviour of
elpa-admin.el.
(package-vc-generate-description-file): Use 'package-vc-main-file'.
(package-vc-unpack): Handle special value ':last-release'.
(package-vc-release-rev): Add new function using 'last-change'.
(package-vc-install): Pass ':last-release' as REV instead of a
release.
* lisp/vc/vc-git.el (vc-git-last-change): Add Git 'last-change'
implementation.
* lisp/vc/vc.el (vc-default-last-change): Add default 'last-change'
implementation.

This attempts to replicate the behaviour of elpa-admin.el's
"elpaa--get-last-release-commit".
This commit is contained in:
Philip Kaludercic 2022-10-30 11:43:11 +01:00
parent a52cec7b6b
commit 30f1e7c1e9
3 changed files with 94 additions and 29 deletions

View file

@ -139,12 +139,6 @@ The main file of the project, relevant to gather package
metadata. If not given, the assumed default is the package named metadata. If not given, the assumed default is the package named
with \".el\" concatenated to the end. with \".el\" concatenated to the end.
`:release-rev' (string)
A revision string indicating the revision used for the current
release in the package archive. If missing or nil, no release
was made.
`:vc-backend' (symbol) `:vc-backend' (symbol)
A symbol indicating what the VC backend to use for cloning a A symbol indicating what the VC backend to use for cloning a
@ -179,8 +173,10 @@ The optional argument NAME can be used to override the default
name for PKG-DESC." name for PKG-DESC."
(alist-get (alist-get
(or name (package-desc-name pkg-desc)) (or name (package-desc-name pkg-desc))
(alist-get (intern (package-desc-archive pkg-desc)) (if (package-desc-archive pkg-desc)
package-vc-archive-spec-alist) (alist-get (intern (package-desc-archive pkg-desc))
package-vc-archive-spec-alist)
(mapcan #'append (mapcar #'cdr package-vc-archive-spec-alist)))
nil nil #'string=)) nil nil #'string=))
(define-inline package-vc-query-spec (pkg-desc prop) (define-inline package-vc-query-spec (pkg-desc prop)
@ -258,6 +254,20 @@ asynchronously."
return it return it
finally return "0")) finally return "0"))
(defun package-vc-main-file (pkg-desc)
"Return the main file for PKG-DESC."
(cl-assert (package-vc-p pkg-desc))
(let ((pkg-spec (package-vc-desc->spec pkg-desc)))
(or (plist-get pkg-spec :main-file)
(expand-file-name
(format "%s.el" (package-desc-name pkg-desc))
(file-name-concat
(or (package-desc-dir pkg-desc)
(expand-file-name
(package-desc-name pkg-desc)
package-user-dir))
(plist-get pkg-spec :lisp-dir))))))
(defun package-vc-generate-description-file (pkg-desc pkg-file) (defun package-vc-generate-description-file (pkg-desc pkg-file)
"Generate a package description file for PKG-DESC. "Generate a package description file for PKG-DESC.
The output is written out into PKG-FILE." The output is written out into PKG-FILE."
@ -265,18 +275,13 @@ The output is written out into PKG-FILE."
;; Infer the subject if missing. ;; Infer the subject if missing.
(unless (package-desc-summary pkg-desc) (unless (package-desc-summary pkg-desc)
(setf (package-desc-summary pkg-desc) (setf (package-desc-summary pkg-desc)
(or (package-desc-summary pkg-desc) (let ((main-file (package-vc-main-file pkg-desc)))
(and-let* ((pkg (cadr (assq name package-archive-contents)))) (or (package-desc-summary pkg-desc)
(package-desc-summary pkg)) (and-let* ((pkg (cadr (assq name package-archive-contents))))
(and-let* ((pkg-spec (package-vc-desc->spec pkg-desc)) (package-desc-summary pkg))
(main-file (plist-get pkg-spec :main-file))) (and main-file (file-exists-p main-file)
(lm-summary main-file)) (lm-summary main-file))
(and-let* ((main-file (expand-file-name package--default-summary))))
(format "%s.el" name)
(package-desc-dir pkg-desc)))
((file-exists-p main-file)))
(lm-summary main-file))
package--default-summary)))
(let ((print-level nil) (let ((print-level nil)
(print-quoted t) (print-quoted t)
(print-length nil)) (print-length nil))
@ -424,9 +429,16 @@ the `:brach' attribute in PKG-SPEC."
nil nil #'string=) nil nil #'string=)
:vc-backend) :vc-backend)
package-vc-default-backend))) package-vc-default-backend)))
(unless (vc-clone url backend repo-dir (or rev branch)) (unless (vc-clone url backend repo-dir
(or (and (not (eq rev :last-release)) rev) branch))
(error "Failed to clone %s from %s" name url)))) (error "Failed to clone %s from %s" name url))))
;; Check out the latest release if requested
(when (eq rev :last-release)
(if-let ((release-rev (package-vc-release-rev pkg-desc)))
(vc-retrieve-tag pkg-dir release-rev)
(message "No release revision was found, continuing...")))
(unless (eq pkg-dir repo-dir) (unless (eq pkg-dir repo-dir)
;; Link from the right position in `repo-dir' to the package ;; Link from the right position in `repo-dir' to the package
;; directory in the ELPA store. ;; directory in the ELPA store.
@ -466,6 +478,22 @@ the `:brach' attribute in PKG-SPEC."
(unless package-vc-archive-data-alist (unless package-vc-archive-data-alist
(package-vc--download-and-read-archives))) (package-vc--download-and-read-archives)))
(defun package-vc-release-rev (pkg-desc)
"Find the latest revision that bumps the \"Version\" tag for PKG-DESC.
If no such revision can be found, return nil."
(with-current-buffer (find-file-noselect (package-vc-main-file pkg-desc))
(vc-buffer-sync)
(save-excursion
(goto-char (point-min))
(let ((case-fold-search t))
(when (re-search-forward (concat (lm-get-header-re "version") ".*$")
(lm-code-start) t)
(ignore-error vc-not-supported
(vc-call-backend (vc-backend (buffer-file-name))
'last-change
(match-beginning 0)
(match-end 0))))))))
;;;###autoload ;;;###autoload
(defun package-vc-install (name-or-url &optional name rev backend) (defun package-vc-install (name-or-url &optional name rev backend)
"Fetch the source of NAME-OR-URL. "Fetch the source of NAME-OR-URL.
@ -477,9 +505,11 @@ NAME-OR-URL is taken to be a package name, and the package
metadata will be consulted for the URL. An explicit revision can metadata will be consulted for the URL. An explicit revision can
be requested using REV. If the command is invoked with a prefix be requested using REV. If the command is invoked with a prefix
argument, the revision used for the last release in the package argument, the revision used for the last release in the package
archive is used. If a NAME-OR-URL is a URL, that is to say a archive is used. This can also be reproduced by passing the
string, the VC backend used to clone the repository can be set by special value `:last-release' as REV. If a NAME-OR-URL is a URL,
BACKEND. If missing, `package-vc-guess-backend' will be used." that is to say a string, the VC backend used to clone the
repository can be set by BACKEND. If missing,
`package-vc-guess-backend' will be used."
(interactive (interactive
(progn (progn
;; Initialize the package system to get the list of package ;; Initialize the package system to get the list of package
@ -490,11 +520,7 @@ BACKEND. If missing, `package-vc-guess-backend' will be used."
"Fetch package source (name or URL): " packages)) "Fetch package source (name or URL): " packages))
(name (file-name-base input))) (name (file-name-base input)))
(list input (intern (string-remove-prefix "emacs-" name)) (list input (intern (string-remove-prefix "emacs-" name))
(and current-prefix-arg (and current-prefix-arg :last-release)))))
(or (package-vc-query-spec
(cadr (assoc input package-archive-contents #'string=))
:release-rev)
(user-error "No release revision was found")))))))
(package-vc--archives-initialize) (package-vc--archives-initialize)
(cond (cond
((and-let* ((stringp name-or-url) ((and-let* ((stringp name-or-url)
@ -511,6 +537,10 @@ BACKEND. If missing, `package-vc-guess-backend' will be used."
(setf (package-desc-kind copy) 'vc) (setf (package-desc-kind copy) 'vc)
copy) copy)
(or (package-vc-desc->spec (cadr desc)) (or (package-vc-desc->spec (cadr desc))
(and-let* ((extras (package-desc-extras (cadr desc)))
(url (alist-get :url extras))
(backend (package-vc-guess-backend url)))
(list :vc-backend backend :url url))
(user-error "Package has no VC data")) (user-error "Package has no VC data"))
rev))) rev)))
((user-error "Unknown package to fetch: %s" name-or-url)))) ((user-error "Unknown package to fetch: %s" name-or-url))))

View file

@ -1632,6 +1632,23 @@ This requires git 1.8.4 or later, for the \"-L\" option of \"git log\"."
(expand-file-name fname (vc-git-root default-directory)))) (expand-file-name fname (vc-git-root default-directory))))
revision))))) revision)))))
(defun vc-git-last-change (from to)
(vc-buffer-sync)
(let ((file (file-relative-name
(buffer-file-name)
(vc-git-root (buffer-file-name))))
(start (line-number-at-pos from t))
(end (line-number-at-pos to t)))
(with-temp-buffer
(when (vc-git--out-ok
"blame" "--porcelain"
(format "-L%d,%d" start end)
file)
(goto-char (point-min))
(save-match-data
(when (looking-at "\\`\\([[:alnum:]]+\\)[[:space:]]+")
(match-string 1)))))))
;;; TAG/BRANCH SYSTEM ;;; TAG/BRANCH SYSTEM
(declare-function vc-read-revision "vc" (declare-function vc-read-revision "vc"

View file

@ -448,6 +448,11 @@
;; - mergebase (rev1 &optional rev2) ;; - mergebase (rev1 &optional rev2)
;; ;;
;; Return the common ancestor between REV1 and REV2 revisions. ;; Return the common ancestor between REV1 and REV2 revisions.
;;
;; - last-change (from to)
;;
;; Return the most recent revision that made a change between FROM
;; and TO.
;; TAG/BRANCH SYSTEM ;; TAG/BRANCH SYSTEM
;; ;;
@ -3584,6 +3589,19 @@ it indicates a specific revision to check out."
remote directory rev))) remote directory rev)))
(throw 'ok res))))))) (throw 'ok res)))))))
(declare-function log-view-current-tag "log-view" (&optional pos))
(defun vc-default-last-change (_backend from to)
"Default `last-change' implementation.
FROM and TO are used as region markers"
(save-window-excursion
(let* ((buf (window-buffer (vc-region-history from to)))
(proc (get-buffer-process buf)))
(cl-assert (processp proc))
(while (accept-process-output proc))
(with-current-buffer buf
(prog1 (log-view-current-tag)
(kill-buffer))))))
;; These things should probably be generally available ;; These things should probably be generally available