aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormpeterv <mpeterval@gmail.com>2016-03-19 15:50:20 +0300
committermpeterv <mpeterval@gmail.com>2016-04-19 00:37:34 +0300
commit302025e1812ea790248a14b425f8c46b153af622 (patch)
tree134de93d58a6aab93ec28279c15a5d9673a48531
parent608467a030aa14919e06b2ff8cae529d0db273bd (diff)
downloadluarocks-302025e1812ea790248a14b425f8c46b153af622.tar.gz
luarocks-302025e1812ea790248a14b425f8c46b153af622.tar.bz2
luarocks-302025e1812ea790248a14b425f8c46b153af622.zip
Show if rock is supported on other Lua versions on search fail
Supporting changes: * Change structure of manifest cache: map from repo_url to tables mapping from lua versions to manifests. * New manif_core cache_manifest and get_cached_manifest functions to hide cache implementation. * lua_version optional argument for functions between search.find_suitable_rock and manifest loader. Main changes: * Add a helper function supported_lua_versions that checks which Lua versions can satisfy a query. * Use this helper function when a search for a rock failed, in search.find_suitable_rock, if constraints can be satisfied under a different Lua version mention that in the error message. Examples of error messages: * Constraint "sailor": "sailor supports only Lua 5.1 and Lua 5.2 but not Lua 5.3." * Constraint "sailor 0.5": "sailor 0.5 supports only Lua 5.1 and Lua 5.2 but not Lua 5.3." * Constraint "sailor >= 0.5": "Matching sailor versions support only Lua 5.1 and Lua 5.2 but not Lua 5.3."
-rw-r--r--src/luarocks/manif.lua20
-rw-r--r--src/luarocks/manif_core.lua37
-rw-r--r--src/luarocks/search.lua50
3 files changed, 88 insertions, 19 deletions
diff --git a/src/luarocks/manif.lua b/src/luarocks/manif.lua
index f53f8dca..05621315 100644
--- a/src/luarocks/manif.lua
+++ b/src/luarocks/manif.lua
@@ -105,18 +105,22 @@ end
105-- All functions that use manifest tables assume they were obtained 105-- All functions that use manifest tables assume they were obtained
106-- through either this function or load_local_manifest. 106-- through either this function or load_local_manifest.
107-- @param repo_url string: URL or pathname for the repository. 107-- @param repo_url string: URL or pathname for the repository.
108-- @param lua_version string: Lua version in "5.x" format, defaults to installed version.
108-- @return table or (nil, string, [string]): A table representing the manifest, 109-- @return table or (nil, string, [string]): A table representing the manifest,
109-- or nil followed by an error message and an optional error code. 110-- or nil followed by an error message and an optional error code.
110function manif.load_manifest(repo_url) 111function manif.load_manifest(repo_url, lua_version)
111 assert(type(repo_url) == "string") 112 assert(type(repo_url) == "string")
113 assert(type(lua_version) == "string" or not lua_version)
114 lua_version = lua_version or cfg.lua_version
112 115
113 if manif_core.manifest_cache[repo_url] then 116 local cached_manifest = manif_core.get_cached_manifest(repo_url, lua_version)
114 return manif_core.manifest_cache[repo_url] 117 if cached_manifest then
118 return cached_manifest
115 end 119 end
116 120
117 local filenames = { 121 local filenames = {
118 "manifest-"..cfg.lua_version..".zip", 122 "manifest-"..lua_version..".zip",
119 "manifest-"..cfg.lua_version, 123 "manifest-"..lua_version,
120 "manifest", 124 "manifest",
121 } 125 }
122 126
@@ -156,7 +160,7 @@ function manif.load_manifest(repo_url)
156 end 160 end
157 pathname = nozip 161 pathname = nozip
158 end 162 end
159 return manif_core.manifest_loader(pathname, repo_url) 163 return manif_core.manifest_loader(pathname, repo_url, lua_version)
160end 164end
161 165
162--- Output a table listing items of a package. 166--- Output a table listing items of a package.
@@ -381,7 +385,7 @@ function manif.make_manifest(repo, deps_mode, remote)
381 local results = search.disk_search(repo, query) 385 local results = search.disk_search(repo, query)
382 local manifest = { repository = {}, modules = {}, commands = {} } 386 local manifest = { repository = {}, modules = {}, commands = {} }
383 387
384 manif_core.manifest_cache[repo] = manifest 388 manif_core.cache_manifest(repo, nil, manifest)
385 389
386 local dep_handler = nil 390 local dep_handler = nil
387 if not remote then 391 if not remote then
diff --git a/src/luarocks/manif_core.lua b/src/luarocks/manif_core.lua
index 87fc16cf..610f9860 100644
--- a/src/luarocks/manif_core.lua
+++ b/src/luarocks/manif_core.lua
@@ -7,20 +7,43 @@ package.loaded["luarocks.manif_core"] = manif_core
7 7
8local persist = require("luarocks.persist") 8local persist = require("luarocks.persist")
9local type_check = require("luarocks.type_check") 9local type_check = require("luarocks.type_check")
10local cfg = require("luarocks.cfg")
10local dir = require("luarocks.dir") 11local dir = require("luarocks.dir")
11local util = require("luarocks.util") 12local util = require("luarocks.util")
12local path = require("luarocks.path") 13local path = require("luarocks.path")
13 14
14manif_core.manifest_cache = {} 15-- Table with repository identifiers as keys and tables mapping
16-- Lua versions to cached loaded manifests as values.
17local manifest_cache = {}
18
19--- Cache a loaded manifest.
20-- @param repo_url string: The repository identifier.
21-- @param lua_version string: Lua version in "5.x" format, defaults to installed version.
22-- @param manifest table: the manifest to be cached.
23function manif_core.cache_manifest(repo_url, lua_version, manifest)
24 lua_version = lua_version or cfg.lua_version
25 manifest_cache[repo_url] = manifest_cache[repo_url] or {}
26 manifest_cache[repo_url][lua_version] = manifest
27end
28
29--- Attempt to get cached loaded manifest.
30-- @param repo_url string: The repository identifier.
31-- @param lua_version string: Lua version in "5.x" format, defaults to installed version.
32-- @return table or nil: loaded manifest or nil if cache is empty.
33function manif_core.get_cached_manifest(repo_url, lua_version)
34 lua_version = lua_version or cfg.lua_version
35 return manifest_cache[repo_url] and manifest_cache[repo_url][lua_version]
36end
15 37
16--- Back-end function that actually loads the manifest 38--- Back-end function that actually loads the manifest
17-- and stores it in the manifest cache. 39-- and stores it in the manifest cache.
18-- @param file string: The local filename of the manifest file. 40-- @param file string: The local filename of the manifest file.
19-- @param repo_url string: The repository identifier. 41-- @param repo_url string: The repository identifier.
42-- @param lua_version string: Lua version in "5.x" format, defaults to installed version.
20-- @param quick boolean: If given, skips type checking. 43-- @param quick boolean: If given, skips type checking.
21-- @return table or (nil, string, string): the manifest or nil, 44-- @return table or (nil, string, string): the manifest or nil,
22-- error message and error code ("open", "load", "run" or "type"). 45-- error message and error code ("open", "load", "run" or "type").
23function manif_core.manifest_loader(file, repo_url, quick) 46function manif_core.manifest_loader(file, repo_url, lua_version, quick)
24 local manifest, err, errcode = persist.load_into_table(file) 47 local manifest, err, errcode = persist.load_into_table(file)
25 if not manifest then 48 if not manifest then
26 return nil, "Failed loading manifest for "..repo_url..": "..err, errcode 49 return nil, "Failed loading manifest for "..repo_url..": "..err, errcode
@@ -33,7 +56,7 @@ function manif_core.manifest_loader(file, repo_url, quick)
33 end 56 end
34 end 57 end
35 58
36 manif_core.manifest_cache[repo_url] = manifest 59 manif_core.cache_manifest(repo_url, lua_version, manifest)
37 return manifest 60 return manifest
38end 61end
39 62
@@ -46,13 +69,13 @@ end
46function manif_core.load_local_manifest(repo_url) 69function manif_core.load_local_manifest(repo_url)
47 assert(type(repo_url) == "string") 70 assert(type(repo_url) == "string")
48 71
49 if manif_core.manifest_cache[repo_url] then 72 local cached_manifest = manif_core.get_cached_manifest(repo_url)
50 return manif_core.manifest_cache[repo_url] 73 if cached_manifest then
74 return cached_manifest
51 end 75 end
52 76
53 local pathname = dir.path(repo_url, "manifest") 77 local pathname = dir.path(repo_url, "manifest")
54 78 return manif_core.manifest_loader(pathname, repo_url, nil, true)
55 return manif_core.manifest_loader(pathname, repo_url, true)
56end 79end
57 80
58--- Get all versions of a package listed in a manifest file. 81--- Get all versions of a package listed in a manifest file.
diff --git a/src/luarocks/search.lua b/src/luarocks/search.lua
index 0276dfae..6c0020c0 100644
--- a/src/luarocks/search.lua
+++ b/src/luarocks/search.lua
@@ -170,14 +170,15 @@ end
170-- If the arch field is omitted, the local architecture (cfg.arch) 170-- If the arch field is omitted, the local architecture (cfg.arch)
171-- is used. The special value "any" is also recognized, returning all 171-- is used. The special value "any" is also recognized, returning all
172-- matches regardless of architecture. 172-- matches regardless of architecture.
173-- @param lua_version string: Lua version in "5.x" format, defaults to installed version.
173-- @return true or, in case of errors, nil, an error message and an optional error code. 174-- @return true or, in case of errors, nil, an error message and an optional error code.
174function search.manifest_search(results, repo, query) 175function search.manifest_search(results, repo, query, lua_version)
175 assert(type(results) == "table") 176 assert(type(results) == "table")
176 assert(type(repo) == "string") 177 assert(type(repo) == "string")
177 assert(type(query) == "table") 178 assert(type(query) == "table")
178 179
179 query_arch_as_table(query) 180 query_arch_as_table(query)
180 local manifest, err, errcode = manif.load_manifest(repo) 181 local manifest, err, errcode = manif.load_manifest(repo, lua_version)
181 if not manifest then 182 if not manifest then
182 return nil, err, errcode 183 return nil, err, errcode
183 end 184 end
@@ -193,10 +194,11 @@ end
193 194
194--- Search on all configured rocks servers. 195--- Search on all configured rocks servers.
195-- @param query table: A dependency query. 196-- @param query table: A dependency query.
197-- @param lua_version string: Lua version in "5.x" format, defaults to installed version.
196-- @return table: A table where keys are package names 198-- @return table: A table where keys are package names
197-- and values are tables matching version strings to arrays of 199-- and values are tables matching version strings to arrays of
198-- tables with fields "arch" and "repo". 200-- tables with fields "arch" and "repo".
199function search.search_repos(query) 201function search.search_repos(query, lua_version)
200 assert(type(query) == "table") 202 assert(type(query) == "table")
201 203
202 local results = {} 204 local results = {}
@@ -210,7 +212,7 @@ function search.search_repos(query)
210 if protocol == "file" then 212 if protocol == "file" then
211 mirror = pathname 213 mirror = pathname
212 end 214 end
213 local ok, err, errcode = search.manifest_search(results, mirror, query) 215 local ok, err, errcode = search.manifest_search(results, mirror, query, lua_version)
214 if errcode == "network" then 216 if errcode == "network" then
215 cfg.disabled_servers[repo] = true 217 cfg.disabled_servers[repo] = true
216 end 218 end
@@ -278,6 +280,23 @@ local function pick_latest_version(name, versions)
278 return nil 280 return nil
279end 281end
280 282
283-- Find out which other Lua versions provide rock versions matching a query,
284-- @param query table: A dependency query matching a single rock.
285-- @return table: array of Lua versions supported, in "5.x" format.
286local function supported_lua_versions(query)
287 local results = {}
288
289 for lua_version in util.lua_versions() do
290 if lua_version ~= cfg.lua_version then
291 if search.search_repos(query, lua_version)[query.name] then
292 table.insert(results, lua_version)
293 end
294 end
295 end
296
297 return results
298end
299
281--- Attempt to get a single URL for a given search for a rock. 300--- Attempt to get a single URL for a given search for a rock.
282-- @param query table: A dependency query matching a single rock. 301-- @param query table: A dependency query matching a single rock.
283-- @return string or (nil, string): URL for latest matching version 302-- @return string or (nil, string): URL for latest matching version
@@ -288,6 +307,29 @@ function search.find_suitable_rock(query)
288 local results = search.search_repos(query) 307 local results = search.search_repos(query)
289 local first_rock = next(results) 308 local first_rock = next(results)
290 if not first_rock then 309 if not first_rock then
310 if cfg.rocks_provided[query.name] == nil then
311 -- Check if constraints are satisfiable with other Lua versions.
312 local lua_versions = supported_lua_versions(query)
313
314 if #lua_versions ~= 0 then
315 -- Build a nice message in "only Lua 5.x and 5.y but not 5.z." format
316 for i, lua_version in ipairs(lua_versions) do
317 lua_versions[i] = "Lua "..lua_version
318 end
319
320 local versions_message = "only "..table.concat(lua_versions, " and ")..
321 " but not Lua "..cfg.lua_version.."."
322
323 if #query.constraints == 0 then
324 return nil, query.name.." supports "..versions_message
325 elseif #query.constraints == 1 and query.constraints[1].op == "==" then
326 return nil, query.name.." "..query.constraints[1].version.string.." supports "..versions_message
327 else
328 return nil, "Matching "..query.name.." versions support "..versions_message
329 end
330 end
331 end
332
291 return nil, "No results matching query were found." 333 return nil, "No results matching query were found."
292 elseif next(results, first_rock) then 334 elseif next(results, first_rock) then
293 -- Shouldn't happen as query must match only one package. 335 -- Shouldn't happen as query must match only one package.