nixpkgs/pkgs/build-support/emacs/melpa.nix
Lin Jian ee46aa8a13
melpaBuild: allow nix unstable version format
Before, an unstable version of melpaBuild has to be in MELPA format,
which has some disadvantages:
- existing update scripts cannot be reused[1]
- it causes inconsistence.

This patch fixes that by allowing an unstable version to be in Nix
format.

We heuristically detect if it is an unstable version in Nix format.
If so, we convert it to MELPA format.

This does not bring evaluation performance overhead.  Here is my
benchmark result using hyperfine-1.18.0 and nix-2.18.1.

Without this patch:

Benchmark 1: NIXPKGS_ALLOW_BROKEN=1 nix eval --include nixpkgs=$PWD --file . emacs.pkgs.melpaPackages --apply 'pkgSet: map (drv: drv.drvPath) (builtins.filter (p: p.type or null == "derivation") (builtins.attrValues pkgSet))' --no-eval-cache >/dev/null
  Time (mean ± σ):      9.126 s ±  0.048 s    [User: 6.531 s, System: 0.997 s]
  Range (min … max):    9.056 s …  9.186 s    10 runs

With this patch applied:

Benchmark 1: NIXPKGS_ALLOW_BROKEN=1 nix eval --include nixpkgs=$PWD --file . emacs.pkgs.melpaPackages --apply 'pkgSet: map (drv: drv.drvPath) (builtins.filter (p: p.type or null == "derivation") (builtins.attrValues pkgSet))' --no-eval-cache >/dev/null
  Time (mean ± σ):      9.124 s ±  0.057 s    [User: 6.522 s, System: 1.011 s]
  Range (min … max):    9.040 s …  9.220 s    10 runs

[1]: 177c9eddad/pkgs/applications/editors/emacs/elisp-packages/manual-packages/lsp-bridge/default.nix (L93-L108)
2024-06-03 05:29:23 +08:00

144 lines
3.6 KiB
Nix

# builder for Emacs packages built for packages.el
# using MELPA package-build.el
{ lib, stdenv, fetchFromGitHub, emacs, texinfo, writeText, gcc }:
let
genericBuild = import ./generic.nix { inherit lib stdenv emacs texinfo writeText gcc; };
packageBuild = stdenv.mkDerivation {
name = "package-build";
src = fetchFromGitHub {
owner = "melpa";
repo = "package-build";
rev = "c48aa078c01b4f07b804270c4583a0a58ffea1c0";
sha256 = "sha256-MzPj375upIiYXdQR+wWXv3A1zMqbSrZlH0taLuxx/1M=";
};
patches = [ ./package-build-dont-use-mtime.patch ];
dontConfigure = true;
dontBuild = true;
installPhase = "
mkdir -p $out
cp -r * $out
";
};
in
{ /*
pname: Nix package name without special symbols and without version or
"emacs-" prefix.
*/
pname
/*
ename: Original Emacs package name, possibly containing special symbols.
Default: pname
*/
, ename ? pname
/*
version: Either a stable version such as "1.2" or an unstable version.
An unstable version can use either Nix format (preferred) such as
"1.2-unstable-2024-06-01" or MELPA format such as "20240601.1230".
*/
, version
/*
commit: Optional package history commit.
Default: src.rev or "unknown"
This will be written into the generated package but it is not needed during
the build process.
*/
, commit ? (args.src.rev or "unknown")
/*
files: Optional recipe property specifying the files used to build the package.
If null, do not set it in recipe, keeping the default upstream behaviour.
Default: null
*/
, files ? null
/*
recipe: Optional MELPA recipe.
Default: a minimally functional recipe
*/
, recipe ? (writeText "${pname}-recipe" ''
(${ename} :fetcher git :url ""
${lib.optionalString (files != null) ":files ${files}"})
'')
, meta ? {}
, ...
}@args:
genericBuild ({
elpa2nix = ./elpa2nix.el;
melpa2nix = ./melpa2nix.el;
inherit packageBuild commit ename recipe;
melpaVersion =
let
parsed = lib.flip builtins.match version
# match <version>-unstable-YYYY-MM-DD format
"^.*-unstable-([[:digit:]]{4})-([[:digit:]]{2})-([[:digit:]]{2})$";
unstableVersionInNixFormat = parsed != null; # heuristics
date = builtins.concatStringsSep "" parsed;
time = "0"; # unstable version in nix format lacks this info
in
if unstableVersionInNixFormat
then date + "." + time
else version;
preUnpack = ''
mkdir -p "$NIX_BUILD_TOP/recipes"
if [ -n "$recipe" ]; then
cp "$recipe" "$NIX_BUILD_TOP/recipes/$ename"
fi
ln -s "$packageBuild" "$NIX_BUILD_TOP/package-build"
mkdir -p "$NIX_BUILD_TOP/packages"
'';
postUnpack = ''
mkdir -p "$NIX_BUILD_TOP/working"
ln -s "$NIX_BUILD_TOP/$sourceRoot" "$NIX_BUILD_TOP/working/$ename"
'';
buildPhase = ''
runHook preBuild
cd "$NIX_BUILD_TOP"
emacs --batch -Q \
-L "$NIX_BUILD_TOP/package-build" \
-l "$melpa2nix" \
-f melpa2nix-build-package \
$ename $melpaVersion $commit
runHook postBuild
'';
installPhase = ''
runHook preInstall
archive="$NIX_BUILD_TOP/packages/$ename-$melpaVersion.el"
if [ ! -f "$archive" ]; then
archive="$NIX_BUILD_TOP/packages/$ename-$melpaVersion.tar"
fi
emacs --batch -Q \
-l "$elpa2nix" \
-f elpa2nix-install-package \
"$archive" "$out/share/emacs/site-lisp/elpa"
runHook postInstall
'';
meta = {
homepage = args.src.meta.homepage or "https://melpa.org/#/${pname}";
} // meta;
}
// removeAttrs args [ "meta" ])