about summary refs log tree commit diff
path: root/pkgs/applications/editors/emacs/build-support/melpa.nix
blob: 29b3567ec6f4016cdd64792db50d16da6da0132a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# 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" ])