From af6026474ace10f235edd367abd38755f7c04b1d Mon Sep 17 00:00:00 2001 From: Nathaniel Wesley Filardo Date: Thu, 21 Jul 2022 14:26:25 +0100 Subject: [PATCH] fix(app) require_here follow symlink'd main module (#423) --- CHANGELOG.md | 2 ++ lua/pl/app.lua | 16 ++++++++++-- tests/test-app.lua | 27 +++++++++++++++++++++ tests/test-app/require_here-link-target.lua | 6 +++++ 4 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 tests/test-app/require_here-link-target.lua diff --git a/CHANGELOG.md b/CHANGELOG.md index a1fb5b92..8c93c047 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ see [CONTRIBUTING.md](CONTRIBUTING.md#release-instructions-for-a-new-version) fo ## 1.13.0 (unreleased) - fix: `xml.parse` returned nonsense when given a file name [#431](https://github.com/lunarmodules/Penlight/pull/431) + - feat: `app.require_here` now follows symlink'd main modules to their directory + [#423](https://github.com/lunarmodules/Penlight/pull/423) - fix: `compat.warn` raised write guard warning in OpenResty [#414](https://github.com/lunarmodules/Penlight/pull/414) - feat: `utils.enum` now accepts hash tables, to enable better error handling diff --git a/lua/pl/app.lua b/lua/pl/app.lua index a06305da..28f839e4 100644 --- a/lua/pl/app.lua +++ b/lua/pl/app.lua @@ -29,12 +29,24 @@ end -- -- Note: the path is prefixed, so it is searched first when requiring modules. -- @string base optional base directory (absolute, or relative path). +-- @bool nofollow always use the invocation's directory, even if the invoked file is a symlink -- @treturn string the current script's path with a trailing slash -function app.require_here (base) - local p = path.dirname(app.script_name()) +function app.require_here (base, nofollow) + local p = app.script_name() if not path.isabs(p) then p = path.join(path.currentdir(),p) end + if not nofollow then + local t = path.link_attrib(p) + if t and t.mode == 'link' then + t = t.target + if not path.isabs(t) then + t = path.join(path.dirname(p), t) + end + p = t + end + end + p = path.normpath(path.dirname(p)) if p:sub(-1,-1) ~= path.sep then p = p..path.sep end diff --git a/tests/test-app.lua b/tests/test-app.lua index 980cb16c..d92a4a72 100644 --- a/tests/test-app.lua +++ b/tests/test-app.lua @@ -2,6 +2,7 @@ local app = require "pl.app" local utils = require "pl.utils" local path = require "pl.path" local asserteq = require 'pl.test'.asserteq +local lfs = require("lfs") local quote = utils.quote_arg @@ -117,6 +118,32 @@ do -- app.require_here stdout = path.normcase(stdout) asserteq(stdout, path.normcase("/fixed/?.lua;/fixed/?/init.lua;\n")) + -- symlinked script, check that we look beside the target of the link + -- -- step 1: find ourselves + local self = app.script_name() + if not path.isabs(self) then self = path.join(cd,self) end + local tadir = path.normcase(path.join(path.dirname(self),"test-app")) + -- -- step 2: create a link to our helper script + local scrl = path.tmpname() + local linkdir = path.normcase(path.dirname(scrl)) + os.remove(scrl) + assert(lfs.link(path.join(tadir,"require_here-link-target.lua"), scrl, true)) + -- -- step 3: check that we look next to ourselves + local success, code, stdout, stderr = utils.executeex(cmd.." "..scrl) + stdout = path.normcase(stdout) + assert(stdout:find(path.normcase(path.join(tadir, "?.lua;")), 1, true)) + assert(stdout:find(path.normcase(path.join(tadir, "?/init.lua;")), 1, true)) + assert(not stdout:find(path.normcase(path.join(linkdir, "?.lua;")), 1, true)) + assert(not stdout:find(path.normcase(path.join(linkdir, "?/init.lua;")), 1, true)) + -- -- step 4: ... but not if we turn on nofollow + local success, code, stdout, stderr = utils.executeex(cmd.." "..scrl.." x") + stdout = path.normcase(stdout) + assert(not stdout:find(path.normcase(path.join(tadir, "?.lua;")), 1, true)) + assert(not stdout:find(path.normcase(path.join(tadir, "?/init.lua;")), 1, true)) + assert(stdout:find(path.normcase(path.join(linkdir, "?.lua;")), 1, true)) + assert(stdout:find(path.normcase(path.join(linkdir, "?/init.lua;")), 1, true)) + os.remove(scrl) + end diff --git a/tests/test-app/require_here-link-target.lua b/tests/test-app/require_here-link-target.lua new file mode 100644 index 00000000..db0f1ebf --- /dev/null +++ b/tests/test-app/require_here-link-target.lua @@ -0,0 +1,6 @@ +-- This file is used as a symbolic link target in test-app.lua, to verify the +-- behaviors of pl.app.require_here() + +local p = package.path +require("pl.app").require_here(nil, #arg > 0) +print(package.path:sub(1, -#p-1))