Recently I wrote an article about NonGNU ELPA and I promised to check for myself how easy it is to submit a new package there. I made good on my promise and in this article I’ll briefly describe the process.

I chose to use clojure-mode for my small experiment, mostly because it doesn’t have any dependencies, which simplifies the submission.1 Here’s the submission process step by step:

  • Clone NonGNU ELPA’s git repository:
$ git clone https://git.savannah.gnu.org/cgit/emacs/nongnu.git
  • Create a new branch for your changes there:
$ git checkout -B add-new-package
  • Edit the file elpa-packages in the root of the repository. You basically need to add one section there for each package. Here’s what I added for clojure-mode:
("clojure-mode"
 :url "https://github.com/clojure-emacs/clojure-mode"
 :ignored-files ("clojure-mode-extra-font-locking.el" "doc" "test" "test.clj")
 :readme "README.md"
 :news "CHANGELOG.md")

I believe the format is pretty self-explanatory, but you can read more about it here. In particular there are some nuances about the default assumptions that you have to be aware of (e.g. for :readme this is README, README.rst, README.org or the commentary section of the package).

Note that it’s important to tag your releases in git, so the build process will be able to identify them automatically. Otherwise you’ll have to manually map git commit to releases, as in this example:

("haskell-mode"	:url "https://github.com/haskell/haskell-mode"
 :doc "doc/haskell-mode.texi"
 :ignored-files ("images" "test" "logo.svg")
 ;; See https://github.com/haskell/haskell-mode/issues/1755
 ;;
 ;; Until a version tag is added, the commit of the latest tag is
 ;; used to determine the last stable release:
 ;; https://github.com/haskell/haskell-mode/releases/tag/17.2
 :version-map ((nil "17.2" "e72677668f5fc7cc148008e885a0f256e245dd43")))

Note: As mentioned in the comments it seems I was mistaken about this part. In reality the build process checks only the Version metadata of the package to figure out the package version. I can imagine this causing problems in some cases (e.g. if you don’t update your version metadata after doing a release), but I’ll have to look more carefully into the implementation.

  • (Optional) Try to build your package locally. The process is well-documented, so I won’t duplicate the instructions here. As most packages are trivial to build (e.g. they are a single Emacs Lisp file), the majority of the time you don’t really have to verify this.

  • Create a patch. This step might be a bit foreign to people who have only used git pull requests, but it’s pretty simple:

$ git format-patch

This will create a file named something like 0001-elpa-packages-clojure-mode-Add-package.patch.

  • Send the patch to the emacs-devel mailing list. There your patch will be reviewed and eventually applied by some of Emacs’s maintainers.

That’s it! I have to admit that the process is much simpler than I expected it would be! Now all you have to do is wait for your package to be eventually built and published. Here’s the end result for clojure-mode. At this point you can install clojure-mode from NonGNU ELPA!

In the end of the day it turned out that submitting your packages on NonGNU ELPA is almost as easy as submitting them to MELPA. There’s no overhead for the development process (everything stays the way you like), there are no additional copyright requirements. Actually, everything in this article applies to GNU ELPA as well, with the caveat that you’ll have to assign the copyright for your packages to the FSF and you’ll be limited when it comes to accepting contributions from people who haven’t signed the FSF copyright agreement.

That’s all I have for you today. I hope this article will inspire some (more?) of you to submit their favorite packages to NonGNU ELPA!2 I’ve already submitted patches for a few more packages that I maintain, and I hope to eventually have my entire Emacs “portfolio” available there. Keep hacking!

  1. Packages on NonGNU ELPA can only have dependencies available in GNU ELPA and NonGNU ELPA. 

  2. Don’t forget that this package repository will be enabled by default in Emacs 28.