rearranging paths funcs, no logic changes (#3018)
#### Does this PR need a docs update or release note? - [x] ⛔ No #### Type of change - [x] 🧹 Tech Debt/Cleanup
This commit is contained in:
parent
43c9ad4a01
commit
f5b1b55971
@ -143,28 +143,6 @@ type Builder struct {
|
|||||||
elements Elements
|
elements Elements
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnescapeAndAppend creates a copy of this Builder and adds one or more already
|
|
||||||
// escaped path elements to the end of the new Builder. Elements are added in
|
|
||||||
// the order they are passed.
|
|
||||||
func (pb Builder) UnescapeAndAppend(elements ...string) (*Builder, error) {
|
|
||||||
res := &Builder{elements: make([]string, 0, len(pb.elements))}
|
|
||||||
copy(res.elements, pb.elements)
|
|
||||||
|
|
||||||
if err := res.appendElements(true, elements); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return res, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SplitUnescapeAppend takes in an escaped string representing a directory
|
|
||||||
// path, splits the string, and appends it to the current builder.
|
|
||||||
func (pb Builder) SplitUnescapeAppend(s string) (*Builder, error) {
|
|
||||||
elems := Split(TrimTrailingSlash(s))
|
|
||||||
|
|
||||||
return pb.UnescapeAndAppend(elems...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Append creates a copy of this Builder and adds the given elements them to the
|
// Append creates a copy of this Builder and adds the given elements them to the
|
||||||
// end of the new Builder. Elements are added in the order they are passed.
|
// end of the new Builder. Elements are added in the order they are passed.
|
||||||
func (pb Builder) Append(elements ...string) *Builder {
|
func (pb Builder) Append(elements ...string) *Builder {
|
||||||
@ -206,6 +184,28 @@ func (pb *Builder) appendElements(escaped bool, elements []string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UnescapeAndAppend creates a copy of this Builder and adds one or more already
|
||||||
|
// escaped path elements to the end of the new Builder. Elements are added in
|
||||||
|
// the order they are passed.
|
||||||
|
func (pb Builder) UnescapeAndAppend(elements ...string) (*Builder, error) {
|
||||||
|
res := &Builder{elements: make([]string, 0, len(pb.elements))}
|
||||||
|
copy(res.elements, pb.elements)
|
||||||
|
|
||||||
|
if err := res.appendElements(true, elements); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SplitUnescapeAppend takes in an escaped string representing a directory
|
||||||
|
// path, splits the string, and appends it to the current builder.
|
||||||
|
func (pb Builder) SplitUnescapeAppend(s string) (*Builder, error) {
|
||||||
|
elems := Split(TrimTrailingSlash(s))
|
||||||
|
|
||||||
|
return pb.UnescapeAndAppend(elems...)
|
||||||
|
}
|
||||||
|
|
||||||
func (pb Builder) PopFront() *Builder {
|
func (pb Builder) PopFront() *Builder {
|
||||||
if len(pb.elements) <= 1 {
|
if len(pb.elements) <= 1 {
|
||||||
return &Builder{}
|
return &Builder{}
|
||||||
@ -219,6 +219,7 @@ func (pb Builder) PopFront() *Builder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dir removes the last element from the builder.
|
||||||
func (pb Builder) Dir() *Builder {
|
func (pb Builder) Dir() *Builder {
|
||||||
if len(pb.elements) <= 1 {
|
if len(pb.elements) <= 1 {
|
||||||
return &Builder{}
|
return &Builder{}
|
||||||
@ -230,6 +231,7 @@ func (pb Builder) Dir() *Builder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LastElem returns the last element in the Builder.
|
||||||
func (pb Builder) LastElem() string {
|
func (pb Builder) LastElem() string {
|
||||||
if len(pb.elements) == 0 {
|
if len(pb.elements) == 0 {
|
||||||
return ""
|
return ""
|
||||||
@ -238,6 +240,8 @@ func (pb Builder) LastElem() string {
|
|||||||
return pb.elements[len(pb.elements)-1]
|
return pb.elements[len(pb.elements)-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ShortRef produces a truncated hash of the builder that
|
||||||
|
// acts as a unique identifier.
|
||||||
func (pb Builder) ShortRef() string {
|
func (pb Builder) ShortRef() string {
|
||||||
if len(pb.elements) == 0 {
|
if len(pb.elements) == 0 {
|
||||||
return ""
|
return ""
|
||||||
@ -268,18 +272,8 @@ func (pb Builder) Elements() Elements {
|
|||||||
return append(Elements{}, pb.elements...)
|
return append(Elements{}, pb.elements...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func verifyInputValues(tenant, resourceOwner string) error {
|
// verifyPrefix ensures that the tenant and resourceOwner are valid
|
||||||
if len(tenant) == 0 {
|
// values, and that the builder has some directory structure.
|
||||||
return clues.Stack(errMissingSegment, clues.New("tenant"))
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(resourceOwner) == 0 {
|
|
||||||
return clues.Stack(errMissingSegment, clues.New("resourceOwner"))
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pb Builder) verifyPrefix(tenant, resourceOwner string) error {
|
func (pb Builder) verifyPrefix(tenant, resourceOwner string) error {
|
||||||
if err := verifyInputValues(tenant, resourceOwner); err != nil {
|
if err := verifyInputValues(tenant, resourceOwner); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -292,6 +286,8 @@ func (pb Builder) verifyPrefix(tenant, resourceOwner string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// withPrefix creates a Builder prefixed with the parameter values, and
|
||||||
|
// concatenated with the current builder elements.
|
||||||
func (pb Builder) withPrefix(elements ...string) *Builder {
|
func (pb Builder) withPrefix(elements ...string) *Builder {
|
||||||
res := Builder{}.Append(elements...)
|
res := Builder{}.Append(elements...)
|
||||||
res.elements = append(res.elements, pb.elements...)
|
res.elements = append(res.elements, pb.elements...)
|
||||||
@ -299,6 +295,10 @@ func (pb Builder) withPrefix(elements ...string) *Builder {
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Data Layer Path Transformers
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
func (pb Builder) ToStreamStorePath(
|
func (pb Builder) ToStreamStorePath(
|
||||||
tenant, purpose string,
|
tenant, purpose string,
|
||||||
service ServiceType,
|
service ServiceType,
|
||||||
@ -377,21 +377,6 @@ func (pb Builder) ToServiceCategoryMetadataPath(
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func Build(
|
|
||||||
tenant, resourceOwner string,
|
|
||||||
service ServiceType,
|
|
||||||
category CategoryType,
|
|
||||||
hasItem bool,
|
|
||||||
elements ...string,
|
|
||||||
) (Path, error) {
|
|
||||||
b := Builder{}.Append(elements...)
|
|
||||||
|
|
||||||
return b.ToDataLayerPath(
|
|
||||||
tenant, resourceOwner,
|
|
||||||
service, category,
|
|
||||||
hasItem)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pb Builder) ToDataLayerPath(
|
func (pb Builder) ToDataLayerPath(
|
||||||
tenant, user string,
|
tenant, user string,
|
||||||
service ServiceType,
|
service ServiceType,
|
||||||
@ -442,6 +427,57 @@ func (pb Builder) ToDataLayerSharePointPath(
|
|||||||
return pb.ToDataLayerPath(tenant, site, SharePointService, category, isItem)
|
return pb.ToDataLayerPath(tenant, site, SharePointService, category, isItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Stringers and PII Concealer Compliance
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Conceal produces a concealed representation of the builder, suitable for
|
||||||
|
// logging, storing in errors, and other output.
|
||||||
|
func (pb Builder) Conceal() string {
|
||||||
|
return pb.elements.Conceal()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format produces a concealed representation of the builder, even when
|
||||||
|
// used within a PrintF, suitable for logging, storing in errors,
|
||||||
|
// and other output.
|
||||||
|
func (pb Builder) Format(fs fmt.State, _ rune) {
|
||||||
|
fmt.Fprint(fs, pb.Conceal())
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a string that contains all path elements joined together.
|
||||||
|
// Elements of the path that need escaping are escaped.
|
||||||
|
// The result is not concealed, and is not suitable for logging or structured
|
||||||
|
// errors.
|
||||||
|
func (pb Builder) String() string {
|
||||||
|
return pb.elements.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// PlainString returns an unescaped, unmodified string of the builder.
|
||||||
|
// The result is not concealed, and is not suitable for logging or structured
|
||||||
|
// errors.
|
||||||
|
func (pb Builder) PlainString() string {
|
||||||
|
return pb.elements.PlainString()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Exported Helpers
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
func Build(
|
||||||
|
tenant, resourceOwner string,
|
||||||
|
service ServiceType,
|
||||||
|
category CategoryType,
|
||||||
|
hasItem bool,
|
||||||
|
elements ...string,
|
||||||
|
) (Path, error) {
|
||||||
|
b := Builder{}.Append(elements...)
|
||||||
|
|
||||||
|
return b.ToDataLayerPath(
|
||||||
|
tenant, resourceOwner,
|
||||||
|
service, category,
|
||||||
|
hasItem)
|
||||||
|
}
|
||||||
|
|
||||||
// FromDataLayerPath parses the escaped path p, validates the elements in p
|
// FromDataLayerPath parses the escaped path p, validates the elements in p
|
||||||
// match a resource-specific path format, and returns a Path struct for that
|
// match a resource-specific path format, and returns a Path struct for that
|
||||||
// resource-specific type. If p does not match any resource-specific paths or
|
// resource-specific type. If p does not match any resource-specific paths or
|
||||||
@ -479,6 +515,102 @@ func FromDataLayerPath(p string, isItem bool) (Path, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TrimTrailingSlash takes an escaped path element and returns an escaped path
|
||||||
|
// element with the trailing path separator character(s) removed if they were not
|
||||||
|
// escaped. If there were no trailing path separator character(s) or the separator(s)
|
||||||
|
// were escaped the input is returned unchanged.
|
||||||
|
func TrimTrailingSlash(element string) string {
|
||||||
|
for len(element) > 0 && element[len(element)-1] == PathSeparator {
|
||||||
|
lastIdx := len(element) - 1
|
||||||
|
numSlashes := 0
|
||||||
|
|
||||||
|
for i := lastIdx - 1; i >= 0; i-- {
|
||||||
|
if element[i] != escapeCharacter {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
numSlashes++
|
||||||
|
}
|
||||||
|
|
||||||
|
if numSlashes%2 != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
element = element[:lastIdx]
|
||||||
|
}
|
||||||
|
|
||||||
|
return element
|
||||||
|
}
|
||||||
|
|
||||||
|
// split takes an escaped string and returns a slice of path elements. The
|
||||||
|
// string is split on the path separator according to the escaping rules. The
|
||||||
|
// provided string must not contain an unescaped trailing path separator.
|
||||||
|
func Split(segment string) []string {
|
||||||
|
res := make([]string, 0)
|
||||||
|
numEscapes := 0
|
||||||
|
startIdx := 0
|
||||||
|
// Start with true to ignore leading separator.
|
||||||
|
prevWasSeparator := true
|
||||||
|
|
||||||
|
for i, c := range segment {
|
||||||
|
if c == escapeCharacter {
|
||||||
|
prevWasSeparator = false
|
||||||
|
numEscapes++
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if c != PathSeparator {
|
||||||
|
prevWasSeparator = false
|
||||||
|
numEscapes = 0
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remaining is just path separator handling.
|
||||||
|
if numEscapes%2 != 0 {
|
||||||
|
// This is an escaped separator.
|
||||||
|
prevWasSeparator = false
|
||||||
|
numEscapes = 0
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore leading separator characters and don't add elements that would
|
||||||
|
// be empty.
|
||||||
|
if !prevWasSeparator {
|
||||||
|
res = append(res, segment[startIdx:i])
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't want to include the path separator in the result.
|
||||||
|
startIdx = i + 1
|
||||||
|
prevWasSeparator = true
|
||||||
|
numEscapes = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the final segment because the loop above won't catch it. There should
|
||||||
|
// be no trailing separator character.
|
||||||
|
res = append(res, segment[startIdx:])
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Unexported Helpers
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
func verifyInputValues(tenant, resourceOwner string) error {
|
||||||
|
if len(tenant) == 0 {
|
||||||
|
return clues.Stack(errMissingSegment, clues.New("tenant"))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(resourceOwner) == 0 {
|
||||||
|
return clues.Stack(errMissingSegment, clues.New("resourceOwner"))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// escapeElement takes a single path element and escapes all characters that
|
// escapeElement takes a single path element and escapes all characters that
|
||||||
// require an escape sequence. If there are no characters that need escaping,
|
// require an escape sequence. If there are no characters that need escaping,
|
||||||
// the input is returned unchanged.
|
// the input is returned unchanged.
|
||||||
@ -574,33 +706,6 @@ func validateEscapedElement(element string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TrimTrailingSlash takes an escaped path element and returns an escaped path
|
|
||||||
// element with the trailing path separator character(s) removed if they were not
|
|
||||||
// escaped. If there were no trailing path separator character(s) or the separator(s)
|
|
||||||
// were escaped the input is returned unchanged.
|
|
||||||
func TrimTrailingSlash(element string) string {
|
|
||||||
for len(element) > 0 && element[len(element)-1] == PathSeparator {
|
|
||||||
lastIdx := len(element) - 1
|
|
||||||
numSlashes := 0
|
|
||||||
|
|
||||||
for i := lastIdx - 1; i >= 0; i-- {
|
|
||||||
if element[i] != escapeCharacter {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
numSlashes++
|
|
||||||
}
|
|
||||||
|
|
||||||
if numSlashes%2 != 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
element = element[:lastIdx]
|
|
||||||
}
|
|
||||||
|
|
||||||
return element
|
|
||||||
}
|
|
||||||
|
|
||||||
// join returns a string containing the given elements joined by the path
|
// join returns a string containing the given elements joined by the path
|
||||||
// separator '/'.
|
// separator '/'.
|
||||||
func join(elements []string) string {
|
func join(elements []string) string {
|
||||||
@ -608,88 +713,3 @@ func join(elements []string) string {
|
|||||||
// '\' according to the escaping rules.
|
// '\' according to the escaping rules.
|
||||||
return strings.Join(elements, string(PathSeparator))
|
return strings.Join(elements, string(PathSeparator))
|
||||||
}
|
}
|
||||||
|
|
||||||
// split takes an escaped string and returns a slice of path elements. The
|
|
||||||
// string is split on the path separator according to the escaping rules. The
|
|
||||||
// provided string must not contain an unescaped trailing path separator.
|
|
||||||
func Split(segment string) []string {
|
|
||||||
res := make([]string, 0)
|
|
||||||
numEscapes := 0
|
|
||||||
startIdx := 0
|
|
||||||
// Start with true to ignore leading separator.
|
|
||||||
prevWasSeparator := true
|
|
||||||
|
|
||||||
for i, c := range segment {
|
|
||||||
if c == escapeCharacter {
|
|
||||||
prevWasSeparator = false
|
|
||||||
numEscapes++
|
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if c != PathSeparator {
|
|
||||||
prevWasSeparator = false
|
|
||||||
numEscapes = 0
|
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remaining is just path separator handling.
|
|
||||||
if numEscapes%2 != 0 {
|
|
||||||
// This is an escaped separator.
|
|
||||||
prevWasSeparator = false
|
|
||||||
numEscapes = 0
|
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ignore leading separator characters and don't add elements that would
|
|
||||||
// be empty.
|
|
||||||
if !prevWasSeparator {
|
|
||||||
res = append(res, segment[startIdx:i])
|
|
||||||
}
|
|
||||||
|
|
||||||
// We don't want to include the path separator in the result.
|
|
||||||
startIdx = i + 1
|
|
||||||
prevWasSeparator = true
|
|
||||||
numEscapes = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the final segment because the loop above won't catch it. There should
|
|
||||||
// be no trailing separator character.
|
|
||||||
res = append(res, segment[startIdx:])
|
|
||||||
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// PII Concealer Compliance
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// Conceal produces a concealed representation of the builder, suitable for
|
|
||||||
// logging, storing in errors, and other output.
|
|
||||||
func (pb Builder) Conceal() string {
|
|
||||||
return pb.elements.Conceal()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Format produces a concealed representation of the builder, even when
|
|
||||||
// used within a PrintF, suitable for logging, storing in errors,
|
|
||||||
// and other output.
|
|
||||||
func (pb Builder) Format(fs fmt.State, _ rune) {
|
|
||||||
fmt.Fprint(fs, pb.Conceal())
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns a string that contains all path elements joined together.
|
|
||||||
// Elements of the path that need escaping are escaped.
|
|
||||||
// The result is not concealed, and is not suitable for logging or structured
|
|
||||||
// errors.
|
|
||||||
func (pb Builder) String() string {
|
|
||||||
return pb.elements.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// PlainString returns an unescaped, unmodified string of the builder.
|
|
||||||
// The result is not concealed, and is not suitable for logging or structured
|
|
||||||
// errors.
|
|
||||||
func (pb Builder) PlainString() string {
|
|
||||||
return pb.elements.PlainString()
|
|
||||||
}
|
|
||||||
|
|||||||
@ -237,6 +237,8 @@ func (rp dataLayerResourcePath) Item() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dir removes the last element from the path. If this would remove a
|
||||||
|
// value that is part of the standard prefix structure, an error is returned.
|
||||||
func (rp dataLayerResourcePath) Dir() (Path, error) {
|
func (rp dataLayerResourcePath) Dir() (Path, error) {
|
||||||
if len(rp.elements) <= 4 {
|
if len(rp.elements) <= 4 {
|
||||||
return nil, clues.New("unable to shorten path").With("path", rp)
|
return nil, clues.New("unable to shorten path").With("path", rp)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user