From 5cce6d01add5fbe2c3293f6d1da44d0348a46e47 Mon Sep 17 00:00:00 2001 From: Fabian Homborg Date: Thu, 7 Apr 2022 15:13:10 +0200 Subject: [PATCH] resolve: Normalize This means "../" components are cancelled out even after non-existent paths or files. (the alternative is to error out, but being able to say `path resolve /path/to/file/../../` over `path resolve (path dirname /path/to/file)/../../` seems worth it?) --- src/builtins/path.cpp | 5 +++++ tests/checks/path.fish | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/src/builtins/path.cpp b/src/builtins/path.cpp index b1840d9fd..fca03bd82 100644 --- a/src/builtins/path.cpp +++ b/src/builtins/path.cpp @@ -675,6 +675,11 @@ static int path_resolve(parser_t &parser, io_streams_t &streams, int argc, const } } + // Normalize the path so "../" components are eliminated even after + // nonexistent or non-directory components. + // Otherwise `path resolve foo/../` will be `$PWD/foo/../` if foo is a file. + real = normalize_path(*real, false); + // Return 0 if we found a realpath. if (opts.quiet) { return STATUS_CMD_OK; diff --git a/tests/checks/path.fish b/tests/checks/path.fish index ae14e5022..7334f0e7d 100644 --- a/tests/checks/path.fish +++ b/tests/checks/path.fish @@ -118,6 +118,10 @@ path resolve bin//sh | string match -r -- 'bin/bash$' # sh here is bash # CHECK: bin/bash +# "../" cancels out even files. +path resolve bin//sh/../ | string match -r -- 'bin$' +# CHECK: bin + # `path resolve` with nonexistent paths set -l path (path resolve foo/bar) string match -rq "^"(pwd -P | string escape --style=regex)'/' -- $path