11

This is similar to this question but the answer there seems to be deprecated.

Let's say I'm using a layer and want hack the code of a particular package that layer is using. How do I go about it?


To better illustrate what I want to accomplish in general, I present a specific example.

I try to get the spotify layer to work, but the current master branch in the helm-spotify package uses a deprecated web API. There is a pull request to fix this and I want to try it and maybe contribute something. My problem is, that I can not get the local copy of helm-spotify to load.

What I tried was to switch to the develop branch of spacemacs:

git branch --track develop origin/develop
git checkout develop

In ~/.emacs.d/layers/spotify/packages.el

I changed from

(setq spotify-packages '(spotify helm-spotify))

To

(setq spotify-packages
          '(    
                spotify
                (helm-spotify :location local)
           ))

And pulled the helm-spotify repository to ~/.emacs.d/layers/spotify/local/helm-spotify

When I restart spacemacs I get

File error: Cannot open load file, no such file or directory, multi

In when I look into helm-spotify.el there is:

(require 'multi)

So my guess is, that when installing helm-spotify from melpa the dependency on multi gets resolved prior to loading helm-spotify but of course not anymore when I use a local copy of helm-spotify.

So my questions are:

  • How do resolve dependencies when using a local package?
  • Or should I do this completely differently from what I described?

I also tried, without success, to add multi to dotspacemacs-additional-packages and to spotify-packages:

(setq spotify-packages '(
                         multi ;; I added this
                         spotify
                         (helm-spotify :location local) ;; I modified here
                         ))

;; I added this
(defun spotify/init-multi ()
  (use-package multi))

;; the rest is as it was

(defun spotify/init-spotify ()
  (use-package spotify
    :config (spacemacs/set-leader-keys
              "amsp" 'spotify-playpause
              "amsn" 'spotify-next
              "amsN" 'spotify-previous
              "amsQ" 'spotify-quit)))

(when (configuration-layer/layer-usedp 'spacemacs-helm)
  (defun spotify/init-helm-spotify ()
    (use-package helm-spotify
      :config (spacemacs/set-leader-keys
                "amsg" 'helm-spotify))))

in packages.el. Also tried without adding multi to dotspacemacs-additional-packages.

  • AFAIK there isn't a way to automatically resolve dependencies when using local packages, since `package.el` (the built-in Emacs module) doesn't really see `local/helm-spotify` as a package. The way to resolve it is manually, and you are in the right direction. Can you add more detail how you tried to add `multi`? It's not clear if you added it to `additional-packages` and `spotify-packages` at the same time, or tried them separately. Having `multi` in `spotify-packages` and a `spotify/init-multi` function in `packages.el` (without using `additional-packages`) should be enough – bmag Feb 20 '16 at 20:48
  • Also, if you want to test a pull request without editing its code locally, you can use `recipe` instead of `local`. e.g. `(helm-spotify :location (recipe ))` – bmag Feb 20 '16 at 20:51
  • I just tried it without adding `multi` to `dotspacemacs-additional-packages` with no success. The error is the same. I updated my question to reflect the `packages.el` I'm using. Thanks for your effort! – Dimitri Schachmann Feb 20 '16 at 21:04
  • I think you found a bug, because I tried what I thought should work and I got the same error. It's late here so I can't dig deeper right now, but in the meantime you can either try using `recipe` instead of `local` (it should take care of the multi dependency for you), or move the `multi` configuration to a separate layer and make sure that layer is listed before `spotify` in `dotspacemacs-configuration-layers` (the layer list) – bmag Feb 20 '16 at 21:40

1 Answers1

14

First, you should never modify the code in master branch, Spacemacs is designed to be hackable while keeping the master branch read-only, also not that force pushes to master branch may happen!. If you really want to modify the code you should use the develop branch and keep it up to date manually. Develop branch is never forced push.

EDIT: actually you were using the develop branch, my apologies, I let the paragraph for reference.

Now the answer :-) The correct way to do what you want is to overwrite the location in dotspacemacs-additional-packages. I just tried it by forking helm-spotify in my namespace and then added:

   dotspacemacs-additional-packages
     '((helm-spotify :location (recipe :fetcher github :repo "syl20bnr/helm-spotify")))

Then upon restart Spacemacs fetched the package from my fork correctly instead of reaching MELPA. Spacemacs uses quelpa to fetch repositories from GitHub based on MELPA recipes, package.el is used to install the packages so dependencies are correctly resolved.

Note that:

  • you may have to manually delete the helm-spotify folder in ˜/.emacs.d/elpa directory and restart Emacs.
  • You still have to add the spotify layer to your dotspacemacs-configuration-layers variable.
syl20bnr
  • 2,095
  • 11
  • 21
  • 3
    You can also add a branch to the recipe: `:branch "my-branch"` – syl20bnr Feb 23 '16 at 03:13
  • This worked perfectly! Thank you a lot! – Dimitri Schachmann Feb 23 '16 at 14:33
  • Sorry if I'm slow to grasp, but could somebody please explain this is a stupid-form? So I'm using package _XYZ_, currently installed automatically by Spacemacs from Melpa. What exactly are the steps that need to be taken to switch this package to a local version? (Or one on a Github repo of mine, if that's necessary; but frankly it would be a quite annoying for the debugging of any changes.) What Spacemacs configuration files need to be tweaked, and in which way? – leftaroundabout Jun 20 '19 at 15:43
  • 1
    Alternatively create a directory with the name of the package in the `.emacs.d/private/local` directory, and add that directory to the load-path variable by adding `(some-package :location local)` to the list `dotspacemacs-additional-packages` within the `dotspacemacs/layers` function of your dotspacemacs file. After placing your package file into this package-directory the file can be loaded, without requiring the full path, by placing a `(require 'package-name)` within the body of the `dotspacemacs/user-config` function of your dotspacemacs file. - from spacemacs doc – Didier A. Apr 14 '20 at 02:24
  • 1
    Thank you for mentioning that you need to remove package from elpa directory. That was not obvious for me. – Astery Mar 03 '21 at 08:36