aboutsummaryrefslogtreecommitdiff
path: root/src/luarocks2.lua
blob: 0ca2f5053ce621b791376262bafca8ee79af3f93 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147

local global_env = _G
local package, require, assert, ipairs, pairs, os, print, table, type, next, unpack =
      package, require, assert, ipairs, pairs, os, print, table, type, next, unpack

module("luarocks")

local path = require("luarocks.path")
local manif_core = require("luarocks.manif_core")
local deps = require("luarocks.deps")
local cfg = require("luarocks.cfg")

context = {}

-- Contains a table when rocks trees are loaded,
-- or 'false' to indicate rocks trees failed to load.
-- 'nil' indicates rocks trees were not attempted to be loaded yet.
rocks_trees = nil

local function load_rocks_trees() 
   local any_ok = false
   local trees = {}
   
   -- FIXME select correctly file to be fetched
   local persist = require("luarocks.persist")
   table.insert(trees, { manifest = persist.load_into_table("manifest2") } )
   any_ok = true

   if not any_ok then
      rocks_trees = false
      return false
   end
   rocks_trees = trees
   return true
end

--- Process the dependencies of a package to determine its dependency
-- chain for loading modules.
-- @parse name string: The name of an installed rock.
-- @parse version string: The version of the rock, in string format
-- @parse manifest table: The local manifest table where this rock
-- is installed.
local function add_context(name, version)
   -- assert(type(name) == "string")
   -- assert(type(version) == "string")
   -- assert(type(manifest) == "table")

   if context[name] then
      return
   end
   context[name] = version
   --[[

   local pkgdeps = manifest.dependencies and manifest.dependencies[name][version]
   if not pkgdeps then
      return
   end
   for _, dep in ipairs(pkgdeps) do
      local package, constraints = dep.name, dep.constraints

      for _, tree in pairs(rocks_trees) do
         local entries = tree.manifest.repository[package]
         if entries then
            for version, packages in pairs(entries) do
               if (not constraints) or deps.match_constraints(deps.parse_version(version), constraints) then
                  add_context(package, version, tree.manifest)
               end
            end
         end
      end
   end
   ]]
end

--- Internal sorting function.
-- @param a table: A provider table.
-- @param b table: Another provider table.
-- @return boolean: True if the version of a is greater than that of b.
local function sort_versions(a,b)
   return a.version > b.version
end

local function call_other_loaders(module, name, version, file)
   
   local actual_module = file:match("(.*)%.[^.]+$")
   
   for i, loader in pairs(package.loaders) do
      if loader ~= luarocks_loader then
         local results = { loader(actual_module) }
         if type(results[1]) == "function" then
            return unpack(results)
         end
      end
   end
   return nil, "Failed loading module "..module.." in LuaRocks rock "..name.." "..version
end

local function pick_module(module)
   --assert(type(module) == "string")

   if not rocks_trees and not load_rocks_trees() then
      return nil
   end

   local providers = {}
   for _, tree in pairs(rocks_trees) do
      local entries = tree.manifest.modules[module]
      if entries then
         for entry, file in pairs(entries) do
            local name, version = entry:match("^([^/]*)/(.*)$")
            if context[name] == version then
               return name, version, file
            end
            version = deps.parse_version(version)
            table.insert(providers, {name = name, version = version, file = file})
         end
      end
   end

   if next(providers) then
      table.sort(providers, sort_versions)
      local first = providers[1]
      return first.name, first.version.string, first.file
   end
end

--- Package loader for LuaRocks support.
-- A module is searched in installed rocks that match the
-- current LuaRocks context. If module is not part of the
-- context, or if a context has not yet been set, the module
-- in the package with the highest version is used.
-- @param module string: The module name, like in plain require().
-- @return table: The module table (typically), like in plain
-- require(). See <a href="http://www.lua.org/manual/5.1/manual.html#pdf-require">require()</a>
-- in the Lua reference manual for details.

function luarocks_loader(module)
   local name, version, file = pick_module(module)
   if not name then
      return nil, "No LuaRocks module found for "..module
   else
      add_context(name, version)
      return call_other_loaders(module, name, version, file)
   end
end

table.insert(global_env.package.loaders, 1, luarocks_loader)