package storage import ( "path" "sort" "strings" ) const StateFileName = ".distributor.json" func ValidatePath(value string) error { if value == "" { return NewError(OpValidatePath, "", value, ErrInvalidPath, nil) } return validateLogicalPath(value) } func ValidatePrefix(value string) error { if value == "" { return nil } return validateLogicalPath(value) } func Join(base, child string) (string, error) { if err := ValidatePrefix(base); err != nil { return "", err } if err := ValidatePath(child); err != nil { return "", err } if base == "" { return child, nil } return base + "/" + child, nil } func StatePath(bundlePath string) (string, error) { if bundlePath == "" { return StateFileName, nil } return Join(bundlePath, StateFileName) } func DisplayPath(path string) string { if path == "" { return "." } return path } func ManagedBundleTargets(bundlePath string, managedOutputPaths []string) ([]string, error) { targets, err := ManagedOutputTargets(bundlePath, managedOutputPaths) if err != nil { return nil, err } statePath, err := StatePath(bundlePath) if err != nil { return nil, err } targets = append(targets, statePath) return targets, nil } func ManagedOutputTargets(bundlePath string, managedOutputPaths []string) ([]string, error) { if err := ValidatePrefix(bundlePath); err != nil { return nil, err } targets := make([]string, 0, len(managedOutputPaths)) for _, outputPath := range managedOutputPaths { target, err := Join(bundlePath, outputPath) if err != nil { return nil, err } targets = append(targets, target) } return targets, nil } func SortEntries(entries []Entry) { sort.Slice(entries, func(i, j int) bool { return entries[i].Path < entries[j].Path }) } func validateLogicalPath(value string) error { if strings.Contains(value, "\\") || strings.HasPrefix(value, "/") { return NewError(OpValidatePath, "", value, ErrInvalidPath, nil) } if path.Clean(value) != value { return NewError(OpValidatePath, "", value, ErrInvalidPath, nil) } for _, segment := range strings.Split(value, "/") { if segment == "" || segment == "." || segment == ".." { return NewError(OpValidatePath, "", value, ErrInvalidPath, nil) } } return nil }