summary refs log tree commit diff
path: root/maintainers
diff options
context:
space:
mode:
authorMatthieu Coudron <mcoudron@hotmail.com>2021-07-30 02:25:15 +0200
committerMatthieu Coudron <mcoudron@hotmail.com>2021-08-09 21:37:56 +0200
commit560a4e4e086ea748a7836c62a167db959d3767d2 (patch)
treefc09ab4c55b6b2fd1b53162aed63687e2365ef9f /maintainers
parent7b554c947764b14cec5d6b839a6d52666190e223 (diff)
downloadnixpkgs-560a4e4e086ea748a7836c62a167db959d3767d2.tar
nixpkgs-560a4e4e086ea748a7836c62a167db959d3767d2.tar.gz
nixpkgs-560a4e4e086ea748a7836c62a167db959d3767d2.tar.bz2
nixpkgs-560a4e4e086ea748a7836c62a167db959d3767d2.tar.lz
nixpkgs-560a4e4e086ea748a7836c62a167db959d3767d2.tar.xz
nixpkgs-560a4e4e086ea748a7836c62a167db959d3767d2.tar.zst
nixpkgs-560a4e4e086ea748a7836c62a167db959d3767d2.zip
update-luarocks-packages: use pluginupdate.py
Trying to reuse the update scripts used by kakoune/vim to provide the
user with an unified convergence. Some stuff doesn't work yet (parallel
download, caching) but I (anyone else welcome to try too) will improve
it in other PRs.
Diffstat (limited to 'maintainers')
-rw-r--r--maintainers/scripts/luarocks-packages.csv176
-rw-r--r--maintainers/scripts/pluginupdate.py78
-rwxr-xr-xmaintainers/scripts/update-luarocks-packages283
3 files changed, 304 insertions, 233 deletions
diff --git a/maintainers/scripts/luarocks-packages.csv b/maintainers/scripts/luarocks-packages.csv
index c5cee697c8f..6ad159a7fff 100644
--- a/maintainers/scripts/luarocks-packages.csv
+++ b/maintainers/scripts/luarocks-packages.csv
@@ -1,89 +1,87 @@
-# nix name,luarocks name,server,version,luaversion,maintainers
-alt-getopt,,,,,arobyn
-ansicolors,,,,,
-argparse,,,,,
-basexx,,,,,
-binaryheap,,,,,vcunat
-bit32,,,,lua5_1,lblasc
-busted,,,,,
-cassowary,,,,,marsam alerque
-cjson,lua-cjson,,,,
-compat53,,,,,vcunat
-cosmo,,,,,marsam
-coxpcall,,,1.17.0-1,,
-cqueues,,,,,vcunat
-cyrussasl,,,,,
-digestif,,,,lua5_3,
-dkjson,,,,,
-fifo,,,,,
-gitsigns.nvim,,,,lua5_1,
-http,,,,,vcunat
-inspect,,,,,
-ldbus,,http://luarocks.org/dev,,,
-ldoc,,,,,
-lgi,,,,,
-linenoise,,,,,
-ljsyscall,,,,lua5_1,lblasc
-lpeg,,,,,vyp
-lpeg_patterns,,,,,
-lpeglabel,,,,,
-lpty,,,,,
-lrexlib-gnu,,,,,
-lrexlib-pcre,,,,,vyp
-lrexlib-posix,,,,,
-ltermbox,,,,,
-lua-cmsgpack,,,,,
-lua-iconv,,,,,
-lua-lsp,,http://luarocks.org/dev,,,
-lua-messagepack,,,,,
-lua-resty-http,,,,,
-lua-resty-jwt,,,,,
-lua-resty-openidc,,,,,
-lua-resty-openssl,,,,,
-lua-resty-session,,,,,
-lua-term,,,,,
-lua-toml,,,,,
-lua-zlib,,,,,koral
-lua_cliargs,,,,,
-luabitop,,,,,
-luacheck,,,,,
-luacov,,,,,
-luadbi,,,,,
-luadbi-mysql,,,,,
-luadbi-postgresql,,,,,
-luadbi-sqlite3,,,,,
-luadoc,,,,,
-luaepnf,,,,,
-luaevent,,,,,
-luaexpat,,,1.3.0-1,,arobyn flosse
-luaffi,,http://luarocks.org/dev,,,
-luafilesystem,,,1.7.0-2,,flosse
-lualogging,,,,,
-luaossl,,,,lua5_1,
-luaposix,,,,,vyp lblasc
-luarepl,,,,,
-luasec,,,,,flosse
-luasocket,,,,,
-luasql-sqlite3,,,,,vyp
-luassert,,,,,
-luasystem,,,,,
-luautf8,,,,,pstn
-luazip,,,,,
-lua-yajl,,,,,pstn
-luuid,,,,,
-luv,,,,,
-lyaml,,,,,lblasc
-markdown,,,,,
-mediator_lua,,,,,
-mpack,,,,,
-moonscript,,,,,arobyn
-nvim-client,,,,,
-penlight,,,,,
-plenary.nvim,,,,lua5_1,
-rapidjson,,,,,
-readline,,,,,
-say,,,,,
-std-_debug,std._debug,,,,
-std_normalize,std.normalize,,,,
-stdlib,,,,,vyp
-vstruct,,,,,
+name,server,version,luaversion,maintainers
+bit32,,,lua5_1,lblasc
+argparse,,,,
+basexx,,,,
+binaryheap,,,,vcunat
+busted,,,,
+cassowary,,,,marsam alerque
+compat53,,,,vcunat
+cosmo,,,,marsam
+coxpcall,,1.17.0-1,,
+cqueues,,,,vcunat
+cyrussasl,,,,
+digestif,,,lua5_3,
+dkjson,,,,
+fifo,,,,
+gitsigns.nvim,,,lua5_1,
+http,,,,vcunat
+inspect,,,,
+ldbus,http://luarocks.org/dev,,,
+ldoc,,,,
+lgi,,,,
+linenoise,,,,
+ljsyscall,,,lua5_1,lblasc
+lpeg,,,,vyp
+lpeg_patterns,,,,
+lpeglabel,,,,
+lpty,,,,
+lrexlib-gnu,,,,
+lrexlib-pcre,,,,vyp
+lrexlib-posix,,,,
+ltermbox,,,,
+lua-cjson,,,,
+lua-cmsgpack,,,,
+lua-iconv,,,,
+lua-lsp,http://luarocks.org/dev,,,
+lua-messagepack,,,,
+lua-resty-http,,,,
+lua-resty-jwt,,,,
+lua-resty-openidc,,,,
+lua-resty-openssl,,,,
+lua-resty-session,,,,
+lua-term,,,,
+lua-toml,,,,
+lua-zlib,,,,koral
+lua_cliargs,,,,
+luabitop,,,,
+luacheck,,,,
+luacov,,,,
+luadbi,,,,
+luadbi-mysql,,,,
+luadbi-postgresql,,,,
+luadbi-sqlite3,,,,
+luadoc,,,,
+luaepnf,,,,
+luaevent,,,,
+luaexpat,,1.3.0-1,,arobyn flosse
+luaffi,http://luarocks.org/dev,,,
+luafilesystem,,1.7.0-2,,flosse
+lualogging,,,,
+luaossl,,,lua5_1,
+luaposix,,,,vyp lblasc
+luarepl,,,,
+luasec,,,,flosse
+luasocket,,,,
+luasql-sqlite3,,,,vyp
+luassert,,,,
+luasystem,,,,
+luautf8,,,,pstn
+luazip,,,,
+lua-yajl,,,,pstn
+luuid,,,,
+luv,,,,
+lyaml,,,,lblasc
+markdown,,,,
+mediator_lua,,,,
+mpack,,,,
+moonscript,,,,arobyn
+nvim-client,,,,
+penlight,,,,
+plenary.nvim,,,lua5_1,
+rapidjson,,,,
+readline,,,,
+say,,,,
+std._debug,,,,
+std.normalize,,,,
+stdlib,,,,vyp
+vstruct,,,,
diff --git a/maintainers/scripts/pluginupdate.py b/maintainers/scripts/pluginupdate.py
index 91c5214d153..45511607b03 100644
--- a/maintainers/scripts/pluginupdate.py
+++ b/maintainers/scripts/pluginupdate.py
@@ -28,6 +28,7 @@ from pathlib import Path
 from typing import Dict, List, Optional, Tuple, Union, Any, Callable
 from urllib.parse import urljoin, urlparse
 from tempfile import NamedTemporaryFile
+from dataclasses import dataclass
 
 import git
 
@@ -82,6 +83,13 @@ def make_request(url: str) -> urllib.request.Request:
         headers["Authorization"] = f"token {token}"
     return urllib.request.Request(url, headers=headers)
 
+@dataclass
+class PluginDesc:
+    owner: str
+    repo: str
+    branch: str
+    alias: str
+
 
 class Repo:
     def __init__(
@@ -195,21 +203,46 @@ class Editor:
         name: str,
         root: Path,
         get_plugins: str,
+        # TODO modifier pour accepter un plugin
         generate_nix: Callable[[List[Tuple[str, str, Plugin]], str], None],
         default_in: Optional[Path] = None,
         default_out: Optional[Path] = None,
         deprecated: Optional[Path] = None,
         cache_file: Optional[str] = None,
     ):
+        log.debug("get_plugins:", get_plugins)
         self.name = name
         self.root = root
         self.get_plugins = get_plugins
-        self.generate_nix = generate_nix
+        self._generate_nix = generate_nix
         self.default_in = default_in or root.joinpath(f"{name}-plugin-names")
         self.default_out = default_out or root.joinpath("generated.nix")
         self.deprecated = deprecated or root.joinpath("deprecated.json")
         self.cache_file = cache_file or f"{name}-plugin-cache.json"
 
+    def get_current_plugins(self):
+        """To fill the cache"""
+        return get_current_plugins(self)
+
+    def load_plugin_spec(self, plugin_file) -> List[PluginDesc]:
+        return load_plugin_spec(plugin_file)
+
+    def generate_nix(self, plugins, outfile):
+        '''Returns nothing for now, writes directly to outfile'''
+        self._generate_nix(plugins, outfile)
+
+    def get_update(self, input_file: str, outfile: str, proc: int):
+        return get_update(input_file, outfile, proc, editor=self)
+
+    @property
+    def attr_path(self):
+        return self.name + "Plugins"
+
+    def rewrite_input(self, *args, **kwargs):
+        return rewrite_input(*args, **kwargs)
+
+
+
 
 class CleanEnvironment(object):
     def __enter__(self) -> None:
@@ -228,7 +261,9 @@ class CleanEnvironment(object):
 
 def get_current_plugins(editor: Editor) -> List[Plugin]:
     with CleanEnvironment():
-        out = subprocess.check_output(["nix", "eval", "--json", editor.get_plugins])
+        cmd = ["nix", "eval", "--json", editor.get_plugins]
+        log.debug("Running command %s", cmd)
+        out = subprocess.check_output(cmd)
     data = json.loads(out)
     plugins = []
     for name, attr in data.items():
@@ -244,12 +279,13 @@ def prefetch_plugin(
     alias: Optional[str],
     cache: "Optional[Cache]" = None,
 ) -> Tuple[Plugin, Dict[str, str]]:
-    log.info("Prefetching plugin %s", repo_name)
+    log.info(f"Fetching last commit for plugin {user}/{repo_name}@{branch}")
     repo = Repo(user, repo_name, branch, alias)
     commit, date = repo.latest_commit()
     has_submodules = repo.has_submodules()
     cached_plugin = cache[commit] if cache else None
     if cached_plugin is not None:
+        log.debug("Cache hit !")
         cached_plugin.name = alias or repo_name
         cached_plugin.date = date
         return cached_plugin, repo.redirect
@@ -306,8 +342,7 @@ def check_results(
 
         sys.exit(1)
 
-
-def parse_plugin_line(line: str) -> Tuple[str, str, str, Optional[str]]:
+def parse_plugin_line(line: str) -> PluginDesc:
     branch = "master"
     alias = None
     name, repo = line.split("/")
@@ -317,15 +352,15 @@ def parse_plugin_line(line: str) -> Tuple[str, str, str, Optional[str]]:
     if "@" in repo:
         repo, branch = repo.split("@")
 
-    return (name.strip(), repo.strip(), branch.strip(), alias)
+    return PluginDesc(name.strip(), repo.strip(), branch.strip(), alias)
 
 
-def load_plugin_spec(plugin_file: str) -> List[Tuple[str, str, str, Optional[str]]]:
+def load_plugin_spec(plugin_file: str) -> List[PluginDesc]:
     plugins = []
     with open(plugin_file) as f:
         for line in f:
             plugin = parse_plugin_line(line)
-            if not plugin[0]:
+            if not plugin.owner:
                 msg = f"Invalid repository {line}, must be in the format owner/repo[ as alias]"
                 print(msg, file=sys.stderr)
                 sys.exit(1)
@@ -387,12 +422,11 @@ class Cache:
 
 
 def prefetch(
-    args: Tuple[str, str, str, Optional[str]], cache: Cache
+    args: PluginDesc, cache: Cache
 ) -> Tuple[str, str, Union[Exception, Plugin], dict]:
-    assert len(args) == 4
-    owner, repo, branch, alias = args
+    owner, repo = args.owner, args.repo
     try:
-        plugin, redirect = prefetch_plugin(owner, repo, branch, alias, cache)
+        plugin, redirect = prefetch_plugin(owner, repo, args.branch, args.alias, cache)
         cache[plugin.commit] = plugin
         return (owner, repo, plugin, redirect)
     except Exception as e:
@@ -433,7 +467,7 @@ def rewrite_input(
     with open(input_file, "w") as f:
         f.writelines(lines)
 
-
+# TODO move to Editor ?
 def parse_args(editor: Editor):
     parser = argparse.ArgumentParser(
         description=(
@@ -446,7 +480,7 @@ def parse_args(editor: Editor):
         dest="add_plugins",
         default=[],
         action="append",
-        help=f"Plugin to add to {editor.name}Plugins from Github in the form owner/repo",
+        help=f"Plugin to add to {editor.attr_path} from Github in the form owner/repo",
     )
     parser.add_argument(
         "--input-names",
@@ -493,11 +527,11 @@ def commit(repo: git.Repo, message: str, files: List[Path]) -> None:
 
 
 def get_update(input_file: str, outfile: str, proc: int, editor: Editor):
-    cache: Cache = Cache(get_current_plugins(editor), editor.cache_file)
+    cache: Cache = Cache(editor.get_current_plugins(), editor.cache_file)
     _prefetch = functools.partial(prefetch, cache=cache)
 
     def update() -> dict:
-        plugin_names = load_plugin_spec(input_file)
+        plugin_names = editor.load_plugin_spec(input_file)
 
         try:
             pool = Pool(processes=proc)
@@ -522,33 +556,33 @@ def update_plugins(editor: Editor):
 
     log.info("Start updating plugins")
     nixpkgs_repo = git.Repo(editor.root, search_parent_directories=True)
-    update = get_update(args.input_file, args.outfile, args.proc, editor)
+    update = editor.get_update(args.input_file, args.outfile, args.proc)
 
     redirects = update()
-    rewrite_input(args.input_file, editor.deprecated, redirects)
+    editor.rewrite_input(args.input_file, editor.deprecated, redirects)
 
     autocommit = not args.no_commit
 
     if autocommit:
-        commit(nixpkgs_repo, f"{editor.name}Plugins: update", [args.outfile])
+        commit(nixpkgs_repo, f"{editor.attr_path}: update", [args.outfile])
 
     if redirects:
         update()
         if autocommit:
             commit(
                 nixpkgs_repo,
-                f"{editor.name}Plugins: resolve github repository redirects",
+                f"{editor.attr_path}: resolve github repository redirects",
                 [args.outfile, args.input_file, editor.deprecated],
             )
 
     for plugin_line in args.add_plugins:
-        rewrite_input(args.input_file, editor.deprecated, append=(plugin_line + "\n",))
+        editor.rewrite_input(args.input_file, editor.deprecated, append=(plugin_line + "\n",))
         update()
         plugin = fetch_plugin_from_pluginline(plugin_line)
         if autocommit:
             commit(
                 nixpkgs_repo,
-                "{editor}Plugins.{name}: init at {version}".format(
+                "{editor.attr_path}.{name}: init at {version}".format(
                     editor=editor.name, name=plugin.normalized_name, version=plugin.version
                 ),
                 [args.outfile, args.input_file],
diff --git a/maintainers/scripts/update-luarocks-packages b/maintainers/scripts/update-luarocks-packages
index c7180083da2..2524b4c9b89 100755
--- a/maintainers/scripts/update-luarocks-packages
+++ b/maintainers/scripts/update-luarocks-packages
@@ -1,140 +1,179 @@
 #!/usr/bin/env nix-shell
-#!nix-shell update-luarocks-shell.nix -i bash
+#!nix-shell -p nix-prefetch-git luarocks-nix python3 python3Packages.GitPython nix -i python3
+
+# format:
+# $ nix run nixpkgs.python3Packages.black -c black update.py
+# type-check:
+# $ nix run nixpkgs.python3Packages.mypy -c mypy update.py
+# linted:
+# $ nix run nixpkgs.python3Packages.flake8 -c flake8 --ignore E501,E265,E402 update.py
+
+import inspect
+import os
+import tempfile
+import shutil
+from dataclasses import dataclass
+import subprocess
+import csv
+import logging
+
+from typing import List
+from pathlib import Path
+
+LOG_LEVELS = {
+    logging.getLevelName(level): level for level in [
+        logging.DEBUG, logging.INFO, logging.WARN, logging.ERROR ]
+}
 
-# You'll likely want to use
-# ``
-# nixpkgs $ maintainers/scripts/update-luarocks-packages pkgs/development/lua-modules/generated-packages.nix
-# ``
-# to update all libraries in that folder.
-# to debug, redirect stderr to stdout with 2>&1
+log = logging.getLogger()
+log.addHandler(logging.StreamHandler())
 
-# stop the script upon C-C
-set -eu -o pipefail
+ROOT = Path(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))).parent.parent
+from pluginupdate import Editor, parse_args, update_plugins, PluginDesc, CleanEnvironment
 
-CSV_FILE="maintainers/scripts/luarocks-packages.csv"
+PKG_LIST="maintainers/scripts/luarocks-packages.csv"
 TMP_FILE="$(mktemp)"
-# Set in the update-luarocks-shell.nix
-NIXPKGS_PATH="$LUAROCKS_NIXPKGS_PATH"
-export LUAROCKS_CONFIG="$NIXPKGS_PATH/maintainers/scripts/luarocks-config.lua"
-
-# 10 is a pretty arbitrary number of simultaneous jobs, but it is generally
-# impolite to hit a webserver with *too* many simultaneous connections :)
-PARALLEL_JOBS=1
+GENERATED_NIXFILE="pkgs/development/lua-modules/generated-packages.nix"
+LUAROCKS_CONFIG="$NIXPKGS_PATH/maintainers/scripts/luarocks-config.lua"
 
-exit_trap() {
-    local lc="$BASH_COMMAND" rc=$?
-    test $rc -eq 0 || echo -e "*** error $rc: $lc.\nGenerated temporary file in $TMP_FILE" >&2
-}
-
-print_help() {
-    echo "Usage: $0 <GENERATED_FILE>"
-    echo "(most likely pkgs/development/lua-modules/generated-packages.nix)"
-    echo ""
-    echo " -c <CSV_FILE> to set the list of luarocks package to generate"
-    exit 1
-}
-
-if [ $# -lt 1 ]; then
-    print_help
-    exit 1
-fi
-
-trap exit_trap EXIT
-
-while getopts ":hc:" opt; do
-    case $opt in
-    h)
-        print_help
-        ;;
-    c)
-        echo "Loading package list from $OPTARG !" >&2
-        CSV_FILE="$OPTARG"
-        ;;
-    \?)
-        echo "Invalid option: -$OPTARG" >&2
-        ;;
-    esac
-    shift $((OPTIND - 1))
-done
-
-GENERATED_NIXFILE="$1"
-
-HEADER="
-/* ${GENERATED_NIXFILE} is an auto-generated file -- DO NOT EDIT!
+HEADER = """
+/* {GENERATED_NIXFILE} is an auto-generated file -- DO NOT EDIT!
 Regenerate it with:
-nixpkgs$ ${0} ${GENERATED_NIXFILE}
+nixpkgs$ ./maintainers/scripts/update-luarocks-packages
 
-These packages are manually refined in lua-overrides.nix
+You can customize the generated packages in pkgs/development/lua-modules/overrides.nix
 */
-{ self, stdenv, lib, fetchurl, fetchgit, pkgs, ... } @ args:
+""".format(GENERATED_NIXFILE=GENERATED_NIXFILE)
+
+FOOTER="""
+}
+/* GENERATED - do not edit this file */
+"""
+
+@dataclass
+class LuaPlugin:
+    name: str
+    version: str
+    server: str
+    luaversion: str
+    maintainers: str
+
+    @property
+    def normalized_name(self) -> str:
+        return self.name.replace(".", "-")
+
+# rename Editor to LangUpdate/ EcosystemUpdater
+class LuaEditor(Editor):
+    def get_current_plugins(self):
+        return []
+
+    def load_plugin_spec(self, input_file) -> List[PluginDesc]:
+        luaPackages = []
+        csvfilename=input_file
+        log.info("Loading package descriptions from %s", csvfilename)
+
+
+        with open(csvfilename, newline='') as csvfile:
+            reader = csv.DictReader(csvfile,)
+            for row in reader:
+                # name,server,version,luaversion,maintainers
+                plugin = LuaPlugin(**row)
+                luaPackages.append(plugin)
+        return luaPackages
+
+    @property
+    def attr_path(self):
+        return "luaPackages"
+
+    def get_update(self, input_file: str, outfile: str, _: int):
+
+        def update() -> dict:
+            plugin_specs = self.load_plugin_spec(input_file)
+
+            self.generate_nix(plugin_specs, outfile)
+
+            redirects = []
+            return redirects
+
+        return update
+
+    def rewrite_input(self, *args, **kwargs):
+        # not implemented yet
+        pass
+
+def generate_nix(
+    plugins: List[LuaPlugin],
+    outfilename: str
+    ):
+    sorted_plugins = sorted(plugins, key=lambda v: v.name.lower())
+
+    # plug = {}
+    # selon le manifest luarocks.org/manifest
+    def _generate_pkg_nix(plug):
+        cmd = [ "luarocks", "nix", plug.name]
+        if plug.server:
+            cmd.append(f"--only-server={plug.server}")
+
+        if plug.maintainers:
+            cmd.append(f"--maintainers={plug.maintainers}")
+
+        if plug.version:
+            cmd.append(plug.version)
+
+        if plug.luaversion:
+            with CleanEnvironment():
+                local_pkgs = str(ROOT.resolve())
+                cmd2 = ["nix-build", "--no-out-link", local_pkgs, "-A", f"{plug.luaversion}"]
+
+                log.debug("running %s", cmd2)
+                lua_drv_path=subprocess.check_output(cmd2, text=True).strip()
+                cmd.append(f"--lua-dir={lua_drv_path}/bin")
+
+        log.debug("running %s", cmd)
+        output = subprocess.check_output(cmd, text=True)
+        return output
+
+    with tempfile.NamedTemporaryFile("w+") as f:
+        f.write(HEADER)
+        f.write("""
+{ self, stdenv, lib, fetchurl, fetchgit, ... } @ args:
 self: super:
 with self;
 {
-"
+""")
 
-FOOTER="
-}
-/* GENERATED */
-"
-
-function convert_pkg() {
-    nix_pkg_name="$1"
-    lua_pkg_name="$2"
-    server="$3"
-    pkg_version="$4"
-    lua_version="$5"
-    maintainers="$6"
-
-    if [ "${nix_pkg_name:0:1}" == "#" ]; then
-        echo "Skipping comment ${*}" >&2
-        return
-    fi
-
-    # Normalize package name
-    nix_pkg_name_normalized=$(sed 's/\./-/' <(echo "$nix_pkg_name"))
-
-    if [ -z "$lua_pkg_name" ]; then
-        echo "Using nix_name as lua_pkg_name for '$nix_pkg_name'" >&2
-        lua_pkg_name="$nix_pkg_name"
-    fi
-
-    echo "Building expression for $lua_pkg_name (version $pkg_version) from server [$server]" >&2
-    luarocks_args=(nix)
-    if [[ -n $server ]]; then
-        luarocks_args+=("--only-server=$server")
-    fi
-    if [[ -n $maintainers ]]; then
-        luarocks_args+=("--maintainers=$maintainers")
-    fi
-    if [[ -n $lua_version ]]; then
-        lua_drv_path=$(nix-build --no-out-link "$NIXPKGS_PATH" -A "$lua_version")
-        luarocks_args+=("--lua-dir=$lua_drv_path/bin")
-    fi
-    luarocks_args+=("$lua_pkg_name")
-    if [[ -n $pkg_version ]]; then
-        luarocks_args+=("$pkg_version")
-    fi
-    echo "Running 'luarocks ${luarocks_args[*]}'" >&2
-    if drv="$nix_pkg_name_normalized = $(luarocks "${luarocks_args[@]}")"; then
-        echo "$drv"
-    else
-        echo "Failed to convert $nix_pkg_name" >&2
-        return 1
-    fi
-}
+        for plugin in sorted_plugins:
+
+            nix_expr = _generate_pkg_nix(plugin)
+            f.write(f"{plugin.normalized_name} = {nix_expr}"
+            )
+        f.write(FOOTER)
+        f.flush()
+
+        # if everything went fine, move the generated file to its destination
+        # using copy since move doesn't work across disks
+        shutil.copy(f.name, outfilename)
+
+    print(f"updated {outfilename}")
+
+def load_plugin_spec():
+    pass
+
+
+def main():
+
+    editor = LuaEditor("lua", ROOT, '', generate_nix,
+        default_in = ROOT.joinpath(PKG_LIST),
+        default_out = ROOT.joinpath(GENERATED_NIXFILE)
+        )
+
+    args = parse_args(editor)
+    log.setLevel(LOG_LEVELS[args.debug])
 
-# params needed when called via callPackage
-echo "$HEADER" | tee "$TMP_FILE"
+    update_plugins(editor)
 
-# Ensure parallel can run our bash function
-export -f convert_pkg
-export SHELL=bash
-# Read each line in the csv file and run convert_pkg for each, in parallel
-parallel --group --keep-order --halt now,fail=1 --jobs "$PARALLEL_JOBS" --colsep ',' convert_pkg {} <"$CSV_FILE" | tee -a "$TMP_FILE"
 
-# close the set
-echo "$FOOTER" | tee -a "$TMP_FILE"
+if __name__ == "__main__":
 
-cp "$TMP_FILE" "$GENERATED_NIXFILE"
+    main()
 
-# vim: set ts=4 sw=4 ft=sh: