@@ -82,27 +82,44 @@ func HasTrailingDirectorySeparator(path string) bool {
82
82
func CombinePaths (firstPath string , paths ... string ) string {
83
83
// TODO (drosen): There is potential for a fast path here.
84
84
// In the case where we find the last absolute path and just path.Join from there.
85
- result := NormalizeSlashes (firstPath )
85
+ firstPath = NormalizeSlashes (firstPath )
86
+
87
+ var b strings.Builder
88
+ size := len (firstPath ) + len (paths )
89
+ for _ , p := range paths {
90
+ size += len (p )
91
+ }
92
+ b .Grow (size )
93
+
94
+ b .WriteString (firstPath )
95
+
96
+ // To provide a way to "set" the path, keep track of the start and then slice.
97
+ // This will waste some memory each time we do it, but saving memory is more common.
98
+ start := 0
99
+ result := func () string {
100
+ return b .String ()[start :]
101
+ }
102
+ setResult := func (value string ) {
103
+ start = b .Len ()
104
+ b .WriteString (value )
105
+ }
86
106
87
107
for _ , trailingPath := range paths {
88
108
if trailingPath == "" {
89
109
continue
90
110
}
91
111
trailingPath = NormalizeSlashes (trailingPath )
92
- if result == "" || GetRootLength (trailingPath ) != 0 {
112
+ if result () == "" || GetRootLength (trailingPath ) != 0 {
93
113
// `trailingPath` is absolute.
94
- result = trailingPath
114
+ setResult ( trailingPath )
95
115
} else {
96
- // Could use
97
- // result = path.Join(result, trailingPath)
98
- // but that collapses `..` and prior segments,
99
- // which is not necessarily compatible with how combinePaths
100
- // was originally implemented.
101
-
102
- result = EnsureTrailingDirectorySeparator (result ) + trailingPath
116
+ if ! HasTrailingDirectorySeparator (result ()) {
117
+ b .WriteByte (DirectorySeparator )
118
+ }
119
+ b .WriteString (trailingPath )
103
120
}
104
121
}
105
- return result
122
+ return result ()
106
123
}
107
124
108
125
func GetPathComponents (path string , currentDirectory string ) []string {
0 commit comments