init()

in Sources/TSCBasic/Path.swift [618:691]


    init(normalizingRelativePath path: String) {
      #if os(Windows)
        if path.isEmpty || path == "." {
            self.init(string: ".")
        } else {
            var buffer: [WCHAR] = Array<WCHAR>(repeating: 0, count: Int(MAX_PATH + 1))
            _ = path.replacingOccurrences(of: "/", with: "\\").withCString(encodedAs: UTF16.self) {
                PathCanonicalizeW(&buffer, $0)
            }
            self.init(string: String(decodingCString: buffer, as: UTF16.self))
        }
      #else
        precondition(path.first != "/")

        // FIXME: Here we should also keep track of whether anything actually has
        // to be changed in the string, and if not, just return the existing one.

        // Split the character array into parts, folding components as we go.
        // As we do so, we count the number of characters we'll end up with in
        // the normalized string representation.
        var parts: [String] = []
        var capacity = 0
        for part in path.split(separator: "/") {
            switch part.count {
            case 0:
                // Ignore empty path components.
                continue
            case 1 where part.first == ".":
                // Ignore `.` path components.
                continue
            case 2 where part.first == "." && part.last == ".":
                // If at beginning, fall through to treat the `..` literally.
                guard let prev = parts.last else {
                    fallthrough
                }
                // If previous component is anything other than `..`, drop it.
                if !(prev.count == 2 && prev.first == "." && prev.last == ".") {
                    parts.removeLast()
                    capacity -= prev.count
                    continue
                }
                // Otherwise, fall through to treat the `..` literally.
                fallthrough
            default:
                // Any other component gets appended.
                parts.append(String(part))
                capacity += part.count
            }
        }
        capacity += max(parts.count - 1, 0)

        // Create an output buffer using the capacity we've calculated.
        // FIXME: Determine the most efficient way to reassemble a string.
        var result = ""
        result.reserveCapacity(capacity)

        // Put the normalized parts back together again.
        var iter = parts.makeIterator()
        if let first = iter.next() {
            result.append(contentsOf: first)
            while let next = iter.next() {
                result.append("/")
                result.append(contentsOf: next)
            }
        }

        // Sanity-check the result (including the capacity we reserved).
        assert(result.count == capacity, "count: " +
            "\(result.count), cap: \(capacity)")

        // If the result is empty, return `.`, otherwise we return it as a string.
        self.init(string: result.isEmpty ? "." : result)
      #endif
    }