aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorhisham <hisham@9ca3f7c1-7366-0410-b1a3-b5c78f85698c>2009-04-23 15:00:35 +0000
committerhisham <hisham@9ca3f7c1-7366-0410-b1a3-b5c78f85698c>2009-04-23 15:00:35 +0000
commit940d5b91d3372c46b690027e14af85f41c0cffd8 (patch)
tree2162f6b9e7b2b73bb8c54df1bd50df6c2c844216 /src
parent40b346c145cb7ff175e6955652a0a32debea9b6c (diff)
downloadluarocks-940d5b91d3372c46b690027e14af85f41c0cffd8.tar.gz
luarocks-940d5b91d3372c46b690027e14af85f41c0cffd8.tar.bz2
luarocks-940d5b91d3372c46b690027e14af85f41c0cffd8.zip
Add LuaRocks package loader
git-svn-id: http://luarocks.org/svn/luarocks/trunk@12 9ca3f7c1-7366-0410-b1a3-b5c78f85698c
Diffstat (limited to 'src')
-rw-r--r--src/luarocks.lua240
1 files changed, 240 insertions, 0 deletions
diff --git a/src/luarocks.lua b/src/luarocks.lua
new file mode 100644
index 00000000..fad62e07
--- /dev/null
+++ b/src/luarocks.lua
@@ -0,0 +1,240 @@
1
2local global_env = _G
3local plain_package_path = package.path
4local plain_package_cpath = package.cpath
5local package, require, assert, ipairs, pairs, os, print, table, type, next, unpack =
6 package, require, assert, ipairs, pairs, os, print, table, type, next, unpack
7
8module("luarocks")
9
10local path = require("luarocks.path")
11local manif_core = require("luarocks.manif_core")
12local deps = require("luarocks.deps")
13local cfg = require("luarocks.cfg")
14
15context = {}
16
17-- Contains a table when rocks trees are loaded,
18-- or 'false' to indicate rocks trees failed to load.
19-- 'nil' indicates rocks trees were not attempted to be loaded yet.
20rocks_trees = nil
21
22local function load_rocks_trees()
23 local any_ok = false
24 local trees = {}
25 for _, tree in pairs(cfg.rocks_trees) do
26 local rocks_dir = tree .. "/rocks/"
27 local manifest, err = manif_core.load_local_manifest(rocks_dir)
28 if manifest then
29 any_ok = true
30 table.insert(trees, {rocks_dir=rocks_dir, manifest=manifest})
31 end
32 end
33 if not any_ok then
34 rocks_trees = false
35 return false
36 end
37 rocks_trees = trees
38 return true
39end
40
41--- Process the dependencies of a package to determine its dependency
42-- chain for loading modules.
43-- @parse name string: The name of an installed rock.
44-- @parse version string: The version of the rock, in string format
45-- @parse manifest table: The local manifest table where this rock
46-- is installed.
47local function add_context(name, version, manifest)
48 -- assert(type(name) == "string")
49 -- assert(type(version) == "string")
50 -- assert(type(manifest) == "table")
51
52 if context[name] then
53 return
54 end
55 context[name] = version
56
57 local pkgdeps = manifest.dependencies and manifest.dependencies[name][version]
58 if not pkgdeps then
59 return
60 end
61 for _, dep in ipairs(pkgdeps) do
62 local package, constraints = dep.name, dep.constraints
63
64 for _, tree in pairs(rocks_trees) do do
65 local entries = tree.manifest.repository[package]
66 if entries then
67 break -- continue for
68 end
69 for version, packages in pairs(entries) do
70 if (not constraints) or deps.match_constraints(deps.parse_version(version), constraints) then
71 add_context(package, version, tree.manifest)
72 end
73 end
74 end end
75 end
76end
77
78--- Internal sorting function.
79-- @param a table: A provider table.
80-- @param b table: Another provider table.
81-- @return boolean: True if the version of a is greater than that of b.
82local function sort_versions(a,b)
83 return a.version > b.version
84end
85
86--- Specify a dependency chain for LuaRocks.
87-- In the presence of multiple versions of packages, it is necessary to,
88-- at some point, indicate which dependency chain we're following.
89-- set_context does this by allowing one to pick a package to be the
90-- root of this dependency chain. Once a dependency chain is picked it's
91-- easy to know which modules to load ("I want to use *this* version of
92-- A, which requires *that* version of B, which requires etc etc etc").
93-- @param name string: The package name of an installed rock.
94-- @param version string or nil: Optionally, a version number
95-- When a version is not given, it picks the highest version installed.
96-- @return boolean: true if succeeded, false otherwise.
97function set_context(name, version)
98 --assert(type(name) == "string")
99 --assert(type(version) == "string" or not version)
100
101 if rocks_trees == false or (not rocks_trees and not load_rocks_trees()) then
102 return false
103 end
104
105 local manifest
106 local vtables = {}
107 for _, tree in ipairs(rocks_trees) do
108 if version then
109 local manif_repo = tree.manifest.repository
110 if manif_repo[name] and manif_repo[name][version] then
111 manifest = tree.manifest
112 break
113 end
114 else
115 local versions = manif_core.get_versions(name, tree.manifest)
116 for _, version in ipairs(versions) do
117 table.insert(vtables, {version = deps.parse_version(version), manifest = tree.manifest})
118 end
119 end
120 end
121 if not version then
122 if not next(vtables) then
123 table.sort(vtables, sort_versions)
124 local highest = vtables[#vtables]
125 version = highest.version.string
126 manifest = highest.manifest
127 end
128 end
129 if not manifest then
130 return false
131 end
132
133 add_context(name, version, manifest)
134 -- TODO: platform independence
135 local lpath, cpath = "", ""
136 for name, version in pairs(context) do
137 lpath = lpath .. path.lua_dir(name, version) .. "/?.lua;"
138 lpath = lpath .. path.lua_dir(name, version) .. "/?/init.lua;"
139 cpath = cpath .. path.lib_dir(name, version) .."/?."..cfg.lib_extension..";"
140 end
141 global_env.package.path = lpath .. plain_package_path
142 global_env.package.cpath = cpath .. plain_package_cpath
143end
144
145local function call_other_loaders(module, name, version, rocks_dir)
146 local save_path = package.path
147 local save_cpath = package.cpath
148 package.path = path.lua_dir(name, version, rocks_dir) .. "/?.lua;"
149 .. path.lua_dir(name, version, rocks_dir) .. "/?/init.lua;" .. save_path
150 package.cpath = path.lib_dir(name, version, rocks_dir) .. "/?."..cfg.lib_extension..";" .. save_cpath
151 for i, loader in pairs(package.loaders) do
152 if loader ~= luarocks_loader then
153 local results = { loader(module) }
154 if type(results[1]) == "function" then
155 package.path = save_path
156 package.cpath = save_cpath
157 return unpack(results)
158 end
159 end
160 end
161 package.path = save_path
162 package.cpath = save_cpath
163 return nil, "Failed loading module "..module.." in LuaRocks rock "..name.." "..version
164end
165
166local function pick_module(module, constraints)
167 --assert(type(module) == "string")
168 --assert(not constraints or type(constraints) == "string")
169
170 if not rocks_trees and not load_rocks_trees() then
171 return nil
172 end
173
174 if constraints then
175 if type(constraints) == "string" then
176 constraints = deps.parse_constraints(constraints)
177 else
178 constraints = nil
179 end
180 end
181
182 local providers = {}
183 for _, tree in pairs(rocks_trees) do
184 local entries = tree.manifest.modules[module]
185 if entries then
186 for _, entry in pairs(entries) do
187 local name, version = entry:match("^([^/]*)/(.*)$")
188 if context[name] == version then
189 return name, version, tree
190 end
191 version = deps.parse_version(version)
192 if (not constraints) or deps.match_constraints(version, constraints) then
193 table.insert(providers, {name = name, version = version, repo = tree})
194 end
195 end
196 end
197 end
198
199 if next(providers) then
200 table.sort(providers, sort_versions)
201 local first = providers[1]
202 return first.name, first.version.string, first.repo
203 end
204end
205
206--- Inform which rock LuaRocks would use if require() is called
207-- with the given arguments.
208-- @param module string: The module name, like in plain require().
209-- @param constraints string or nil: An optional comma-separated
210-- list of version constraints.
211-- @return (string, string) or nil: Rock name and version if the
212-- requested module can be supplied by LuaRocks, or nil if it can't.
213function get_rock_from_module(module, constraints)
214 --assert(type(module) == "string")
215 --assert(not constraints or type(constraints) == "string")
216 local name, version = pick_module(module, constraints)
217 return name, version
218end
219
220--- Package loader for LuaRocks support.
221-- A module is searched in installed rocks that match the
222-- current LuaRocks context. If module is not part of the
223-- context, or if a context has not yet been set, the module
224-- in the package with the highest version is used.
225-- @param module string: The module name, like in plain require().
226-- @return table: The module table (typically), like in plain
227-- require(). See <a href="http://www.lua.org/manual/5.1/manual.html#pdf-require">require()</a>
228-- in the Lua reference manual for details.
229
230function luarocks_loader(module)
231 local name, version, repo = pick_module(module)
232 if not name then
233 return nil, "No LuaRocks module found for "..module
234 else
235 add_context(name, version, repo.manifest)
236 return call_other_loaders(module, name, version, repo.rocks_dir)
237 end
238end
239
240table.insert(global_env.package.loaders, luarocks_loader)