file: fix `simplify_path` behavior for path starting with `.`.
authorAlexandre Terrasa <alexandre@moz-code.org>
Tue, 9 Jun 2015 17:20:34 +0000 (13:20 -0400)
committerAlexandre Terrasa <alexandre@moz-code.org>
Tue, 9 Jun 2015 17:20:34 +0000 (13:20 -0400)
Before this PR `./` was simplified as `/` which is wrong.

Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

lib/standard/file.nit

index 46c52ec..9687b0c 100644 (file)
@@ -767,11 +767,12 @@ redef class String
                return res
        end
 
-       # Simplify a file path by remove useless ".", removing "//", and resolving ".."
+       # Simplify a file path by remove useless `.`, removing `//`, and resolving `..`
        #
-       # * ".." are not resolved if they start the path
-       # * starting "/" is not removed
-       # * trailing "/" is removed
+       # * `..` are not resolved if they start the path
+       # * starting `.` is simplified unless the path is empty
+       # * starting `/` is not removed
+       # * trailing `/` is removed
        #
        # Note that the method only work on the string:
        #
@@ -785,17 +786,29 @@ redef class String
        # assert "dir/..".simplify_path            ==  "."
        # assert "//absolute//path/".simplify_path ==  "/absolute/path"
        # assert "//absolute//../".simplify_path   ==  "/"
+       # assert "/".simplify_path                 == "/"
+       # assert "../".simplify_path               == ".."
+       # assert "./".simplify_path                == "."
+       # assert "././././././".simplify_path      == "."
+       # assert "./../dir".simplify_path                  == "../dir"
+       # assert "./dir".simplify_path                     == "dir"
        # ~~~
        fun simplify_path: String
        do
                var a = self.split_with("/")
                var a2 = new Array[String]
                for x in a do
-                       if x == "." then continue
-                       if x == "" and not a2.is_empty then continue
+                       if x == "." and not a2.is_empty then continue # skip `././`
+                       if x == "" and not a2.is_empty then continue # skip `//`
                        if x == ".." and not a2.is_empty and a2.last != ".." then
-                               a2.pop
-                               continue
+                               if a2.last == "." then # do not skip `./../`
+                                       a2.pop # reduce `./../` in `../`
+                               else # reduce `dir/../` in `/`
+                                       a2.pop
+                                       continue
+                               end
+                       else if not a2.is_empty and a2.last == "." then
+                               a2.pop # reduce `./dir` in `dir`
                        end
                        a2.push(x)
                end