mirror of
https://github.com/k3s-io/k3s.git
synced 2024-06-07 19:41:36 +00:00
126 lines
3.9 KiB
Go
126 lines
3.9 KiB
Go
|
// Copyright 2019 The Kubernetes Authors.
|
||
|
// SPDX-License-Identifier: Apache-2.0
|
||
|
|
||
|
package filesys
|
||
|
|
||
|
import (
|
||
|
"os"
|
||
|
"path/filepath"
|
||
|
"strings"
|
||
|
)
|
||
|
|
||
|
// RootedPath returns a rooted path, e.g. "/foo/bar" as
|
||
|
// opposed to "foo/bar".
|
||
|
func RootedPath(elem ...string) string {
|
||
|
return Separator + filepath.Join(elem...)
|
||
|
}
|
||
|
|
||
|
// StripTrailingSeps trims trailing filepath separators from input.
|
||
|
func StripTrailingSeps(s string) string {
|
||
|
k := len(s)
|
||
|
for k > 0 && s[k-1] == filepath.Separator {
|
||
|
k--
|
||
|
}
|
||
|
return s[:k]
|
||
|
}
|
||
|
|
||
|
// StripLeadingSeps trims leading filepath separators from input.
|
||
|
func StripLeadingSeps(s string) string {
|
||
|
k := 0
|
||
|
for k < len(s) && s[k] == filepath.Separator {
|
||
|
k++
|
||
|
}
|
||
|
return s[k:]
|
||
|
}
|
||
|
|
||
|
// PathSplit converts a file path to a slice of string.
|
||
|
// If the path is absolute (if the path has a leading slash),
|
||
|
// then the first entry in the result is an empty string.
|
||
|
// Desired: path == PathJoin(PathSplit(path))
|
||
|
func PathSplit(incoming string) []string {
|
||
|
if incoming == "" {
|
||
|
return []string{}
|
||
|
}
|
||
|
dir, path := filepath.Split(incoming)
|
||
|
if dir == string(os.PathSeparator) {
|
||
|
if path == "" {
|
||
|
return []string{""}
|
||
|
}
|
||
|
return []string{"", path}
|
||
|
}
|
||
|
dir = strings.TrimSuffix(dir, string(os.PathSeparator))
|
||
|
if dir == "" {
|
||
|
return []string{path}
|
||
|
}
|
||
|
return append(PathSplit(dir), path)
|
||
|
}
|
||
|
|
||
|
// PathJoin converts a slice of string to a file path.
|
||
|
// If the first entry is an empty string, then the returned
|
||
|
// path is absolute (it has a leading slash).
|
||
|
// Desired: path == PathJoin(PathSplit(path))
|
||
|
func PathJoin(incoming []string) string {
|
||
|
if len(incoming) == 0 {
|
||
|
return ""
|
||
|
}
|
||
|
if incoming[0] == "" {
|
||
|
return string(os.PathSeparator) + filepath.Join(incoming[1:]...)
|
||
|
}
|
||
|
return filepath.Join(incoming...)
|
||
|
}
|
||
|
|
||
|
// InsertPathPart inserts 'part' at position 'pos' in the given filepath.
|
||
|
// The first position is 0.
|
||
|
//
|
||
|
// E.g. if part == 'PEACH'
|
||
|
//
|
||
|
// OLD : NEW : POS
|
||
|
// --------------------------------------------------------
|
||
|
// {empty} : PEACH : irrelevant
|
||
|
// / : /PEACH : irrelevant
|
||
|
// pie : PEACH/pie : 0 (or negative)
|
||
|
// /pie : /PEACH/pie : 0 (or negative)
|
||
|
// raw : raw/PEACH : 1 (or larger)
|
||
|
// /raw : /raw/PEACH : 1 (or larger)
|
||
|
// a/nice/warm/pie : a/nice/warm/PEACH/pie : 3
|
||
|
// /a/nice/warm/pie : /a/nice/warm/PEACH/pie : 3
|
||
|
//
|
||
|
// * An empty part results in no change.
|
||
|
//
|
||
|
// * Absolute paths get their leading '/' stripped, treated like
|
||
|
// relative paths, and the leading '/' is re-added on output.
|
||
|
// The meaning of pos is intentionally the same in either absolute or
|
||
|
// relative paths; if it weren't, this function could convert absolute
|
||
|
// paths to relative paths, which is not desirable.
|
||
|
//
|
||
|
// * For robustness (liberal input, conservative output) Pos values that
|
||
|
// that are too small (large) to index the split filepath result in a
|
||
|
// prefix (postfix) rather than an error. Use extreme position values
|
||
|
// to assure a prefix or postfix (e.g. 0 will always prefix, and
|
||
|
// 9999 will presumably always postfix).
|
||
|
func InsertPathPart(path string, pos int, part string) string {
|
||
|
if part == "" {
|
||
|
return path
|
||
|
}
|
||
|
parts := PathSplit(path)
|
||
|
if pos < 0 {
|
||
|
pos = 0
|
||
|
} else if pos > len(parts) {
|
||
|
pos = len(parts)
|
||
|
}
|
||
|
if len(parts) > 0 && parts[0] == "" && pos < len(parts) {
|
||
|
// An empty string at 0 indicates an absolute path, and means
|
||
|
// we must increment pos. This change means that a position
|
||
|
// specification has the same meaning in relative and absolute paths.
|
||
|
// E.g. in either the path 'a/b/c' or the path '/a/b/c',
|
||
|
// 'a' is at 0, 'b' is at 1 and 'c' is at 2, and inserting at
|
||
|
// zero means a new first field _without_ changing an absolute
|
||
|
// path to a relative path.
|
||
|
pos++
|
||
|
}
|
||
|
result := make([]string, len(parts)+1)
|
||
|
copy(result, parts[0:pos])
|
||
|
result[pos] = part
|
||
|
return PathJoin(append(result, parts[pos:]...))
|
||
|
}
|