@@ -8,6 +8,47 @@ class Perl6::SysConfig is HLL::SysConfig {
88 $ obj
99 }
1010
11+ # A naive implementation of path normalization.
12+ # Resolves '..' and '.' path components. It does not resolve symlinks.
13+ # It does not understand UNC paths. It misses loads of cornercases I'm
14+ # blissfully unaware of.
15+ sub normalize-rakudo-home ($ path , $ sep ) {
16+ my $ all-slash := nqp :: join (' /' , nqp :: split (' \\ ' , $ path ));
17+
18+ my @ new-comps ;
19+ for nqp :: split (' /' , $ all-slash ) -> $ component {
20+ if $ component eq ' .' {
21+ next ;
22+ }
23+ elsif $ component eq ' ..' {
24+ if nqp :: elems (@ new-comps ) == 1 &&
25+ (@ new-comps [0 ] eq ' ' # path starts with "/.."
26+ || nqp :: substr (@ new-comps [0 ], 1 ) eq ' :' ) # path starts with "C:/.."
27+ {
28+ # Updir-ing beyond the root is a noop. Thus we'll just drop it.
29+ }
30+ else {
31+ # Will die if @new-comps is empty. This would mean the path
32+ # starts with "../". This should not happen as we don't
33+ # expect relative paths here.
34+ @ new-comps . pop ;
35+ }
36+ }
37+ else {
38+ @ new-comps . push : $ component ;
39+ }
40+ }
41+
42+ if ! nqp :: elems (@ new-comps ) # path is ""
43+ || (@ new-comps [0 ] ne ' ' # path doesn't start with "/"
44+ && nqp :: substr (@ new-comps [0 ], 1 ) ne ' :' ) # path doesn't start with "C:/"
45+ {
46+ die (" Invalid relative rakudo-home path found: $ path" );
47+ }
48+
49+ nqp :: join ($ sep , @ new-comps )
50+ }
51+
1152 method BUILD (% rakudo-build-config ) {
1253 self . build-hll-sysconfig();
1354
@@ -26,6 +67,8 @@ class Perl6::SysConfig is HLL::SysConfig {
2667 if nqp :: substr ($ ! rakudo-home , nqp :: chars ($ ! rakudo-home ) - 1 ) eq self . path-sep {
2768 $ ! rakudo-home := nqp :: substr ($ ! rakudo-home , 0 , nqp :: chars ($ ! rakudo-home ) - 1 );
2869 }
70+
71+ $ ! rakudo-home := normalize-rakudo-home($ ! rakudo-home , self . path-sep);
2972 }
3073
3174 method rakudo-build-config () { % ! rakudo-build-config }
0 commit comments