Skip to content

:setup form is not called before Eldev tries to use the package from eldev-use-vc-repository #114

@mathrick

Description

@mathrick

Describe the bug

#91 suggests that :setup can be used to adjust where Eldev looks for the package files when fetching via VC. However, the form is not actually called until after eldev-package-descriptor is called, which makes it impossible to use packages whose header file is not located at the top level of the repository.

Steps to reproduce

  1. Add VC repository for magit, and declare it as a dependency
    (eldev-add-extra-dependencies 'prepare 'magit)
    (eldev-use-vc-repository 'magit :github "magit/magit" :commit "v4.0.0" :setup '(setf eldev-project-source-dirs "lisp"))
    
  2. Run eldev prepare
  3. It fails with No .el files with package headers in ‘/home/mathrick/Dev/magit-p4/.eldev/git/magit/’

Expected behavior

:setup forms should be executed before

Actual behavior

eldev-package-descriptor is called on the fetched source before :setup had a chance to run, which causes it to fail miserably. Backtrace:

Started up on Sun Mar 9 00:15:39 2025
Running on GNU Emacs 27.1 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.20, cairo version 1.16.0) of 2020-09-19
Emacs source is unknown
Project directory: ‘/home/mathrick/Dev/magit-p4/’
No file ‘/home/mathrick/.config/eldev/config’, not applying user-specific configuration
Loading file ‘Eldev’...
Using package archive ‘gnu’ at ‘https://elpa.gnu.org/packages/’ with priority 300
Using package archive ‘gnu-devel’ at ‘https://elpa.gnu.org/devel/’ with priority 190
Using package archive ‘melpa-stable’ at ‘https://stable.melpa.org/packages/’ with priority 200
Using package archive ‘melpa-unstable’ at ‘https://melpa.org/packages/’ with priority 100
Reading target dependencies from file ‘.eldev/27.1/target-dependencies.build’...
Target dependency information is up-to-date, not saving...
Old Emacs version detected, remapping lisp-data-mode
Loading file ‘Eldev-local’...
Executing command ‘prepare’...
Contents of package archive ‘gnu’ has been fetched already
Contents of package archive ‘melpa-stable’ has been fetched already
Contents of package archive ‘gnu-devel’ has been fetched already
Contents of package archive ‘melpa-unstable’ has been fetched already
Reusing existing Git clone of ‘/home/mathrick/Dev/magit-p4/.eldev/git/magit/’...
Reading internal evaluation cache from file ‘.eldev/27.1/internal-eval.cache’...
Using cached value for form ‘(eldev-project-source-dirs)’ in directory ‘/home/mathrick/Dev/magit-p4/.eldev/git/magit/’: ("/home/mathrick/Dev/magit-p4/.eldev/git/magit/")
Using cached value for form ‘eldev-project-main-file’ in directory ‘/home/mathrick/Dev/magit-p4/.eldev/git/magit/’: nil

Debugger entered--Lisp error: (error "No .el files with package headers in ‘/home/mathrick/Dev/magit-p4/.eldev/git/magit/’")
 signal(error ("No .el files with package headers in ‘/home/mathrick/Dev/magit-p4/.eldev/git/magit/’"))
 eldev-package-descriptor("/home/mathrick/Dev/magit-p4/.eldev/git/magit/")
 eldev--vc-fetch-repository((magit :git "https://github.com/magit/magit.git" :github "magit/magit" :commit "v4.0.0" :setup (setf eldev-project-source-dirs "lisp")) nil)
 eldev--do-install-or-upgrade-dependencies(project nil nil nil t nil nil)
 eldev--install-or-upgrade-dependencies(project nil nil nil t nil nil)
 eldev-load-project-dependencies(nil nil t)
 eldev-prepare()
 apply(eldev-prepare nil)
 eldev--execute-command(("prepare"))
 eldev-cli(("-dt" "--old-deps" "prepare"))
 (kill-emacs (eldev-cli (append (cdr (member "--" command-line-args)) nil)))
 eval((kill-emacs (eldev-cli (append (cdr (member "--" command-line-args)) nil))) t)
 command-line-1(("--execute" "(let ((eldev--emacs-version (format \"%s.%s\" emacs-major-version emacs-minor-version))\n      (eldev--dir           (getenv \"ELDEV_DIR\"))\n      ;; This is intentional.  First, this is in case ELDEV_LOCAL is\n      ;; defined, second, this is just Eldev default for packages.\n      (load-prefer-newer    t))\n  ;; Setting `debug-on-error' would be useful, but it can break many\n  ;; `package-*' functions, since those use `with-demoted-errors' and\n  ;; so `condition-case-unless-debug'.\n  (unless (and (fboundp 'version<=) (version<= \"24.4\" eldev--emacs-version))\n    (error \"Eldev requires Emacs 24.4 or newer\"))\n  (setf package-user-dir\n        (expand-file-name \"bootstrap\"\n                          (expand-file-name eldev--emacs-version\n                                            (if (> (length eldev--dir) 0)\n                                                eldev--dir\n                                              (if (file-directory-p \"~/.eldev\")\n                                                  \"~/.eldev\"\n                                                ;; Duplicating not-yet-available code from `eldev-xdg-cache-home'.\n                                                (expand-file-name \"eldev\"\n                                                                  (let ((eldev--xdg-cache-dir (getenv \"XDG_CACHE_HOME\")))\n                                                                    (if (and eldev--xdg-cache-dir (file-name-absolute-p eldev--xdg-cache-dir))\n                                                                        eldev--xdg-cache-dir\n                                                                      \"~/.cache\")))))))\n        package-directory-list nil\n        package-archives       nil)\n  (require 'package)\n  (package-initialize t)\n  (let ((package-archives '((\"melpa-stable\" . \"http://stable.melpa.org/packages/\")))\n        (archive-name      \"MELPA Stable\")\n        (inhibit-message  t)\n        (eldev-local      (getenv \"ELDEV_LOCAL\"))\n        eldev-pkg\n        requirements)\n    (unless (= (length eldev-local) 0)\n      (if (string-prefix-p \":pa:\" eldev-local)\n          (setf package-archives `((\"bootstrap-pa\" . ,(file-name-as-directory (substring eldev-local (length \":pa:\")))))\n                archive-name     \"a local package archive\")\n        (with-temp-buffer\n          (insert-file-contents (expand-file-name \"eldev.el\" eldev-local))\n          (setf eldev-pkg                    (package-buffer-info)\n                (package-desc-dir eldev-pkg) (expand-file-name eldev-local))\n          ;; Currently Eldev has no external dependencies, but let's be generic.\n          (dolist (requirement (package-desc-reqs eldev-pkg))\n            (unless (package-activate (car requirement))\n              (push requirement requirements))))))\n    (when (if eldev-pkg\n              requirements\n            (not (package-activate 'eldev)))\n      (let ((inhibit-message nil))\n        (message \"Bootstrapping Eldev for Emacs %s from %s...\\n\" eldev--emacs-version archive-name)\n        (when eldev-pkg\n          (message \"Eldev package itself will be used from `%s'\\n\" eldev-local)))\n      ;; See `eldev-retrying-for-robustness'; since Eldev is not bootstrapped yet, we have\n      ;; to inline everything.  No control from command line here.\n      (let* ((all-retry-delays (when (equal (getenv \"CI\") \"true\") '(30 60 120 180 300)))\n             (remaining-delays all-retry-delays))\n        (catch 'obtained-result\n          (while t\n            (condition-case error\n                (throw 'obtained-result (let ((debug-on-error (and debug-on-error (null remaining-delays))))\n                                          ;; See similar workarounds for `package-refresh-contents' in `eldev.el'.\n                                          (let* (failure\n                                                 (failure-catcher (lambda (original archive &rest arguments)\n                                                                    (unless failure\n                                                                      (condition-case-unless-debug error\n                                                                          (apply original archive arguments)\n                                                                        (error (setf failure (cons error (if (consp archive) (car archive) archive)))))))))\n                                            (advice-add 'package--download-one-archive :around failure-catcher)\n                                            (unwind-protect\n                                                (package-refresh-contents)\n                                              (advice-remove 'package--download-one-archive failure-catcher))\n                                            (when failure\n                                              (error \"%s (when updating contents of package archive `%s')\" (error-message-string (car failure)) (cdr failure))))))\n              (error (let ((inhibit-message nil)\n                           (delay           (pop remaining-delays)))\n                       (unless delay\n                         (when all-retry-delays\n                           (message \"Giving up: too many retries already\"))\n                         (signal (car error) (cdr error)))\n                       (message \"%s\" (error-message-string error))\n                       (message \"Assuming this is an intermittent problem, waiting %s before retrying...\\n\"\n                                (if (< delay 60) (format \"%s s\" delay) (format \"%s m\" (/ delay 60))))\n                       (sleep-for delay)\n                       (let ((n (- 5 (length remaining-delays))))\n                         (message \"Retry #%d%s...\" n (if (= n 5) \", the last\" \" of maximum 5\")))))))))\n      (if eldev-pkg\n          (package-download-transaction (package-compute-transaction nil requirements))\n        (package-install 'eldev)))\n    (when eldev-pkg\n      (push `(eldev . (,eldev-pkg)) package-alist)\n      ;; `package--autoloads-file-name' is package-private.\n      (let* ((autoloads-file     (expand-file-name (format \"%s-autoloads\" (package-desc-name eldev-pkg))\n                                                   (package-desc-dir eldev-pkg)))\n             (autoloads-disabler (lambda (do-load file &rest args) (unless (equal file autoloads-file) (apply do-load file args)))))\n        ;; Otherwise old Emacs versions print an ugly error having not found the autoloads file.\n        (advice-add #'load :around autoloads-disabler)\n        (package-activate-1 eldev-pkg)\n        ;; As of commit 1d5b164109b in Emacs repository, `package-activate-1' no longer modifies `load-path',\n        ;; leaving this to the autoloads file.  As we don't have such a file, we have to do that ourselves.\n        (add-to-list 'load-path (package-desc-dir eldev-pkg))\n        (advice-remove #'load autoloads-disabler))))\n  (require 'eldev)\n  (eldev-start-up))" "--execute" "(kill-emacs (eldev-cli (append (cdr (member \"--\" command-line-args)) nil)))" "--" "-dt" "--old-deps" "prepare"))
 command-line()
 normal-top-level()

Environment

  • Eldev: 1.11
  • Emacs: 27.1
  • OS: Ubuntu Linux 20.04

Additional context

Looking at git blame of eldev-vc.el, it doesn't seem that it ever would have worked, starting with the initial implementation in 96d5baa. There are also no tests to verify that it works.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions