lol

luarocks-packages-update: init (#262156)

* luarocks-packages-updater: init

Goal is to make it possible to maintain out-of-tree luarocks packages
without needing to clone nixpkgs.

maintainers/scripts/update-luarocks-packages gets renamed to
pkgs/development/lua-modules/updater/updater.py

Once merged you can run for instance
nix run nixpkgs#luarocks-packages-updater -- -i contrib/luarocks-packages.csv -o contrib/generated-packages.nix

I also set the parallelism (--proc) to 1 by default else luarocks fails
because of https://github.com/luarocks/luarocks/issues/1540

* Update maintainers/scripts/pluginupdate.py

Co-authored-by: Marc Jakobi <mrcjkb89@outlook.com>

---------

Co-authored-by: Marc Jakobi <mrcjkb89@outlook.com>

authored by

Matthieu Coudron
Marc Jakobi
and committed by
GitHub
f15e58cb 24df0476

+290 -243
+3 -3
doc/languages-frameworks/lua.section.md
··· 134 134 135 135 Luarocks-based packages are generated in [pkgs/development/lua-modules/generated-packages.nix](https://github.com/NixOS/nixpkgs/tree/master/pkgs/development/lua-modules/generated-packages.nix) from 136 136 the whitelist maintainers/scripts/luarocks-packages.csv and updated by running 137 - the script 138 - [maintainers/scripts/update-luarocks-packages](https://github.com/NixOS/nixpkgs/tree/master/maintainers/scripts/update-luarocks-packages): 137 + the package `luarocks-packages-updater`: 139 138 140 139 ```sh 141 - ./maintainers/scripts/update-luarocks-packages update 140 + 141 + nix-shell -p luarocks-packages-updater --run luarocks-packages-updater 142 142 ``` 143 143 144 144 [luarocks2nix](https://github.com/nix-community/luarocks) is a tool capable of generating nix derivations from both rockspec and src.rock (and favors the src.rock).
+12 -3
maintainers/scripts/pluginupdate.py
··· 468 468 "--input-names", 469 469 "-i", 470 470 dest="input_file", 471 + type=Path, 471 472 default=self.default_in, 472 473 help="A list of plugins in the form owner/repo", 473 474 ) ··· 476 477 "-o", 477 478 dest="outfile", 478 479 default=self.default_out, 480 + type=Path, 479 481 help="Filename to save generated nix code", 480 482 ) 481 483 common.add_argument( ··· 787 789 788 790 if autocommit: 789 791 from datetime import date 790 - editor.nixpkgs_repo = git.Repo(editor.root, search_parent_directories=True) 791 - updated = date.today().strftime('%m-%d-%Y') 792 792 793 - commit(editor.nixpkgs_repo, f"{editor.attr_path}: updated the {updated}", [args.outfile]) 793 + try: 794 + repo = git.Repo(os.getcwd()) 795 + updated = date.today().strftime('%m-%d-%Y') 796 + print(args.outfile) 797 + commit(repo, 798 + f"{editor.attr_path}: updated the {updated}", [args.outfile] 799 + ) 800 + except git.InvalidGitRepositoryError as e: 801 + print(f"Not in a git repository: {e}", file=sys.stderr) 802 + sys.exit(1) 794 803 795 804 if redirects: 796 805 update()
-224
maintainers/scripts/update-luarocks-packages
··· 1 - #!/usr/bin/env nix-shell 2 - #!nix-shell update-luarocks-shell.nix -i python3 3 - 4 - # format: 5 - # $ nix run nixpkgs#python3Packages.black -- update.py 6 - # type-check: 7 - # $ nix run nixpkgs#python3Packages.mypy -- update.py 8 - # linted: 9 - # $ nix run nixpkgs#python3Packages.flake8 -- --ignore E501,E265,E402 update.py 10 - 11 - import inspect 12 - import os 13 - import tempfile 14 - import shutil 15 - from dataclasses import dataclass 16 - import subprocess 17 - import csv 18 - import logging 19 - import textwrap 20 - from multiprocessing.dummy import Pool 21 - 22 - from typing import List, Tuple, Optional 23 - from pathlib import Path 24 - 25 - log = logging.getLogger() 26 - log.addHandler(logging.StreamHandler()) 27 - 28 - ROOT = Path(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))).parent.parent # type: ignore 29 - import pluginupdate 30 - from pluginupdate import update_plugins, FetchConfig, CleanEnvironment 31 - 32 - PKG_LIST = "maintainers/scripts/luarocks-packages.csv" 33 - TMP_FILE = "$(mktemp)" 34 - GENERATED_NIXFILE = "pkgs/development/lua-modules/generated-packages.nix" 35 - LUAROCKS_CONFIG = "maintainers/scripts/luarocks-config.lua" 36 - 37 - HEADER = """/* {GENERATED_NIXFILE} is an auto-generated file -- DO NOT EDIT! 38 - Regenerate it with: 39 - nixpkgs$ ./maintainers/scripts/update-luarocks-packages 40 - 41 - You can customize the generated packages in pkgs/development/lua-modules/overrides.nix 42 - */ 43 - """.format( 44 - GENERATED_NIXFILE=GENERATED_NIXFILE 45 - ) 46 - 47 - FOOTER = """ 48 - } 49 - /* GENERATED - do not edit this file */ 50 - """ 51 - 52 - 53 - @dataclass 54 - class LuaPlugin: 55 - name: str 56 - """Name of the plugin, as seen on luarocks.org""" 57 - src: str 58 - """address to the git repository""" 59 - ref: Optional[str] 60 - """git reference (branch name/tag)""" 61 - version: Optional[str] 62 - """Set it to pin a package """ 63 - server: Optional[str] 64 - """luarocks.org registers packages under different manifests. 65 - Its value can be 'http://luarocks.org/dev' 66 - """ 67 - luaversion: Optional[str] 68 - """Attribue of the lua interpreter if a package is available only for a specific lua version""" 69 - maintainers: Optional[str] 70 - """ Optional string listing maintainers separated by spaces""" 71 - 72 - @property 73 - def normalized_name(self) -> str: 74 - return self.name.replace(".", "-") 75 - 76 - 77 - # rename Editor to LangUpdate/ EcosystemUpdater 78 - class LuaEditor(pluginupdate.Editor): 79 - def get_current_plugins(self): 80 - return [] 81 - 82 - def load_plugin_spec(self, input_file) -> List[LuaPlugin]: 83 - luaPackages = [] 84 - csvfilename = input_file 85 - log.info("Loading package descriptions from %s", csvfilename) 86 - 87 - with open(csvfilename, newline="") as csvfile: 88 - reader = csv.DictReader( 89 - csvfile, 90 - ) 91 - for row in reader: 92 - # name,server,version,luaversion,maintainers 93 - plugin = LuaPlugin(**row) 94 - luaPackages.append(plugin) 95 - return luaPackages 96 - 97 - def update(self, args): 98 - update_plugins(self, args) 99 - 100 - def generate_nix(self, results: List[Tuple[LuaPlugin, str]], outfilename: str): 101 - with tempfile.NamedTemporaryFile("w+") as f: 102 - f.write(HEADER) 103 - header2 = textwrap.dedent( 104 - # header2 = inspect.cleandoc( 105 - """ 106 - { self, stdenv, lib, fetchurl, fetchgit, callPackage, ... } @ args: 107 - final: prev: 108 - { 109 - """ 110 - ) 111 - f.write(header2) 112 - for plugin, nix_expr in results: 113 - f.write(f"{plugin.normalized_name} = {nix_expr}") 114 - f.write(FOOTER) 115 - f.flush() 116 - 117 - # if everything went fine, move the generated file to its destination 118 - # using copy since move doesn't work across disks 119 - shutil.copy(f.name, outfilename) 120 - 121 - print(f"updated {outfilename}") 122 - 123 - @property 124 - def attr_path(self): 125 - return "luaPackages" 126 - 127 - def get_update(self, input_file: str, outfile: str, config: FetchConfig): 128 - _prefetch = generate_pkg_nix 129 - 130 - def update() -> dict: 131 - plugin_specs = self.load_plugin_spec(input_file) 132 - sorted_plugin_specs = sorted(plugin_specs, key=lambda v: v.name.lower()) 133 - 134 - try: 135 - pool = Pool(processes=config.proc) 136 - results = pool.map(_prefetch, sorted_plugin_specs) 137 - finally: 138 - pass 139 - 140 - self.generate_nix(results, outfile) 141 - 142 - redirects = {} 143 - return redirects 144 - 145 - return update 146 - 147 - def rewrite_input(self, input_file: str, *args, **kwargs): 148 - # vim plugin reads the file before update but that shouldn't be our case 149 - # not implemented yet 150 - # fieldnames = ['name', 'server', 'version', 'luaversion', 'maintainers'] 151 - # input_file = "toto.csv" 152 - # with open(input_file, newline='') as csvfile: 153 - # writer = csv.DictWriter(csvfile, fieldnames=fieldnames) 154 - # writer.writeheader() 155 - # for row in reader: 156 - # # name,server,version,luaversion,maintainers 157 - # plugin = LuaPlugin(**row) 158 - # luaPackages.append(plugin) 159 - pass 160 - 161 - 162 - def generate_pkg_nix(plug: LuaPlugin): 163 - """ 164 - Generate nix expression for a luarocks package 165 - Our cache key associates "p.name-p.version" to its rockspec 166 - """ 167 - log.debug("Generating nix expression for %s", plug.name) 168 - custom_env = os.environ.copy() 169 - custom_env["LUAROCKS_CONFIG"] = LUAROCKS_CONFIG 170 - 171 - # we add --dev else luarocks wont find all the "scm" (=dev) versions of the 172 - # packages 173 - # , "--dev" 174 - cmd = ["luarocks", "nix"] 175 - 176 - if plug.maintainers: 177 - cmd.append(f"--maintainers={plug.maintainers}") 178 - 179 - # if plug.server == "src": 180 - if plug.src != "": 181 - if plug.src is None: 182 - msg = ( 183 - "src must be set when 'version' is set to \"src\" for package %s" 184 - % plug.name 185 - ) 186 - log.error(msg) 187 - raise RuntimeError(msg) 188 - log.debug("Updating from source %s", plug.src) 189 - cmd.append(plug.src) 190 - # update the plugin from luarocks 191 - else: 192 - cmd.append(plug.name) 193 - if plug.version and plug.version != "src": 194 - cmd.append(plug.version) 195 - 196 - if plug.server != "src" and plug.server: 197 - cmd.append(f"--only-server={plug.server}") 198 - 199 - if plug.luaversion: 200 - cmd.append(f"--lua-version={plug.luaversion}") 201 - 202 - log.debug("running %s", " ".join(cmd)) 203 - 204 - output = subprocess.check_output(cmd, env=custom_env, text=True) 205 - output = "callPackage(" + output.strip() + ") {};\n\n" 206 - return (plug, output) 207 - 208 - 209 - def main(): 210 - editor = LuaEditor( 211 - "lua", 212 - ROOT, 213 - "", 214 - default_in=ROOT.joinpath(PKG_LIST), 215 - default_out=ROOT.joinpath(GENERATED_NIXFILE), 216 - ) 217 - 218 - editor.run() 219 - 220 - 221 - if __name__ == "__main__": 222 - main() 223 - 224 - # vim: set ft=python noet fdm=manual fenc=utf-8 ff=unix sts=0 sw=4 ts=4 :
-13
maintainers/scripts/update-luarocks-shell.nix
··· 1 - { nixpkgs ? import ../.. { } 2 - }: 3 - with nixpkgs; 4 - let 5 - pyEnv = python3.withPackages(ps: [ ps.gitpython ]); 6 - in 7 - mkShell { 8 - packages = [ 9 - pyEnv 10 - luarocks-nix 11 - nix-prefetch-scripts 12 - ]; 13 - }
+4
nixos/doc/manual/release-notes/rl-2311.section.md
··· 162 162 163 163 - `getent` has been moved from `glibc`'s `bin` output to its own dedicated output, reducing closure size for many dependents. Dependents using the `getent` alias should not be affected; others should move from using `glibc.bin` or `getBin glibc` to `getent` (which also improves compatibility with non-glibc platforms). 164 164 165 + - `maintainers/scripts/update-luarocks-packages` is now a proper package 166 + `luarocks-packages-updater` that can be run to maintain out-of-tree luarocks 167 + packages 168 + 165 169 - The `users.users.<name>.passwordFile` has been renamed to `users.users.<name>.hashedPasswordFile` to avoid possible confusions. The option is in fact the file-based version of `hashedPassword`, not `password`, and expects a file containing the {manpage}`crypt(3)` hash of the user password. 166 170 167 171 - The `services.ananicy.extraRules` option now has the type of `listOf attrs` instead of `string`.
+49
pkgs/development/lua-modules/updater/default.nix
··· 1 + { buildPythonApplication 2 + , nix 3 + , makeWrapper 4 + , python3Packages 5 + , lib 6 + # , nix-prefetch-git 7 + , nix-prefetch-scripts 8 + , luarocks-nix 9 + }: 10 + let 11 + 12 + path = lib.makeBinPath [ nix nix-prefetch-scripts luarocks-nix ]; 13 + in 14 + buildPythonApplication { 15 + pname = "luarocks-packages-updater"; 16 + version = "0.1"; 17 + 18 + format = "other"; 19 + 20 + nativeBuildInputs = [ 21 + makeWrapper 22 + python3Packages.wrapPython 23 + ]; 24 + propagatedBuildInputs = [ 25 + python3Packages.gitpython 26 + ]; 27 + 28 + dontUnpack = true; 29 + 30 + installPhase = 31 + '' 32 + mkdir -p $out/bin $out/lib 33 + cp ${./updater.py} $out/bin/luarocks-packages-updater 34 + cp ${../../../../maintainers/scripts/pluginupdate.py} $out/lib/pluginupdate.py 35 + 36 + # wrap python scripts 37 + makeWrapperArgs+=( --prefix PATH : "${path}" --prefix PYTHONPATH : "$out/lib" ) 38 + wrapPythonProgramsIn "$out" 39 + ''; 40 + 41 + shellHook = '' 42 + export PYTHONPATH="maintainers/scripts:$PYTHONPATH" 43 + export PATH="${path}:$PATH" 44 + ''; 45 + 46 + meta.mainProgram = "luarocks-packages-updater"; 47 + } 48 + 49 +
+217
pkgs/development/lua-modules/updater/updater.py
··· 1 + #!/usr/bin/env python 2 + # format: 3 + # $ nix run nixpkgs#python3Packages.black -- update.py 4 + # type-check: 5 + # $ nix run nixpkgs#python3Packages.mypy -- update.py 6 + # linted: 7 + # $ nix run nixpkgs#python3Packages.flake8 -- --ignore E501,E265,E402 update.py 8 + 9 + import inspect 10 + import os 11 + import tempfile 12 + import shutil 13 + from dataclasses import dataclass 14 + import subprocess 15 + import csv 16 + import logging 17 + import textwrap 18 + from multiprocessing.dummy import Pool 19 + 20 + from typing import List, Tuple, Optional 21 + from pathlib import Path 22 + 23 + log = logging.getLogger() 24 + log.addHandler(logging.StreamHandler()) 25 + 26 + ROOT = Path(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))).parent.parent # type: ignore 27 + import pluginupdate 28 + from pluginupdate import update_plugins, FetchConfig, CleanEnvironment 29 + 30 + PKG_LIST = "maintainers/scripts/luarocks-packages.csv" 31 + TMP_FILE = "$(mktemp)" 32 + GENERATED_NIXFILE = "pkgs/development/lua-modules/generated-packages.nix" 33 + 34 + HEADER = """/* {GENERATED_NIXFILE} is an auto-generated file -- DO NOT EDIT! 35 + Regenerate it with: nix run nixpkgs#update-luarocks-packages 36 + You can customize the generated packages in pkgs/development/lua-modules/overrides.nix 37 + */ 38 + """.format( 39 + GENERATED_NIXFILE=GENERATED_NIXFILE 40 + ) 41 + 42 + FOOTER = """ 43 + } 44 + /* GENERATED - do not edit this file */ 45 + """ 46 + 47 + 48 + @dataclass 49 + class LuaPlugin: 50 + name: str 51 + """Name of the plugin, as seen on luarocks.org""" 52 + src: str 53 + """address to the git repository""" 54 + ref: Optional[str] 55 + """git reference (branch name/tag)""" 56 + version: Optional[str] 57 + """Set it to pin a package """ 58 + server: Optional[str] 59 + """luarocks.org registers packages under different manifests. 60 + Its value can be 'http://luarocks.org/dev' 61 + """ 62 + luaversion: Optional[str] 63 + """Attribue of the lua interpreter if a package is available only for a specific lua version""" 64 + maintainers: Optional[str] 65 + """ Optional string listing maintainers separated by spaces""" 66 + 67 + @property 68 + def normalized_name(self) -> str: 69 + return self.name.replace(".", "-") 70 + 71 + 72 + # rename Editor to LangUpdate/ EcosystemUpdater 73 + class LuaEditor(pluginupdate.Editor): 74 + 75 + def create_parser(self): 76 + parser = super().create_parser() 77 + parser.set_defaults(proc=1) 78 + return parser 79 + 80 + def get_current_plugins(self): 81 + return [] 82 + 83 + def load_plugin_spec(self, input_file) -> List[LuaPlugin]: 84 + luaPackages = [] 85 + csvfilename = input_file 86 + log.info("Loading package descriptions from %s", csvfilename) 87 + 88 + with open(csvfilename, newline="") as csvfile: 89 + reader = csv.DictReader( 90 + csvfile, 91 + ) 92 + for row in reader: 93 + # name,server,version,luaversion,maintainers 94 + plugin = LuaPlugin(**row) 95 + luaPackages.append(plugin) 96 + return luaPackages 97 + 98 + def update(self, args): 99 + update_plugins(self, args) 100 + 101 + def generate_nix(self, results: List[Tuple[LuaPlugin, str]], outfilename: str): 102 + with tempfile.NamedTemporaryFile("w+") as f: 103 + f.write(HEADER) 104 + header2 = textwrap.dedent( 105 + """ 106 + { stdenv, lib, fetchurl, fetchgit, callPackage, ... } @ args: 107 + final: prev: 108 + { 109 + """ 110 + ) 111 + f.write(header2) 112 + for plugin, nix_expr in results: 113 + f.write(f"{plugin.normalized_name} = {nix_expr}") 114 + f.write(FOOTER) 115 + f.flush() 116 + 117 + # if everything went fine, move the generated file to its destination 118 + # using copy since move doesn't work across disks 119 + shutil.copy(f.name, outfilename) 120 + 121 + print(f"updated {outfilename}") 122 + 123 + @property 124 + def attr_path(self): 125 + return "luaPackages" 126 + 127 + def get_update(self, input_file: str, outfile: str, config: FetchConfig): 128 + _prefetch = generate_pkg_nix 129 + 130 + def update() -> dict: 131 + plugin_specs = self.load_plugin_spec(input_file) 132 + sorted_plugin_specs = sorted(plugin_specs, key=lambda v: v.name.lower()) 133 + 134 + try: 135 + pool = Pool(processes=config.proc) 136 + results = pool.map(_prefetch, sorted_plugin_specs) 137 + finally: 138 + pass 139 + 140 + self.generate_nix(results, outfile) 141 + 142 + redirects = {} 143 + return redirects 144 + 145 + return update 146 + 147 + def rewrite_input(self, input_file: str, *args, **kwargs): 148 + # vim plugin reads the file before update but that shouldn't be our case 149 + # not implemented yet 150 + # fieldnames = ['name', 'server', 'version', 'luaversion', 'maintainers'] 151 + # input_file = "toto.csv" 152 + # with open(input_file, newline='') as csvfile: 153 + # writer = csv.DictWriter(csvfile, fieldnames=fieldnames) 154 + # writer.writeheader() 155 + # for row in reader: 156 + # # name,server,version,luaversion,maintainers 157 + # plugin = LuaPlugin(**row) 158 + # luaPackages.append(plugin) 159 + pass 160 + 161 + 162 + def generate_pkg_nix(plug: LuaPlugin): 163 + """ 164 + Generate nix expression for a luarocks package 165 + Our cache key associates "p.name-p.version" to its rockspec 166 + """ 167 + log.debug("Generating nix expression for %s", plug.name) 168 + 169 + cmd = ["luarocks", "nix"] 170 + 171 + if plug.maintainers: 172 + cmd.append(f"--maintainers={plug.maintainers}") 173 + 174 + # if plug.server == "src": 175 + if plug.src != "": 176 + if plug.src is None: 177 + msg = ( 178 + "src must be set when 'version' is set to \"src\" for package %s" 179 + % plug.name 180 + ) 181 + log.error(msg) 182 + raise RuntimeError(msg) 183 + log.debug("Updating from source %s", plug.src) 184 + cmd.append(plug.src) 185 + # update the plugin from luarocks 186 + else: 187 + cmd.append(plug.name) 188 + if plug.version and plug.version != "src": 189 + cmd.append(plug.version) 190 + 191 + if plug.server != "src" and plug.server: 192 + cmd.append(f"--only-server={plug.server}") 193 + 194 + if plug.luaversion: 195 + cmd.append(f"--lua-version={plug.luaversion}") 196 + 197 + log.debug("running %s", " ".join(cmd)) 198 + 199 + output = subprocess.check_output(cmd, text=True) 200 + output = "callPackage(" + output.strip() + ") {};\n\n" 201 + return (plug, output) 202 + 203 + 204 + def main(): 205 + editor = LuaEditor( 206 + "lua", 207 + ROOT, 208 + "", 209 + default_in=PKG_LIST, 210 + default_out=GENERATED_NIXFILE, 211 + ) 212 + 213 + editor.run() 214 + 215 + 216 + if __name__ == "__main__": 217 + main()
+5
pkgs/top-level/all-packages.nix
··· 17766 17766 luarocks = luaPackages.luarocks; 17767 17767 luarocks-nix = luaPackages.luarocks-nix; 17768 17768 17769 + luarocks-packages-updater = callPackage ../development/lua-modules/updater { 17770 + inherit (python3Packages) buildPythonApplication ; 17771 + }; 17772 + 17773 + 17769 17774 luau = callPackage ../development/interpreters/luau { }; 17770 17775 17771 17776 lune = callPackage ../development/interpreters/lune { };