backend, options: Prefer strings.Cut to SplitN

Also realigned the various "split into host🪣prefix"
implementations.
This commit is contained in:
greatroar 2022-11-27 18:09:59 +01:00 committed by Michael Eischer
parent 60aa87bbab
commit 65612d797c
9 changed files with 56 additions and 66 deletions

View File

@ -43,14 +43,13 @@ func ParseConfig(s string) (interface{}, error) {
// use the first entry of the path as the bucket name and the
// remainder as prefix
data := strings.SplitN(s, ":", 2)
if len(data) < 2 {
container, prefix, colon := strings.Cut(s, ":")
if !colon {
return nil, errors.New("azure: invalid format: bucket name or path not found")
}
container, path := data[0], path.Clean(data[1])
path = strings.TrimPrefix(path, "/")
prefix = strings.TrimPrefix(path.Clean(prefix), "/")
cfg := NewConfig()
cfg.Container = container
cfg.Prefix = path
cfg.Prefix = prefix
return cfg, nil
}

View File

@ -37,7 +37,7 @@ var bucketName = regexp.MustCompile("^[a-zA-Z0-9-]+$")
// https://help.backblaze.com/hc/en-us/articles/217666908-What-you-need-to-know-about-B2-Bucket-names
func checkBucketName(name string) error {
if name == "" {
return errors.New("bucket name is empty")
return errors.New("bucket name not found")
}
if len(name) < 6 {
@ -64,30 +64,18 @@ func ParseConfig(s string) (interface{}, error) {
}
s = s[3:]
data := strings.SplitN(s, ":", 2)
if len(data) == 0 || len(data[0]) == 0 {
return nil, errors.New("bucket name not found")
}
cfg := NewConfig()
cfg.Bucket = data[0]
if err := checkBucketName(cfg.Bucket); err != nil {
bucket, prefix, _ := strings.Cut(s, ":")
if err := checkBucketName(bucket); err != nil {
return nil, err
}
if len(data) == 2 {
p := data[1]
if len(p) > 0 {
p = path.Clean(p)
}
if len(p) > 0 && path.IsAbs(p) {
p = p[1:]
}
cfg.Prefix = p
if len(prefix) > 0 {
prefix = strings.TrimPrefix(path.Clean(prefix), "/")
}
cfg := NewConfig()
cfg.Bucket = bucket
cfg.Prefix = prefix
return cfg, nil
}

View File

@ -42,17 +42,15 @@ func ParseConfig(s string) (interface{}, error) {
// use the first entry of the path as the bucket name and the
// remainder as prefix
data := strings.SplitN(s, ":", 2)
if len(data) < 2 {
bucket, prefix, colon := strings.Cut(s, ":")
if !colon {
return nil, errors.New("gs: invalid format: bucket name or path not found")
}
bucket, path := data[0], path.Clean(data[1])
path = strings.TrimPrefix(path, "/")
prefix = strings.TrimPrefix(path.Clean(prefix), "/")
cfg := NewConfig()
cfg.Bucket = bucket
cfg.Prefix = path
cfg.Prefix = prefix
return cfg, nil
}

View File

@ -127,6 +127,6 @@ func StripPassword(s string) string {
}
func extractScheme(s string) string {
data := strings.SplitN(s, ":", 2)
return data[0]
scheme, _, _ := strings.Cut(s, ":")
return scheme
}

View File

@ -59,8 +59,8 @@ func ParseConfig(s string) (interface{}, error) {
return nil, errors.New("s3: bucket name not found")
}
path := strings.SplitN(url.Path[1:], "/", 2)
return createConfig(url.Host, path, url.Scheme == "http")
bucket, path, _ := strings.Cut(url.Path[1:], "/")
return createConfig(url.Host, bucket, path, url.Scheme == "http")
case strings.HasPrefix(s, "s3://"):
s = s[5:]
case strings.HasPrefix(s, "s3:"):
@ -70,24 +70,24 @@ func ParseConfig(s string) (interface{}, error) {
}
// use the first entry of the path as the endpoint and the
// remainder as bucket name and prefix
path := strings.SplitN(s, "/", 3)
return createConfig(path[0], path[1:], false)
endpoint, rest, _ := strings.Cut(s, "/")
bucket, prefix, _ := strings.Cut(rest, "/")
return createConfig(endpoint, bucket, prefix, false)
}
func createConfig(endpoint string, p []string, useHTTP bool) (interface{}, error) {
if len(p) < 1 {
func createConfig(endpoint, bucket, prefix string, useHTTP bool) (interface{}, error) {
if endpoint == "" {
return nil, errors.New("s3: invalid format, host/region or bucket name not found")
}
var prefix string
if len(p) > 1 && p[1] != "" {
prefix = path.Clean(p[1])
if prefix != "" {
prefix = path.Clean(prefix)
}
cfg := NewConfig()
cfg.Endpoint = endpoint
cfg.UseHTTP = useHTTP
cfg.Bucket = p[0]
cfg.Bucket = bucket
cfg.Prefix = prefix
return cfg, nil
}

View File

@ -1,6 +1,9 @@
package s3
import "testing"
import (
"strings"
"testing"
)
var configTests = []struct {
s string
@ -111,3 +114,14 @@ func TestParseConfig(t *testing.T) {
}
}
}
func TestParseError(t *testing.T) {
const prefix = "s3: invalid format,"
for _, s := range []string{"", "/", "//", "/bucket/prefix"} {
_, err := ParseConfig("s3://" + s)
if err == nil || !strings.HasPrefix(err.Error(), prefix) {
t.Errorf("expected %q, got %q", prefix, err)
}
}
}

View File

@ -60,14 +60,13 @@ func ParseConfig(s string) (interface{}, error) {
// "user@host:path" in s
s = s[5:]
// split user@host and path at the colon
data := strings.SplitN(s, ":", 2)
if len(data) < 2 {
var colon bool
host, dir, colon = strings.Cut(s, ":")
if !colon {
return nil, errors.New("sftp: invalid format, hostname or path not found")
}
host = data[0]
dir = data[1]
// split user and host at the "@"
data = strings.SplitN(host, "@", 3)
data := strings.SplitN(host, "@", 3)
if len(data) == 3 {
user = data[0] + "@" + data[1]
host = data[2]

View File

@ -51,17 +51,13 @@ func NewConfig() Config {
// ParseConfig parses the string s and extract swift's container name and prefix.
func ParseConfig(s string) (interface{}, error) {
data := strings.SplitN(s, ":", 3)
if len(data) != 3 {
if !strings.HasPrefix(s, "swift:") {
return nil, errors.New("invalid URL, expected: swift:container-name:/[prefix]")
}
s = strings.TrimPrefix(s, "swift:")
scheme, container, prefix := data[0], data[1], data[2]
if scheme != "swift" {
return nil, errors.Errorf("unexpected prefix: %s", data[0])
}
if len(prefix) == 0 {
container, prefix, _ := strings.Cut(s, ":")
if prefix == "" {
return nil, errors.Errorf("prefix is empty")
}

View File

@ -92,14 +92,10 @@ func (h helpList) Swap(i, j int) {
// splitKeyValue splits at the first equals (=) sign.
func splitKeyValue(s string) (key string, value string) {
data := strings.SplitN(s, "=", 2)
key = strings.ToLower(strings.TrimSpace(data[0]))
if len(data) == 1 {
// no equals sign is treated as the empty value
return key, ""
}
return key, strings.TrimSpace(data[1])
key, value, _ = strings.Cut(s, "=")
key = strings.ToLower(strings.TrimSpace(key))
value = strings.TrimSpace(value)
return key, value
}
// Parse takes a slice of key=value pairs and returns an Options type.