From: Jakub Jirutka <jakub@jirutka.cz>
Date: Mon, 01 Jan 2017 17:59:00 +0200
Subject: [PATCH] Fix support for tree.rocks_dir

LuaRocks allows to specify "tree" using just "root" which is a prefix
prepended to default locations such as /lib/luarocks/rocks (rocks_dir),
/share/lua/5.x (lua_dir) etc. Later they added option to specify
rocks_dir, lua_dir, bin_dir... directly. The problem is that it's kinda
broken, some methods does not respect these options and always
construct these paths from "root".

This patch hopefuly fixes this problem.

We need it for /usr/lib/luarocks/rocks-common where we install
rock_manifests for Lua modules compatible with Lua 5.1-5.3.
See also config.lua.

--- a/src/luarocks/command_line.lua
+++ b/src/luarocks/command_line.lua
@@ -35,9 +35,14 @@
 end
 
 local function replace_tree(flags, tree)
-   tree = dir.normalize(tree)
+   if type(tree) == "table" then
+      path.use_tree(tree)
+      tree = dir.normalize(tree.root)
+   else
+      tree = dir.normalize(tree)
+      path.use_tree(tree)
+   end
    flags["tree"] = tree
-   path.use_tree(tree)
 end
 
 local function is_ownership_ok(directory)
@@ -137,7 +142,7 @@
             if not tree.root then
                die("Configuration error: tree '"..tree.name.."' has no 'root' field.")
             end
-            replace_tree(flags, tree.root)
+            replace_tree(flags, tree)
             named = true
             break
          end
--- a/src/luarocks/path.lua
+++ b/src/luarocks/path.lua
@@ -18,7 +18,9 @@
 end
 
 function path.rocks_dir(tree)
-   if type(tree) == "string" then
+   if not tree then
+      return cfg.rocks_dir
+   elseif type(tree) == "string" then
       return dir.path(tree, cfg.rocks_subdir)
    else
       assert(type(tree) == "table")
@@ -83,7 +85,6 @@
 -- the package (and by extension, the path) exists.
 function path.versions_dir(name, tree)
    assert(type(name) == "string")
-   tree = tree or cfg.root_dir
    return dir.path(path.rocks_dir(tree), name)
 end
 
@@ -96,7 +97,6 @@
 function path.install_dir(name, version, tree)
    assert(type(name) == "string")
    assert(type(version) == "string")
-   tree = tree or cfg.root_dir
    return dir.path(path.rocks_dir(tree), name, version)
 end
 
@@ -109,7 +109,6 @@
 function path.rockspec_file(name, version, tree)
    assert(type(name) == "string")
    assert(type(version) == "string")
-   tree = tree or cfg.root_dir
    return dir.path(path.rocks_dir(tree), name, version, name.."-"..version..".rockspec")
 end
 
@@ -122,7 +121,6 @@
 function path.rock_manifest_file(name, version, tree)
    assert(type(name) == "string")
    assert(type(version) == "string")
-   tree = tree or cfg.root_dir
    return dir.path(path.rocks_dir(tree), name, version, "rock_manifest")
 end
 
@@ -135,7 +133,6 @@
 function path.lib_dir(name, version, tree)
    assert(type(name) == "string")
    assert(type(version) == "string")
-   tree = tree or cfg.root_dir
    return dir.path(path.rocks_dir(tree), name, version, "lib")
 end
 
@@ -148,7 +145,6 @@
 function path.lua_dir(name, version, tree)
    assert(type(name) == "string")
    assert(type(version) == "string")
-   tree = tree or cfg.root_dir
    return dir.path(path.rocks_dir(tree), name, version, "lua")
 end
 
@@ -161,7 +157,6 @@
 function path.doc_dir(name, version, tree)
    assert(type(name) == "string")
    assert(type(version) == "string")
-   tree = tree or cfg.root_dir
    return dir.path(path.rocks_dir(tree), name, version, "doc")
 end
 
@@ -174,7 +169,6 @@
 function path.conf_dir(name, version, tree)
    assert(type(name) == "string")
    assert(type(version) == "string")
-   tree = tree or cfg.root_dir
    return dir.path(path.rocks_dir(tree), name, version, "conf")
 end
 
@@ -188,7 +182,6 @@
 function path.bin_dir(name, version, tree)
    assert(type(name) == "string")
    assert(type(version) == "string")
-   tree = tree or cfg.root_dir
    return dir.path(path.rocks_dir(tree), name, version, "bin")
 end
 
@@ -303,11 +296,15 @@
 end
 
 function path.use_tree(tree)
-   cfg.root_dir = tree
+   cfg.root_dir = path.rocks_tree_to_string(tree)
    cfg.rocks_dir = path.rocks_dir(tree)
    cfg.deploy_bin_dir = path.deploy_bin_dir(tree)
    cfg.deploy_lua_dir = path.deploy_lua_dir(tree)
    cfg.deploy_lib_dir = path.deploy_lib_dir(tree)
+   -- Workaround for outdated methods that ignore cfg.rocks_dir.
+   if tree.rocks_dir then
+      cfg.rocks_subdir = tree.rocks_dir:match("^" .. util.matchquote(cfg.root_dir) .. "(.*)$")
+   end
 end
 
 --- Apply a given function to the active rocks trees based on chosen dependency mode.
