Unverified Commit 8670e496 authored by Matthieu Coudron's avatar Matthieu Coudron Committed by GitHub
Browse files

Merge pull request #227714 from ony/feature/generateLuarocksConfig-toLua

lua.lib: use toLua in generateLuarocksConfig
parents 68378870 82e9b3f3
Loading
Loading
Loading
Loading
+21 −3
Original line number Diff line number Diff line
@@ -434,6 +434,7 @@ ${expr "" v}
   Configuration:
     * multiline - by default is true which results in indented block-like view.
     * indent - initial indent.
     * asBindings - by default generate single value, but with this use attrset to set global vars.

   Attention:
     Regardless of multiline parameter there is no trailing newline.
@@ -464,18 +465,35 @@ ${expr "" v}
    /* If this option is true, the output is indented with newlines for attribute sets and lists */
    multiline ? true,
    /* Initial indentation level */
    indent ? ""
    indent ? "",
    /* Interpret as variable bindings */
    asBindings ? false,
  }@args: v:
    with builtins;
    let
      innerIndent = "${indent}  ";
      introSpace = if multiline then "\n${innerIndent}" else " ";
      outroSpace = if multiline then "\n${indent}" else " ";
      innerArgs = args // { indent = innerIndent; };
      innerArgs = args // {
        indent = if asBindings then indent else innerIndent;
        asBindings = false;
      };
      concatItems = concatStringsSep ",${introSpace}";
      isLuaInline = { _type ? null, ... }: _type == "lua-inline";

      generatedBindings =
          assert lib.assertMsg (badVarNames == []) "Bad Lua var names: ${toPretty {} badVarNames}";
          libStr.concatStrings (
            lib.attrsets.mapAttrsToList (key: value: "${indent}${key} = ${toLua innerArgs value}\n") v
            );

      # https://en.wikibooks.org/wiki/Lua_Programming/variable#Variable_names
      matchVarName = match "[[:alpha:]_][[:alnum:]_]*(\\.[[:alpha:]_][[:alnum:]_]*)*";
      badVarNames = filter (name: matchVarName name == null) (attrNames v);
    in
    if v == null then
    if asBindings then
      generatedBindings
    else if v == null then
      "nil"
    else if isInt v || isFloat v || isString v || isBool v then
      builtins.toJSON v
+40 −0
Original line number Diff line number Diff line
@@ -4,6 +4,11 @@
with import ../default.nix;

let
  testingThrow = expr: {
    expr = (builtins.tryEval (builtins.seq expr "didn't throw"));
    expected = { success = false; value = false; };
  };
  testingDeepThrow = expr: testingThrow (builtins.deepSeq expr expr);

  testSanitizeDerivationName = { name, expected }:
  let
@@ -962,6 +967,41 @@ runTests {
    expected = ''{ 41, 43 }'';
  };

  testToLuaEmptyBindings = {
    expr = generators.toLua { asBindings = true; } {};
    expected = "";
  };

  testToLuaBindings = {
    expr = generators.toLua { asBindings = true; } { x1 = 41; _y = { a = 43; }; };
    expected = ''
      _y = {
        ["a"] = 43
      }
      x1 = 41
    '';
  };

  testToLuaPartialTableBindings = {
    expr = generators.toLua { asBindings = true; } { "x.y" = 42; };
    expected = ''
      x.y = 42
    '';
  };

  testToLuaIndentedBindings = {
    expr = generators.toLua { asBindings = true; indent = "  "; } { x = { y = 42; }; };
    expected = "  x = {\n    [\"y\"] = 42\n  }\n";
  };

  testToLuaBindingsWithSpace = testingThrow (
    generators.toLua { asBindings = true; } { "with space" = 42; }
  );

  testToLuaBindingsWithLeadingDigit = testingThrow (
    generators.toLua { asBindings = true; } { "11eleven" = 42; }
  );

  testToLuaBasicExample = {
    expr = generators.toLua {} {
      cmd = [ "typescript-language-server" "--stdio" ];
+35 −42
Original line number Diff line number Diff line
{ pkgs, lib, lua }:
let
  inherit (lib.generators) toLua;
  requiredLuaModules = drvs: with lib; let
    modules =  filter hasLuaModule drvs;
  in unique ([lua] ++ modules ++ concatLists (catAttrs "requiredLuaModules" modules));
@@ -88,58 +89,50 @@ rec {
    , rocksSubdir
    }: let
      rocksTrees = lib.imap0
        (i: dep: "{ name = [[dep-${toString i}]], root = '${dep}', rocks_dir = '${dep}/${dep.rocksSubdir}' }")
        (i: dep: { name = "dep-${toString i}"; root = "${dep}"; rocks_dir = "${dep}/${dep.rocksSubdir}"; })
        requiredLuaRocks;

      # Explicitly point luarocks to the relevant locations for multiple-output
      # derivations that are external dependencies, to work around an issue it has
      # (https://github.com/luarocks/luarocks/issues/766)
      depVariables = lib.concatMap ({name, dep}: [
        "${name}_INCDIR='${lib.getDev dep}/include';"
        "${name}_LIBDIR='${lib.getLib dep}/lib';"
        "${name}_BINDIR='${lib.getBin dep}/bin';"
      ]) externalDeps';
      depVariables = zipAttrsWithLast (lib.lists.map ({name, dep}: {
        "${name}_INCDIR" = "${lib.getDev dep}/include";
        "${name}_LIBDIR" = "${lib.getLib dep}/lib";
        "${name}_BINDIR" = "${lib.getBin dep}/bin";
      }) externalDeps');
      zipAttrsWithLast = lib.attrsets.zipAttrsWith (name: lib.lists.last);

      # example externalDeps': [ { name = "CRYPTO"; dep = pkgs.openssl; } ]
      externalDeps' = lib.filter (dep: !lib.isDerivation dep) externalDeps;

      externalDepsDirs = map
        (x: "'${builtins.toString x}'")
        (x: builtins.toString x)
        (lib.filter (lib.isDerivation) externalDeps);

      extraVariablesStr = lib.concatStringsSep "\n "
        (lib.mapAttrsToList (k: v: "${k}='${v}';") extraVariables);
  in ''
    local_cache = ""
    -- To prevent collisions when creating environments, we install the rock
    -- files into per-package subdirectories
    rocks_subdir = '${rocksSubdir}'
    -- first tree is the default target where new rocks are installed,
    -- any other trees in the list are treated as additional sources of installed rocks for matching dependencies.
    rocks_trees = {
      {name = "current", root = '${placeholder "out"}', rocks_dir = "current" },
      ${lib.concatStringsSep "\n, " rocksTrees}
    }
  '' + lib.optionalString lua.pkgs.isLuaJIT ''
    -- Luajit provides some additional functionality built-in; this exposes
    -- that to luarock's dependency system
  in toLua { asBindings = true; } ({
    local_cache = "";
    # To prevent collisions when creating environments, we install the rock
    # files into per-package subdirectories
    rocks_subdir = rocksSubdir;
    # first tree is the default target where new rocks are installed,
    # any other trees in the list are treated as additional sources of installed rocks for matching dependencies.
    rocks_trees = (
      [{name = "current"; root = "${placeholder "out"}"; rocks_dir = "current"; }] ++
      rocksTrees
    );
  } // lib.optionalAttrs lua.pkgs.isLuaJIT {
    # Luajit provides some additional functionality built-in; this exposes
    # that to luarock's dependency system
    rocks_provided = {
      jit='${lua.luaversion}-1';
      ffi='${lua.luaversion}-1';
      luaffi='${lua.luaversion}-1';
      bit='${lua.luaversion}-1';
    }
  '' + ''
    -- For single-output external dependencies
    external_deps_dirs = {
      ${lib.concatStringsSep "\n, " externalDepsDirs}
    }
    variables = {
      -- Some needed machinery to handle multiple-output external dependencies,
      -- as per https://github.com/luarocks/luarocks/issues/766
      ${lib.optionalString (lib.length depVariables > 0) ''
        ${lib.concatStringsSep "\n  " depVariables}''}
      ${extraVariablesStr}
    }
  '';
      jit = "${lua.luaversion}-1";
      ffi = "${lua.luaversion}-1";
      luaffi = "${lua.luaversion}-1";
      bit = "${lua.luaversion}-1";
    };
  } // {
    # For single-output external dependencies
    external_deps_dirs = externalDepsDirs;
    # Some needed machinery to handle multiple-output external dependencies,
    # as per https://github.com/luarocks/luarocks/issues/766
    variables = (depVariables // extraVariables);
  });
}