Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(pl.path): make expanduser more sturdy #469

Merged
merged 5 commits into from
Apr 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ deprecation policy.
see [CONTRIBUTING.md](CONTRIBUTING.md#release-instructions-for-a-new-version) for release instructions

## 1.14.0 (unreleased)
- fix(path): make `path.expanduser` more sturdy
[#469](https://github.com/lunarmodules/Penlight/pull/469)
- feat(func): extend `compose` to support N functions
[#448](https://github.com/lunarmodules/Penlight/pull/448)
- fix(utils) `nil` values in `utils.choose(cond, val1, val2)`
Expand Down
32 changes: 25 additions & 7 deletions lua/pl/path.lua
Original file line number Diff line number Diff line change
Expand Up @@ -493,17 +493,35 @@ end
-- In windows, if HOME isn't set, then USERPROFILE is used in preference to
-- HOMEDRIVE HOMEPATH. This is guaranteed to be writeable on all versions of Windows.
-- @string P A file path
-- @treturn[1] string The file path with the `~` prefix substituted, or the input path if it had no prefix.
-- @treturn[2] nil
-- @treturn[2] string Error message if the environment variables were unavailable.
function path.expanduser(P)
assert_string(1,P)
if at(P,1) == '~' then
local home = getenv('HOME')
if not home then -- has to be Windows
home = getenv 'USERPROFILE' or (getenv 'HOMEDRIVE' .. getenv 'HOMEPATH')
end
return home..sub(P,2)
else
if P:sub(1,1) ~= '~' then
return P
end

local home = getenv('HOME')
if (not home) and (not path.is_windows) then
-- no more options to try on Nix
return nil, "failed to expand '~' (HOME not set)"
end

if (not home) then
-- try alternatives on Windows
home = getenv 'USERPROFILE'
if not home then
local hd = getenv 'HOMEDRIVE'
local hp = getenv 'HOMEPATH'
if not (hd and hp) then
return nil, "failed to expand '~' (HOME, USERPROFILE, and HOMEDRIVE and/or HOMEPATH not set)"
end
home = hd..hp
end
end

return home..sub(P,2)
end


Expand Down
106 changes: 106 additions & 0 deletions spec/path_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@

-- conditional it/pending blocks per platform
local function nix_it(desc, ...)
if package.config:sub(1,1) == "\\" then
pending("Skip test on Windows: " .. desc, ...)
else
it(desc, ...)
end
end
local function win_it(desc, ...)
if package.config:sub(1,1) == "\\" then
it(desc, ...)
else
pending("Skip test on Unix: " .. desc, ...)
end
end



describe("pl.path", function()

local path
local mock_envs
local old_get_env

before_each(function()
mock_envs = {}
old_get_env = os.getenv
os.getenv = function(name) -- luacheck: ignore
return mock_envs[name]
end
package.loaded["pl.path"] = nil
path = require "pl.path"
end)

after_each(function()
package.loaded["pl.path"] = nil
os.getenv = old_get_env -- luacheck: ignore
end)



describe("expanduser()", function()

it("should expand ~ to the user's home directory", function()
mock_envs = {
HOME = "/home/user",
}
assert.equal("/home/user/file", path.expanduser("~/file"))
end)


nix_it("returns an error if expansion fails: HOME not set", function()
mock_envs = {}
assert.same(
{ nil, "failed to expand '~' (HOME not set)" },
{ path.expanduser("~/file")}
)
end)


win_it("returns an error if expansion fails: all Windows vars", function()
mock_envs = {}
assert.same(
{ nil, "failed to expand '~' (HOME, USERPROFILE, and HOMEDRIVE and/or HOMEPATH not set)" },
{ path.expanduser("~/file")}
)
end)


win_it("HOME is first in line", function()
mock_envs = {
HOME = "\\home\\user1",
USERPROFILE = "\\home\\user2",
HOMEDRIVE = "C:",
HOMEPATH = "\\home\\user3",
}
assert.equal("\\home\\user1\\file", path.expanduser("~\\file"))
end)


win_it("USERPROFILE is second in line", function()
mock_envs = {
--HOME = "\\home\\user1",
USERPROFILE = "\\home\\user2",
HOMEDRIVE = "C:",
HOMEPATH = "\\home\\user3",
}
assert.equal("\\home\\user2\\file", path.expanduser("~\\file"))
end)


win_it("HOMEDRIVE/PATH is third in line", function()
mock_envs = {
-- HOME = "\\home\\user1",
-- USERPROFILE = "\\home\\user2",
HOMEDRIVE = "C:",
HOMEPATH = "\\home\\user3",
}
assert.equal("C:\\home\\user3\\file", path.expanduser("~\\file"))
end)

end)

end)

2 changes: 0 additions & 2 deletions tests/test-path.lua
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,6 @@ do -- path.relpath
end


-- TODO: path.expanduser

-- TODO: path.tmpname


Expand Down
Loading