Mercurial > repo
comparison share/lua/5.2/luarocks/loader.lua @ 1132:d137f631bad5
<GreyKnight> (cd luabuild/luarocks-2.0.12; make install)
author | HackBot |
---|---|
date | Fri, 14 Dec 2012 22:24:27 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
1131:ff65dfb63263 | 1132:d137f631bad5 |
---|---|
1 | |
2 --- A module which installs a Lua package loader that is LuaRocks-aware. | |
3 -- This loader uses dependency information from the LuaRocks tree to load | |
4 -- correct versions of modules. It does this by constructing a "context" | |
5 -- table in the environment, which records which versions of packages were | |
6 -- used to load previous modules, so that the loader chooses versions | |
7 -- that are declared to be compatible with the ones loaded earlier. | |
8 local global_env = _G | |
9 local package, require, ipairs, pairs, table, type, next, unpack = | |
10 package, require, ipairs, pairs, table, type, next, unpack | |
11 | |
12 module("luarocks.loader") | |
13 | |
14 local path = require("luarocks.path") | |
15 local manif_core = require("luarocks.manif_core") | |
16 local deps = require("luarocks.deps") | |
17 local cfg = require("luarocks.cfg") | |
18 | |
19 context = {} | |
20 | |
21 -- Contains a table when rocks trees are loaded, | |
22 -- or 'false' to indicate rocks trees failed to load. | |
23 -- 'nil' indicates rocks trees were not attempted to be loaded yet. | |
24 rocks_trees = nil | |
25 | |
26 local function load_rocks_trees() | |
27 local any_ok = false | |
28 local trees = {} | |
29 for _, tree in ipairs(cfg.rocks_trees) do | |
30 local manifest, err = manif_core.load_local_manifest(path.rocks_dir(tree)) | |
31 if manifest then | |
32 any_ok = true | |
33 table.insert(trees, {tree=tree, manifest=manifest}) | |
34 end | |
35 end | |
36 if not any_ok then | |
37 rocks_trees = false | |
38 return false | |
39 end | |
40 rocks_trees = trees | |
41 return true | |
42 end | |
43 | |
44 --- Process the dependencies of a package to determine its dependency | |
45 -- chain for loading modules. | |
46 -- @param name string: The name of an installed rock. | |
47 -- @param version string: The version of the rock, in string format | |
48 function add_context(name, version) | |
49 -- assert(type(name) == "string") | |
50 -- assert(type(version) == "string") | |
51 | |
52 if context[name] then | |
53 return | |
54 end | |
55 context[name] = version | |
56 | |
57 if not rocks_trees and not load_rocks_trees() then | |
58 return nil | |
59 end | |
60 | |
61 local providers = {} | |
62 for _, tree in ipairs(rocks_trees) do | |
63 local manifest = tree.manifest | |
64 | |
65 local pkgdeps | |
66 if manifest.dependencies and manifest.dependencies[name] then | |
67 pkgdeps = manifest.dependencies[name][version] | |
68 end | |
69 if not pkgdeps then | |
70 return nil | |
71 end | |
72 for _, dep in ipairs(pkgdeps) do | |
73 local pkg, constraints = dep.name, dep.constraints | |
74 | |
75 for _, tree in ipairs(rocks_trees) do | |
76 local entries = tree.manifest.repository[pkg] | |
77 if entries then | |
78 for version, pkgs in pairs(entries) do | |
79 if (not constraints) or deps.match_constraints(deps.parse_version(version), constraints) then | |
80 add_context(pkg, version) | |
81 end | |
82 end | |
83 end | |
84 end | |
85 end | |
86 end | |
87 end | |
88 | |
89 --- Internal sorting function. | |
90 -- @param a table: A provider table. | |
91 -- @param b table: Another provider table. | |
92 -- @return boolean: True if the version of a is greater than that of b. | |
93 local function sort_versions(a,b) | |
94 return a.version > b.version | |
95 end | |
96 | |
97 --- Request module to be loaded through other loaders, | |
98 -- once the proper name of the module has been determined. | |
99 -- For example, in case the module "socket.core" has been requested | |
100 -- to the LuaRocks loader and it determined based on context that | |
101 -- the version 2.0.2 needs to be loaded and it is not the current | |
102 -- version, the module requested for the other loaders will be | |
103 -- "socket.core_2_0_2". | |
104 -- @param module The module name requested by the user, such as "socket.core" | |
105 -- @param name The rock name, such as "luasocket" | |
106 -- @param version The rock version, such as "2.0.2-1" | |
107 -- @param module_name The actual module name, such as "socket.core" or "socket.core_2_0_2". | |
108 -- @return table or (nil, string): The module table as returned by some other loader, | |
109 -- or nil followed by an error message if no other loader managed to load the module. | |
110 local function call_other_loaders(module, name, version, module_name) | |
111 for i, loader in pairs(package.loaders) do | |
112 if loader ~= luarocks_loader then | |
113 local results = { loader(module_name) } | |
114 if type(results[1]) == "function" then | |
115 return unpack(results) | |
116 end | |
117 end | |
118 end | |
119 return "Failed loading module "..module.." in LuaRocks rock "..name.." "..version | |
120 end | |
121 | |
122 --- Search for a module in the rocks trees | |
123 -- @param module string: module name (eg. "socket.core") | |
124 -- @param filter_module_name function(string, string, string, string, number): | |
125 -- a function that takes the module name (eg "socket.core"), the rock name | |
126 -- (eg "luasocket"), the version (eg "2.0.2-1"), the path of the rocks tree | |
127 -- (eg "/usr/local"), and the numeric index of the matching entry, so the | |
128 -- filter function can know if the matching module was the first entry or not. | |
129 -- @return string, string, string: name of the rock containing the module | |
130 -- (eg. "luasocket"), version of the rock (eg. "2.0.2-1"), | |
131 -- name of the module (eg. "socket.core", or "socket.core_2_0_2" if file is | |
132 -- stored versioned). | |
133 local function select_module(module, filter_module_name) | |
134 --assert(type(module) == "string") | |
135 --assert(type(filter_module_name) == "function") | |
136 | |
137 if not rocks_trees and not load_rocks_trees() then | |
138 return nil | |
139 end | |
140 | |
141 local providers = {} | |
142 for _, tree in ipairs(rocks_trees) do | |
143 local entries = tree.manifest.modules[module] | |
144 if entries then | |
145 for i, entry in ipairs(entries) do | |
146 local name, version = entry:match("^([^/]*)/(.*)$") | |
147 local module_name = tree.manifest.repository[name][version][1].modules[module] | |
148 if type(module_name) ~= "string" then | |
149 error("Invalid format in manifest file (invalid data for "..tostring(name).." "..tostring(version)..")") | |
150 end | |
151 module_name = filter_module_name(module_name, name, version, tree.tree, i) | |
152 if context[name] == version then | |
153 return name, version, module_name | |
154 end | |
155 version = deps.parse_version(version) | |
156 table.insert(providers, {name = name, version = version, module_name = module_name}) | |
157 end | |
158 end | |
159 end | |
160 | |
161 if next(providers) then | |
162 table.sort(providers, sort_versions) | |
163 local first = providers[1] | |
164 return first.name, first.version.string, first.module_name | |
165 end | |
166 end | |
167 | |
168 --- Search for a module | |
169 -- @param module string: module name (eg. "socket.core") | |
170 -- @return string, string, string: name of the rock containing the module | |
171 -- (eg. "luasocket"), version of the rock (eg. "2.0.2-1"), | |
172 -- name of the module (eg. "socket.core", or "socket.core_2_0_2" if file is | |
173 -- stored versioned). | |
174 local function pick_module(module) | |
175 return | |
176 select_module(module, function(module_name, name, version, tree, i) | |
177 if i > 1 then | |
178 module_name = path.versioned_name(module_name, "", name, version) | |
179 end | |
180 module_name = path.path_to_module(module_name) | |
181 return module_name | |
182 end) | |
183 end | |
184 | |
185 --- Return the pathname of the file that would be loaded for a module. | |
186 -- @param module string: module name (eg. "socket.core") | |
187 -- @return string: filename of the module (eg. "/usr/local/lib/lua/5.1/socket/core.so") | |
188 function which(module) | |
189 local name, version, module_name = select_module(module, path.which_i) | |
190 return module_name | |
191 end | |
192 | |
193 --- Package loader for LuaRocks support. | |
194 -- A module is searched in installed rocks that match the | |
195 -- current LuaRocks context. If module is not part of the | |
196 -- context, or if a context has not yet been set, the module | |
197 -- in the package with the highest version is used. | |
198 -- @param module string: The module name, like in plain require(). | |
199 -- @return table: The module table (typically), like in plain | |
200 -- require(). See <a href="http://www.lua.org/manual/5.1/manual.html#pdf-require">require()</a> | |
201 -- in the Lua reference manual for details. | |
202 function luarocks_loader(module) | |
203 local name, version, module_name = pick_module(module) | |
204 if not name then | |
205 return "No LuaRocks module found for "..module | |
206 else | |
207 add_context(name, version) | |
208 return call_other_loaders(module, name, version, module_name) | |
209 end | |
210 end | |
211 | |
212 table.insert(global_env.package.loaders, 1, luarocks_loader) |