elpaca
elpaca copied to clipboard
[Bug/Support]:How to use elpaca with local packages not in a git repo?
Confirmation
- [x] I have checked the documentation (README, Wiki, docstrings, etc)
- [ ] I am checking these without reading them.
- [x] I have searched previous issues to see if my question is a duplicate.
Elpaca Version
I have a single-file package gco-pkm.el in my ~/.config/emacs/lisp dir (which is in my load-path). I'd like to load that using use-package (which I have hooked up to elpaca with default :ensure t), but only after elpaca has built & loaded org and transient and other dependent packages. And another package gco-pkm-transient.el which I'd like loaded after the first one.
Can I just do
(use-package org
:ensure t
;; other stuff...)
(use-package transient :ensure t)
(use-package gco-pkm
:ensure nil
:load-path "lisp/"
:after org
:demand t ; force loading when org is ready
)
(use-package gco-pkm-transient
:ensure nil
:load-path "lisp/"
:after (gco-pkm org transient)
:demand t
? I don't see those packages in the elpaca-log buffer, so I don't know if it really processed them as part of its dependency graph or if I'm just getting lucky. Is there an elpaca-approved way to do this?
Operating System
MacOS
Description
No response
Seems to be the case : https://github.com/progfolio/elpaca/issues/459#issuecomment-2887798966
I think this is different. In #459 the local package is in its own local git repo, and elpaca clones it and builds it. This question is about a regular .el file, something you could just (require ...).
The final solution provided : https://github.com/progfolio/elpaca/issues/459#issuecomment-2973460209 is indeed using :repo so it'd need to be git, but the answer I linked is :
(use-package my-package :ensure nil :load-path "~/src/my-package" :after (uuid org-ml))
it only uses use-package keywords, as such, it should totally work. I'm just presenting this solution since, as one provided by the maintainer directly, it'd fit with "an elpaca-approved way to do this?" ^v^
@ananashawaw doesn't work for me. Tried with :elpaca nil too. Elpaca just pulls whatever is on MELPA ignoring my :load-path
Working on a redesign of the way build steps are handled which will allow for installing directly from a single file. Will ping when ready. Thank you.
@progfolio thanks for your work! As far as I'm concerned there are 3 ways to specify "installation" with elpaca+use-package:
:ensure twhich will pull stuff from MELPA:ensure nilwhich will generally try to load stuff bundled with Emacs (probably not only that if you add some load paths? Personally I use it only for bundled packages):ensure (name :host XXX :repo XXX)which will load from remote git repo My wish is that there would be some way to quickly toggle between one of these 3 and my local package folder (whatever it is: a repo or just a plain folder) Could be either:ensure (name :load-path XXX)or maybe just:load-pathinstead of a:ensurealtogether.
Here is an example of what I'm doing for local package dev :
(use-package ascii-table
:ensure (ascii-table :repo "~/.emacs.d/elpaca/repos/emacs-ascii-table")
:custom
(ascii-table-initial-base 10)
(ascii-table-initial-control nil)
(ascii-table-initial-escape t))
Altho the repo is available on melpa, elpaca doesn't attempt to fetch it, even when rebuilding or with a fetch-all, as such, the local version is loaded, do note that I don't have always-ensure or always-demand on
Altho the repo is available on melpa, elpaca doesn't attempt to fetch it, even when rebuilding or with a fetch-all, as such, the local version is loaded
But the interesting question is this: if your ascii-table.el file declares dependencies with Package-Requires:, does elpaca know about those and build and load them in the correct order? And then if some other package managed by elpaca declares a dependency on ascii-table, does it get properly loaded only after your package?
In other words, is your ascii-table a full-fledged elpaca citizen participating in the dependency resolution algorithm, or not? I believe that's what @progfolio is referring to above.
I've made some progress on the https://github.com/progfolio/elpaca/tree/feat/refactor branch.
First, I refactored the way build steps are determined.
The elpaca-build-steps-functions can be used to contextually determine the correct build steps for a package. This allowed for moving all of the Git-specific assumptions into a separate subpackage. I also implemented a subpackage to install single source files from disk. The :type recipe keyword is used to dispatch what type of package is desired. This also opens the door for other types of package sources (e.g. tarballs).
In addition, I've replaced the :pre-build and :post-build recipe keywords with a more flexible :build DSL. This combined with two new macros, elpaca-defstep (for conveniently defining elisp based build steps) and elpaca-defscript (the same for system binary based steps), allow for much more flexible build definitions.
The test case below demonstrates all of these features:
Test Case
(elpaca-test
:installer
"https://raw.githubusercontent.com/progfolio/elpaca/refs/heads/feat/refactor/doc/installer.el"
:ref "feat/refactor"
:early-init (setq elpaca-menu-functions '(elpaca-menu-declarations))
(let ((default-directory (expand-file-name "local-file-package" temporary-file-directory)))
(with-temp-buffer
(unless (file-exists-p default-directory)
(make-directory default-directory))
(insert
";;; local-file-package.el --- a local file test -*- lexical-binding: t; -*-
;; Copyright (C) 2025
;; Author: <n@ness>
;; Keywords:
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;;
;;; Code:
;;;###autoload
(defun local-file-package ()
\"A local file test\"
(interactive)
(message \"COMMAND TEST: PASS\"))
(provide 'local-file-package)
")
(write-region (point-min) (point-max) "local-file-package.el")))
:init
(setq +elpaca-env-test "PASS")
(elpaca `(local-file-package :type file :main
"/tmp/local-file-package/local-file-package.el"
:build (:before elpaca--queue-dependencies
,(elpaca-defscript script-test
'("pwd")
'("date"))
,(elpaca-defstep testing nil
(message "env-test: %S" ,+elpaca-env-test)))
:wait t))
(local-file-package)
(princ (elpaca-log "| script |")))
Host Env
| elpaca | c4047f8 HEAD -> feat/refactor, origin/feat/refactor |
| installer | 0.11 |
| emacs | GNU Emacs 31.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.50, cairo version 1.18.4) of 2025-09-12 |
| git | git version 2.51.0 |
Output
INFO Scraping 17 files for loaddefs...
INFO Scraping 17 files for loaddefs...done
GEN ../elpaca-autoloads.el
Cloning into '/tmp/elpaca.UdzT1u/elpaca/repos/elpaca'...
Switched to a new branch 'feat/refactor'
branch 'feat/refactor' set up to track 'origin/feat/refactor'.
Checking /tmp/elpaca.UdzT1u/elpaca/repos/elpaca...
Compiling /tmp/elpaca.UdzT1u/elpaca/repos/elpaca/elpaca-git.el...
Compiling /tmp/elpaca.UdzT1u/elpaca/repos/elpaca/elpaca-info.el...
Compiling /tmp/elpaca.UdzT1u/elpaca/repos/elpaca/elpaca-local.el...
Compiling /tmp/elpaca.UdzT1u/elpaca/repos/elpaca/elpaca-log.el...
Compiling /tmp/elpaca.UdzT1u/elpaca/repos/elpaca/elpaca-manager.el...
Compiling /tmp/elpaca.UdzT1u/elpaca/repos/elpaca/elpaca-menu-elpa.el...
Compiling /tmp/elpaca.UdzT1u/elpaca/repos/elpaca/elpaca-menu-melpa.el...
Compiling /tmp/elpaca.UdzT1u/elpaca/repos/elpaca/elpaca-menu-org.el...
Compiling /tmp/elpaca.UdzT1u/elpaca/repos/elpaca/elpaca-process.el...
Compiling /tmp/elpaca.UdzT1u/elpaca/repos/elpaca/elpaca-test.el...
Compiling /tmp/elpaca.UdzT1u/elpaca/repos/elpaca/elpaca-ui.el...
Compiling /tmp/elpaca.UdzT1u/elpaca/repos/elpaca/elpaca.el...
Checking /tmp/elpaca.UdzT1u/elpaca/repos/elpaca/doc...
Compiling /tmp/elpaca.UdzT1u/elpaca/repos/elpaca/doc/early-init.el...
Compiling /tmp/elpaca.UdzT1u/elpaca/repos/elpaca/doc/init.el...
Compiling /tmp/elpaca.UdzT1u/elpaca/repos/elpaca/doc/installer.el...
Checking /tmp/elpaca.UdzT1u/elpaca/repos/elpaca/extensions...
Compiling /tmp/elpaca.UdzT1u/elpaca/repos/elpaca/extensions/elpaca-use-package.el...
Checking /tmp/elpaca.UdzT1u/elpaca/repos/elpaca/images...
Checking /tmp/elpaca.UdzT1u/elpaca/repos/elpaca/test...
Compiling /tmp/elpaca.UdzT1u/elpaca/repos/elpaca/test/elpaca-tests.el...
Done (Total of 14 files compiled, 3 skipped in 4 directories)
COMMAND TEST: PASS
local-file-package script script-test-1 00.059567
local-file-package script $pwd 00.059820
local-file-package script /tmp/local-file-package 00.060814
local-file-package script script-test-2 00.061370
local-file-package script $date 00.061600
local-file-package script Sun Sep 28 03:17:50 PM EDT 2025 00.063221
local-file-package script $/usr/bin/emacs-31.0.50 -Q --batch --eval (setq gc-cons-percentage 1.0 print-level nil print-circle nil) --eval (progn nil (message "env-test: %S" "PASS")) 00.064107
local-file-package script env-test: "PASS" 00.107498
local-file-package script elpaca-with-emacs-local-file-package complete 00.110281
Ideally, I'd like to unify elpaca-defstep and elpaca-defscript.
Anyone feeling adventurous can try running the elpaca-test above and playing around with it.
Thank you for your patience while I work out the design considerations.
This looks like a big step forward! I'm glad to see this, both for single-file and local-repo cases. Is it close enough for me to try, or should I wait til it's merged?
This looks like a big step forward! I'm glad to see this, both for single-file and local-repo cases. Is it close enough for me to try, or should I wait til it's merged?
I would say hold till merged. I'll ping this thread when ready.