From 74b8dd5bf57dd351b844c6fe407c60f18043d597 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Tue, 30 May 2023 00:29:47 +0300 Subject: Add $path.posix_string() and $path.posix_representation() functions --- libbuild2/functions-path.cxx | 116 +++++++++++++++++++++++++++++++++++++++++ tests/function/path/testscript | 72 +++++++++++++++++++++++++ 2 files changed, 188 insertions(+) diff --git a/libbuild2/functions-path.cxx b/libbuild2/functions-path.cxx index b5511ad..020c8f4 100644 --- a/libbuild2/functions-path.cxx +++ b/libbuild2/functions-path.cxx @@ -154,6 +154,45 @@ namespace build2 return path_match (entry, pattern, *start); } + // Don't fail for absolute paths on Windows and, for example, just return + // c:/foo for c:\foo. + // + template + static inline string + posix_string (P&& p) + { +#ifndef _WIN32 + return move (p).posix_string (); +#else + if (p.relative ()) + return move (p).posix_string (); + + // Note: also handles root directories. + // + dir_path d (p.root_directory ()); + return d.string () + '/' + p.leaf (d).posix_string (); +#endif + } + + // Similar to the above don't fail for absolute paths on Windows. + // + template + static inline string + posix_representation (P&& p) + { +#ifndef _WIN32 + return move (p).posix_representation (); +#else + if (p.relative ()) + return move (p).posix_representation (); + + // Note: also handles root directories. + // + dir_path d (p.root_directory ()); + return d.string () + '/' + p.leaf (d).posix_representation (); +#endif + } + void path_functions (function_map& m) { @@ -185,6 +224,41 @@ namespace build2 return r; }; + // posix_string + // + f["posix_string"] += [](path p) {return posix_string (move (p));}; + f["posix_string"] += [](dir_path p) {return posix_string (move (p));}; + + f["posix_string"] += [](paths v) + { + strings r; + for (auto& p: v) + r.push_back (posix_string (move (p))); + return r; + }; + + f["posix_string"] += [](dir_paths v) + { + strings r; + for (auto& p: v) + r.push_back (posix_string (move (p))); + return r; + }; + + f[".posix_string"] += [](names ns) + { + // For each path decide based on the presence of a trailing slash + // whether it is a directory. Return as untyped list of strings. + // + for (name& n: ns) + { + n = n.directory () + ? posix_string (move (n.dir)) + : posix_string (convert (move (n))); + } + return ns; + }; + // representation // f["representation"] += [](path p) {return move (p).representation ();}; @@ -205,6 +279,48 @@ namespace build2 return r; }; + // posix_representation + // + f["posix_representation"] += [](path p) + { + return posix_representation (move (p)); + }; + + f["posix_representation"] += [](dir_path p) + { + return posix_representation (move (p)); + }; + + f["posix_representation"] += [](paths v) + { + strings r; + for (auto& p: v) + r.push_back (posix_representation (move (p))); + return r; + }; + + f["posix_representation"] += [](dir_paths v) + { + strings r; + for (auto& p: v) + r.push_back (posix_representation (move (p))); + return r; + }; + + f[".posix_representation"] += [](names ns) + { + // For each path decide based on the presence of a trailing slash + // whether it is a directory. Return as untyped list of strings. + // + for (name& n: ns) + { + n = n.directory () + ? posix_representation (move (n.dir)) + : posix_representation (convert (move (n))); + } + return ns; + }; + // canonicalize // // @@ TODO: add ability to specify alternative separator. diff --git a/tests/function/path/testscript b/tests/function/path/testscript index c58bbf8..1ed89ca 100644 --- a/tests/function/path/testscript +++ b/tests/function/path/testscript @@ -8,6 +8,78 @@ posix = (!$windows) s = ($posix ? '/' : '\') +: posix-string +: +{ + : relative + : + { + s = ($posix ? '/' : '\\') + + $* <"print \$posix_string\([path] a$(s)b)" >'a/b' : path + $* <"print \$posix_string\([paths] a$(s)b a$(s)c$(s))" >'a/b a/c' : paths + $* <"print \$posix_string\([dir_path] a$(s)b)" >'a/b' : dir-path + $* <"print \$posix_string\([dir_paths] a$(s)b a$(s)c$(s))" >'a/b a/c' : dir-paths + $* <"print \$path.posix_string\(a$(s)b a$(s)c$(s))" >'a/b a/c' : untyped + } + + : absolute + : + { + if $posix + { + $* <'print $posix_string([paths] /a/b /a/c/)' >'/a/b /a/c' : paths + $* <'print $posix_string([dir_paths] /a/b /a/c/)' >'/a/b /a/c' : dir-paths + $* <'print $posix_string([dir_path] /)' >'/' : root-dir + $* <'print $path.posix_string(/a/b /a/c/)' >'/a/b /a/c' : untyped + } + else + { + $* <'print $posix_string([paths] "c:\\a\\b" "C:\\a\\c\\")' >'c:/a/b C:/a/c' : paths + $* <'print $posix_string([dir_paths] "c:\\a\\b" "C:\\a\\c\\")' >'c:/a/b C:/a/c' : dir-paths + $* <'print $posix_string([dir_paths] "c:\\" "C:")' >'c:/ C:/' : root-dir + $* <'print $path.posix_string("c:\\a\\b" "C:\\a\\c\\")' >'c:/a/b C:/a/c' : untyped + $* <'print $path.posix_string("c:\\" "C:")' >'c:/ C:/' : untyped-root + } + } +} + +: posix-representation +: +{ + : relative + : + { + s = ($posix ? '/' : '\\') + + $* <"print \$posix_representation\([path] a$(s)b)" >'a/b' : path + $* <"print \$posix_representation\([paths] a$(s)b a$(s)c$(s))" >'a/b a/c/' : paths + $* <"print \$posix_representation\([dir_path] a$(s)b)" >'a/b/' : dir-path + $* <"print \$posix_representation\([dir_paths] a$(s)b a$(s)c$(s))" >'a/b/ a/c/' : dir-paths + $* <"print \$path.posix_representation\(a$(s)b a$(s)c$(s))" >'a/b a/c/' : untyped + } + + : absolute + : + { + if $posix + { + $* <'print $posix_representation([paths] /a/b /a/c/)' >'/a/b /a/c/' : paths + $* <'print $posix_representation([dir_paths] /a/b /a/c/)' >'/a/b/ /a/c/' : dir-paths + $* <'print $posix_representation([dir_path] /)' >'/' : root-dir + $* <'print $path.posix_representation(/a/b /a/c/)' >'/a/b /a/c/' : untyped + } + else + { + $* <'print $posix_representation([paths] "c:\\a\\b" "C:\\a\\c\\")' >'c:/a/b C:/a/c/' : paths + $* <'print $posix_representation([dir_paths] "c:\\a\\b" "C:\\a\\c\\")' >'c:/a/b/ C:/a/c/' : dir-paths + $* <'print $posix_representation([dir_paths] "c:\\" "C:")' >'c:/ C:/' : root-dir + $* <'print $path.posix_representation("c:\\a\\b" "C:\\a\\c\\")' >'c:/a/b C:/a/c/' : untyped + $* <'print $path.posix_representation("c:\\" "C:")' >'c:/ C:/' : untyped-root + } + } +} + : canonicalize : { -- cgit v1.1