From f3bb9d5e34a178a2d40e409970c0f60aa13fe657 Mon Sep 17 00:00:00 2001
From: Hisham Muhammad <hisham@gobolinux.org>
Date: Sat, 23 Nov 2019 01:18:25 -0300
Subject: Add --check-lua-versions flag (#1115)

Only check for availability of a rock for other Lua versions
if the user explicitly requests so.
---
 src/luarocks/build.lua        |  1 +
 src/luarocks/cmd/build.lua    |  3 +-
 src/luarocks/cmd/download.lua |  4 +-
 src/luarocks/cmd/install.lua  |  6 ++-
 src/luarocks/cmd/make.lua     |  3 ++
 src/luarocks/cmd/unpack.lua   |  4 +-
 src/luarocks/core/cfg.lua     |  1 -
 src/luarocks/deps.lua         |  2 +-
 src/luarocks/download.lua     |  4 +-
 src/luarocks/search.lua       | 92 ++++++++++++++++++++++++-------------------
 10 files changed, 71 insertions(+), 49 deletions(-)

(limited to 'src')

diff --git a/src/luarocks/build.lua b/src/luarocks/build.lua
index 948c5f53..fe8a815e 100644
--- a/src/luarocks/build.lua
+++ b/src/luarocks/build.lua
@@ -20,6 +20,7 @@ build.opts = util.opts_table("build.opts", {
    namespace = "string?",
    branch = "string?",
    verify = "boolean",
+   check_lua_versions = "boolean",
 })
 
 do
diff --git a/src/luarocks/cmd/build.lua b/src/luarocks/cmd/build.lua
index 1819d0da..6b30666b 100644
--- a/src/luarocks/cmd/build.lua
+++ b/src/luarocks/cmd/build.lua
@@ -79,7 +79,7 @@ local function do_build(ns_name, version, opts)
    if ns_name:match("%.rockspec$") or ns_name:match("%.rock$") then
       url = ns_name
    else
-      url, err = search.find_src_or_rockspec(ns_name, version, true)
+      url, err = search.find_src_or_rockspec(ns_name, version, opts.check_lua_versions)
       if not url then
          return nil, err
       end
@@ -123,6 +123,7 @@ function cmd_build.command(args)
       namespace = args.namespace,
       branch = args.branch,
       verify = not not args.verify,
+      check_lua_versions = not not args.check_lua_versions,
    })
 
    if args.sign and not args.pack_binary_rock then
diff --git a/src/luarocks/cmd/download.lua b/src/luarocks/cmd/download.lua
index 5032d580..4beecdc3 100644
--- a/src/luarocks/cmd/download.lua
+++ b/src/luarocks/cmd/download.lua
@@ -19,6 +19,8 @@ function cmd_download.add_to_parser(parser)
       cmd:flag("--source", "Download .src.rock if available."),
       cmd:flag("--rockspec", "Download .rockspec if available."),
       cmd:option("--arch", "Download rock for a specific architecture."))
+   cmd:flag("--check-lua-versions", "If the rock can't be found, check repository "..
+      "and report if it is available for another Lua version.")
 end
 
 --- Driver function for the "download" command.
@@ -43,7 +45,7 @@ function cmd_download.command(args)
       arch = args.arch
    end
    
-   local dl, err = download.download(arch, name:lower(), args.version, args.all)
+   local dl, err = download.download(arch, name:lower(), args.version, args.all, args.check_lua_versions)
    return dl and true, err
 end
 
diff --git a/src/luarocks/cmd/install.lua b/src/luarocks/cmd/install.lua
index b4c87f7c..0fcec4ad 100644
--- a/src/luarocks/cmd/install.lua
+++ b/src/luarocks/cmd/install.lua
@@ -39,6 +39,8 @@ function install.add_to_parser(parser)
       "file should be already available locally in the same directory.\n"..
       "You need the signer’s public key in your local keyring for this "..
       "option to work properly.")
+   cmd:flag("--check-lua-versions", "If the rock can't be found, check repository "..
+      "and report if it is available for another Lua version.")
    util.deps_mode_option(cmd)
    -- luarocks build options
    parser:flag("--pack-binary-rock"):hidden(true)
@@ -236,7 +238,9 @@ function install.command(args)
          return install_rock_file(args.rock, opts)
       end
    else
-      local url, err = search.find_suitable_rock(queries.new(args.rock:lower(), args.version), true)
+      local url, err = search.find_rock_checking_lua_versions(
+                          queries.new(args.rock:lower(), args.version),
+                          args.check_lua_versions)
       if not url then
          return nil, err
       end
diff --git a/src/luarocks/cmd/make.lua b/src/luarocks/cmd/make.lua
index 0a1f99f0..74de6f26 100644
--- a/src/luarocks/cmd/make.lua
+++ b/src/luarocks/cmd/make.lua
@@ -35,6 +35,8 @@ function make.cmd_options(parser)
       "option to work properly.")
    parser:flag("--sign", "To be used with --pack-binary-rock. Also produce a "..
       "signature file for the generated .rock file.")
+   parser:flag("--check-lua-versions", "If the rock can't be found, check repository "..
+      "and report if it is available for another Lua version.")
    util.deps_mode_option(parser)
 end
 
@@ -94,6 +96,7 @@ function make.command(args)
       namespace = args.namespace,
       branch = args.branch,
       verify = not not args.verify,
+      check_lua_versions = not not args.check_lua_versions,
    })
 
    if args.sign and not args.pack_binary_rock then
diff --git a/src/luarocks/cmd/unpack.lua b/src/luarocks/cmd/unpack.lua
index fe0535e4..c2b5b983 100644
--- a/src/luarocks/cmd/unpack.lua
+++ b/src/luarocks/cmd/unpack.lua
@@ -23,6 +23,8 @@ In the latter case, the rock version may be given as a second argument.]],
       :args("?")
 
    cmd:flag("--force", "Unpack files even if the output directory already exists.")
+   cmd:flag("--check-lua-versions", "If the rock can't be found, check repository "..
+      "and report if it is available for another Lua version.")
 end
 
 --- Load a rockspec file to the given directory, fetches the source
@@ -155,7 +157,7 @@ function unpack.command(args)
    if ns_name:match(".*%.rock") or ns_name:match(".*%.rockspec") then
       url = ns_name
    else
-      url, err = search.find_src_or_rockspec(ns_name, args.version, true)
+      url, err = search.find_src_or_rockspec(ns_name, args.version, args.check_lua_versions)
       if not url then
          return nil, err
       end
diff --git a/src/luarocks/core/cfg.lua b/src/luarocks/core/cfg.lua
index 4e1b5108..e26c263c 100644
--- a/src/luarocks/core/cfg.lua
+++ b/src/luarocks/core/cfg.lua
@@ -191,7 +191,6 @@ local function make_defaults(lua_version, target_cpu, platforms, home)
 
       cache_timeout = 60,
       cache_fail_timeout = 86400,
-      version_check_on_fail = true,
 
       lua_modules_path = "/share/lua/"..lua_version,
       lib_modules_path = "/lib/lua/"..lua_version,
diff --git a/src/luarocks/deps.lua b/src/luarocks/deps.lua
index cb85764e..7f695d9c 100644
--- a/src/luarocks/deps.lua
+++ b/src/luarocks/deps.lua
@@ -165,7 +165,7 @@ function deps.fulfill_dependency(dep, deps_mode, name, version, rocks_provided,
       return nil, "Failed matching dependencies"
    end
 
-   local url, search_err = search.find_suitable_rock(dep, true)
+   local url, search_err = search.find_suitable_rock(dep)
    if not url then
       return nil, "Could not satisfy dependency "..tostring(dep)..": "..search_err
    end
diff --git a/src/luarocks/download.lua b/src/luarocks/download.lua
index 0620be68..145fefed 100644
--- a/src/luarocks/download.lua
+++ b/src/luarocks/download.lua
@@ -21,7 +21,7 @@ local function get_file(filename)
    end
 end
 
-function download.download(arch, name, version, all)
+function download.download(arch, name, version, all, check_lua_versions)
    local substring = (all and name == "")
    local query = queries.new(name, version, substring, arch)
    local search_err
@@ -53,7 +53,7 @@ function download.download(arch, name, version, all)
       end
    else
       local url
-      url, search_err = search.find_suitable_rock(query, true)
+      url, search_err = search.find_rock_checking_lua_versions(query, check_lua_versions)
       if url then
          return get_file(url)
       end
diff --git a/src/luarocks/search.lua b/src/luarocks/search.lua
index 9b13b7cc..efe3b9c9 100644
--- a/src/luarocks/search.lua
+++ b/src/luarocks/search.lua
@@ -205,17 +205,14 @@ end
 
 -- Find out which other Lua versions provide rock versions matching a query,
 -- @param query table: a query object.
--- @param cli boolean: print status messages as it works
 -- @return table: array of Lua versions supported, in "5.x" format.
-local function supported_lua_versions(query, cli)
+local function supported_lua_versions(query)
    assert(query:type() == "query")
    local result_tree = {}
 
    for lua_version in util.lua_versions() do
       if lua_version ~= cfg.lua_version then
-         if cli then
-            util.printout("Checking for Lua " .. lua_version .. "...")
-         end
+         util.printout("Checking for Lua " .. lua_version .. "...")
          if search.search_repos(query, lua_version)[query.name] then
             table.insert(result_tree, lua_version)
          end
@@ -225,21 +222,12 @@ local function supported_lua_versions(query, cli)
    return result_tree
 end
 
-function search.find_src_or_rockspec(ns_name, version, cli)
-   local query = queries.new(ns_name, version, false, "src|rockspec")
-   local url, err = search.find_suitable_rock(query, cli)
-   if not url then
-      return nil, "Could not find a result named "..tostring(query)..": "..err
-   end
-   return url
-end
-
 --- Attempt to get a single URL for a given search for a rock.
 -- @param query table: a query object.
--- @param cli boolean: print status messages as it works
--- @return string or (nil, string): URL for latest matching version
--- of the rock if it was found, or nil followed by an error message.
-function search.find_suitable_rock(query, cli)
+-- @return string or (nil, string, string): URL for latest matching version
+-- of the rock if it was found, or nil followed by an error message
+-- and an error code.
+function search.find_suitable_rock(query)
    assert(query:type() == "query")
 
    local rocks_provided = util.get_rocks_provided()
@@ -247,49 +235,71 @@ function search.find_suitable_rock(query, cli)
    if rocks_provided[query.name] ~= nil then
       -- Do not install versions listed in rocks_provided.
       return nil, "Rock "..query.name.." "..rocks_provided[query.name]..
-         " is already provided by VM or via 'rocks_provided' in the config file."
+         " is already provided by VM or via 'rocks_provided' in the config file.", "provided"
    end
    
    local result_tree = search.search_repos(query)
    local first_rock = next(result_tree)
    if not first_rock then
-      if cfg.version_check_on_fail then
-         if cli then
-            util.printout(query.name .. " not found for Lua " .. cfg.lua_version .. ".")
-            util.printout("Checking if available for other Lua versions...")
-         end
+      return nil, "No results matching query were found for Lua " .. cfg.lua_version .. ".", "notfound"
+   elseif next(result_tree, first_rock) then
+      -- Shouldn't happen as query must match only one package.
+      return nil, "Several rocks matched query.", "manyfound"
+   else
+      return pick_latest_version(query.name, result_tree[first_rock])
+   end
+end
+
+function search.find_src_or_rockspec(ns_name, version, check_lua_versions)
+   local query = queries.new(ns_name, version, false, "src|rockspec")
+   local url, err = search.find_rock_checking_lua_versions(query, check_lua_versions)
+   if not url then
+      return nil, "Could not find a result named "..tostring(query)..": "..err
+   end
+   return url
+end
+
+function search.find_rock_checking_lua_versions(query, check_lua_versions)
+   local url, err, errcode = search.find_suitable_rock(query)
+   if url then
+      return url
+   end
+
+   if errcode == "notfound" then
+      local add
+      if check_lua_versions then
+         util.printout(query.name .. " not found for Lua " .. cfg.lua_version .. ".")
+         util.printout("Checking if available for other Lua versions...")
       
          -- Check if constraints are satisfiable with other Lua versions.
-         local lua_versions = supported_lua_versions(query, cli)
-   
+         local lua_versions = supported_lua_versions(query)
+      
          if #lua_versions ~= 0 then
             -- Build a nice message in "only Lua 5.x and 5.y but not 5.z." format
             for i, lua_version in ipairs(lua_versions) do
                lua_versions[i] = "Lua "..lua_version
             end
-   
+      
             local versions_message = "only "..table.concat(lua_versions, " and ")..
-               " but not Lua "..cfg.lua_version..".\n"..
-               "(To suppress these checks run '"..
-               "luarocks --lua-version="..cfg.lua_version.." config version_check_on_fail false')"
-   
+               " but not Lua "..cfg.lua_version.."."
+      
             if #query.constraints == 0 then
-               return nil, query.name.." supports "..versions_message
+               add = query.name.." supports "..versions_message
             elseif #query.constraints == 1 and query.constraints[1].op == "==" then
-               return nil, query.name.." "..query.constraints[1].version.string.." supports "..versions_message
+               add = query.name.." "..query.constraints[1].version.string.." supports "..versions_message
             else
-               return nil, "Matching "..query.name.." versions support "..versions_message
+               add = "Matching "..query.name.." versions support "..versions_message
             end
+         else
+            add = query.name.." is not available for any Lua versions."
          end
+      else
+         add = "To check if it is available for other Lua versions, use --check-lua-versions."
       end
-
-      return nil, "No results matching query were found for Lua " .. cfg.lua_version .. "."
-   elseif next(result_tree, first_rock) then
-      -- Shouldn't happen as query must match only one package.
-      return nil, "Several rocks matched query."
-   else
-      return pick_latest_version(query.name, result_tree[first_rock])
+      err = err .. "\n" .. add
    end
+
+   return nil, err
 end
 
 --- Print a list of rocks/rockspecs on standard output.
-- 
cgit v1.2.3-55-g6feb