summaryrefslogtreecommitdiff
path: root/src/luarocks/core/dir.lua
diff options
context:
space:
mode:
Diffstat (limited to 'src/luarocks/core/dir.lua')
-rw-r--r--src/luarocks/core/dir.lua98
1 files changed, 98 insertions, 0 deletions
diff --git a/src/luarocks/core/dir.lua b/src/luarocks/core/dir.lua
new file mode 100644
index 0000000..5d6f2c9
--- /dev/null
+++ b/src/luarocks/core/dir.lua
@@ -0,0 +1,98 @@
+
+local dir = {}
+
+local require = nil
+--------------------------------------------------------------------------------
+
+local dir_sep = package.config:sub(1, 1)
+
+local function unquote(c)
+ local first, last = c:sub(1,1), c:sub(-1)
+ if (first == '"' and last == '"') or
+ (first == "'" and last == "'") then
+ return c:sub(2,-2)
+ end
+ return c
+end
+
+--- Describe a path in a cross-platform way.
+-- Use this function to avoid platform-specific directory
+-- separators in other modules. Removes trailing slashes from
+-- each component given, to avoid repeated separators.
+-- Separators inside strings are kept, to handle URLs containing
+-- protocols.
+-- @param ... strings representing directories
+-- @return string: a string with a platform-specific representation
+-- of the path.
+function dir.path(...)
+ local t = {...}
+ while t[1] == "" do
+ table.remove(t, 1)
+ end
+ for i, c in ipairs(t) do
+ t[i] = unquote(c)
+ end
+ return dir.normalize(table.concat(t, "/"))
+end
+
+--- Split protocol and path from an URL or local pathname.
+-- URLs should be in the "protocol://path" format.
+-- For local pathnames, "file" is returned as the protocol.
+-- @param url string: an URL or a local pathname.
+-- @return string, string: the protocol, and the pathname without the protocol.
+function dir.split_url(url)
+ assert(type(url) == "string")
+
+ url = unquote(url)
+ local protocol, pathname = url:match("^([^:]*)://(.*)")
+ if not protocol then
+ protocol = "file"
+ pathname = url
+ end
+ return protocol, pathname
+end
+
+--- Normalize a url or local path.
+-- URLs should be in the "protocol://path" format.
+-- Removes trailing and double slashes, and '.' and '..' components.
+-- for 'file' URLs, the native system's slashes are used.
+-- @param url string: an URL or a local pathname.
+-- @return string: Normalized result.
+function dir.normalize(name)
+ local protocol, pathname = dir.split_url(name)
+ pathname = pathname:gsub("\\", "/"):gsub("(.)/*$", "%1"):gsub("//", "/")
+ local pieces = {}
+ local drive = ""
+ if pathname:match("^.:") then
+ drive, pathname = pathname:match("^(.:)(.*)$")
+ end
+ pathname = pathname .. "/"
+ for piece in pathname:gmatch("(.-)/") do
+ if piece == ".." then
+ local prev = pieces[#pieces]
+ if not prev or prev == ".." then
+ table.insert(pieces, "..")
+ elseif prev ~= "" then
+ table.remove(pieces)
+ end
+ elseif piece ~= "." then
+ table.insert(pieces, piece)
+ end
+ end
+ if #pieces == 0 then
+ pathname = drive .. "."
+ elseif #pieces == 1 and pieces[1] == "" then
+ pathname = drive .. "/"
+ else
+ pathname = drive .. table.concat(pieces, "/")
+ end
+ if protocol ~= "file" then
+ pathname = protocol .. "://" .. pathname
+ else
+ pathname = pathname:gsub("/", dir_sep)
+ end
+ return pathname
+end
+
+return dir
+