-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
findExe and getAppFilename are full of bugs #14292
Comments
You're missing that I've easily lost about 20 hours trying to deal with both Nimble (i.e. |
Note that the OpenBSD implementation used to check if a file was executable, but doesn't do so now - this is because NimScript refused to work with |
nimscript can be fixed :-) it's simply a matter of adding a vmops for it |
Well I'm all for better code but the issues you linked are all BSD specific and BSD follows Unix's tradition in making |
that's not true, several of these issues affect windows, several affect posix, and yes, several affect BSD too
most of these bugs are fixable (just a matter of doing the work)
I don't see how that could work (eg for a binary not under nim's control); or maybe I'm misunderstanding this |
TLDR: Please don't copy paste code. Refactor and keep code DRY. Nim makes it really easy thanks to templates + friends.
findExe
andgetAppFilename
are full of bugs, that keep popping up in lots of unexpected ways, eg in #14285 usingimport std/browsers
instead ofimport browsers
caused CI failures because of that (I'm fixing that aspect in #14291)findExe is full of bugs
Searches for
exein the current directory and then ...
is not true on posix, where $PWD is not searched if/
notinexe
to match the behavior of the shell when you run
program args
(or likewise, the behavior ofwhich
)findExe("src/main", extensions = [".out"])
# ok, finds src/main.outfindExe("src/main.nim", extensions = [".out"])
# bug, doesn't find src/main.nim.outor on windows (IIRC):
findExe("nim")
# ok, finds nim.exefindExe("nim.temp")
# bug, doesn't find nim.temp.exebug 5
on windows:
PATH=\baz
findExe(r"\foo\bar")
=> would return
\baz\foo\bar
I don't think that's correct since
\foo\bar
is absolute, it shouldn't prepend it with PATH prefixesbug 6
followSymlinks is not observed on windows even if using a version of windows that supports symlinks (the docs say:
If the system supports symlinks
)bug 7
findExe duplicates the code for expanding symlinks, instead of calling
expandFilename
(or recursivelyexpandSymlink
), or fixing whatever needs fixing inexpandSymlink
if there's anything to fix for it to use it; also it does so with small differences... and with un-necessary allocationsbug 8
findExe (on posix at least) returns the 1st existing file in PATH regardless whether it's an executable; this is not what the shell does (nor what
which
does); these only return a file if it's an executablebug 9
on posix at least, empty entries in PATH are treated as current directory (which is inconsistent with other shell tools and silly as it makes
PATH=$PATH:$DIR
error prone in case PATH wasn't already set); however that's the correct expected behavior (eg https://www.zsh.org/mla/users/2006/msg00519.html);findExe
however incorrectly skips over empty PATH entries, which is a bug (other code is correct in that respect, eggetApplOpenBsd
andgetApplHeuristic
)The real bug here though is that this should be abstracted over via an
iterator pathItems(): string
and that code should be reused, not duplicatedexpandTilde
should not be called insidefindExe
when iterating over PATH candidates; egPATH='~/temp/' foo
doesn't expand the~
(it only expands if you passPATH=~/temp/ foo
but that's done by the shell, before it even reaches the binary)There are probably more bugs in that function, I haven't investigated
getAppFilename is full of bugs
getAppFilename
absolutePath
) and refactor its code with other code doing something very similar to avoid duplication; chances are the differences should be either none or very small, and awhen defined(x)
would handle thatexpandFilename
is called many times in some code paths (but not others, which is a bug); instead it should be called a single time in a way that captures all code paths. For example, this makes it really hard to updategetAppFilename
to make resolving symlinks optionalthere is no such guarantee, it's merely a convention that doesn't have to be respected.
similar to bug 8 for findExe
Possible Solution
Please don't copy paste code, refactor instead. It's IMO the number 1 reason of bugs and hard to maintain/evolve code.
there's a lot of logic being inlined instead of reused. So you end up with N slightly different versions of copy pasted code instead of a single one that can be fixed in 1 place. Code reuse would reduce the number of bugs and make it easier to fix them.
bugs that can be fixed in
findExe
andgetAppFilename
without introducing problematic breaking changes should be fixed in thosea new proc
which
should be introduced, as a replacement forfindExe
(to be deprecated); without inheriting their bugs nor the cruft; eg: it shouldn't resolve symlinks. That's just standard separation of concerns; the user can just resolve them by 1 function call if they want.Additional Information
example past bugs caused by findExe and getAppFilename
$PATH
#13758links
https://github.com/gpakosz/whereami seems relevant (but I'm not sure it's needed to solve those bugs);
wai_getModulePath
seems more interesting, for another use caseThe text was updated successfully, but these errors were encountered: