mirror of
https://github.com/octoleo/restic.git
synced 2024-11-25 06:07:44 +00:00
backend, options: Prefer strings.Cut to SplitN
Also realigned the various "split into host🪣prefix"
implementations.
This commit is contained in:
parent
60aa87bbab
commit
65612d797c
@ -43,14 +43,13 @@ func ParseConfig(s string) (interface{}, error) {
|
|||||||
|
|
||||||
// use the first entry of the path as the bucket name and the
|
// use the first entry of the path as the bucket name and the
|
||||||
// remainder as prefix
|
// remainder as prefix
|
||||||
data := strings.SplitN(s, ":", 2)
|
container, prefix, colon := strings.Cut(s, ":")
|
||||||
if len(data) < 2 {
|
if !colon {
|
||||||
return nil, errors.New("azure: invalid format: bucket name or path not found")
|
return nil, errors.New("azure: invalid format: bucket name or path not found")
|
||||||
}
|
}
|
||||||
container, path := data[0], path.Clean(data[1])
|
prefix = strings.TrimPrefix(path.Clean(prefix), "/")
|
||||||
path = strings.TrimPrefix(path, "/")
|
|
||||||
cfg := NewConfig()
|
cfg := NewConfig()
|
||||||
cfg.Container = container
|
cfg.Container = container
|
||||||
cfg.Prefix = path
|
cfg.Prefix = prefix
|
||||||
return cfg, nil
|
return cfg, nil
|
||||||
}
|
}
|
||||||
|
@ -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
|
// https://help.backblaze.com/hc/en-us/articles/217666908-What-you-need-to-know-about-B2-Bucket-names
|
||||||
func checkBucketName(name string) error {
|
func checkBucketName(name string) error {
|
||||||
if name == "" {
|
if name == "" {
|
||||||
return errors.New("bucket name is empty")
|
return errors.New("bucket name not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(name) < 6 {
|
if len(name) < 6 {
|
||||||
@ -64,30 +64,18 @@ func ParseConfig(s string) (interface{}, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
s = s[3:]
|
s = s[3:]
|
||||||
data := strings.SplitN(s, ":", 2)
|
bucket, prefix, _ := strings.Cut(s, ":")
|
||||||
if len(data) == 0 || len(data[0]) == 0 {
|
if err := checkBucketName(bucket); err != nil {
|
||||||
return nil, errors.New("bucket name not found")
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg := NewConfig()
|
|
||||||
cfg.Bucket = data[0]
|
|
||||||
|
|
||||||
if err := checkBucketName(cfg.Bucket); err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(data) == 2 {
|
if len(prefix) > 0 {
|
||||||
p := data[1]
|
prefix = strings.TrimPrefix(path.Clean(prefix), "/")
|
||||||
if len(p) > 0 {
|
|
||||||
p = path.Clean(p)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(p) > 0 && path.IsAbs(p) {
|
cfg := NewConfig()
|
||||||
p = p[1:]
|
cfg.Bucket = bucket
|
||||||
}
|
cfg.Prefix = prefix
|
||||||
|
|
||||||
cfg.Prefix = p
|
|
||||||
}
|
|
||||||
|
|
||||||
return cfg, nil
|
return cfg, nil
|
||||||
}
|
}
|
||||||
|
@ -42,17 +42,15 @@ func ParseConfig(s string) (interface{}, error) {
|
|||||||
|
|
||||||
// use the first entry of the path as the bucket name and the
|
// use the first entry of the path as the bucket name and the
|
||||||
// remainder as prefix
|
// remainder as prefix
|
||||||
data := strings.SplitN(s, ":", 2)
|
bucket, prefix, colon := strings.Cut(s, ":")
|
||||||
if len(data) < 2 {
|
if !colon {
|
||||||
return nil, errors.New("gs: invalid format: bucket name or path not found")
|
return nil, errors.New("gs: invalid format: bucket name or path not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
bucket, path := data[0], path.Clean(data[1])
|
prefix = strings.TrimPrefix(path.Clean(prefix), "/")
|
||||||
|
|
||||||
path = strings.TrimPrefix(path, "/")
|
|
||||||
|
|
||||||
cfg := NewConfig()
|
cfg := NewConfig()
|
||||||
cfg.Bucket = bucket
|
cfg.Bucket = bucket
|
||||||
cfg.Prefix = path
|
cfg.Prefix = prefix
|
||||||
return cfg, nil
|
return cfg, nil
|
||||||
}
|
}
|
||||||
|
@ -127,6 +127,6 @@ func StripPassword(s string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func extractScheme(s string) string {
|
func extractScheme(s string) string {
|
||||||
data := strings.SplitN(s, ":", 2)
|
scheme, _, _ := strings.Cut(s, ":")
|
||||||
return data[0]
|
return scheme
|
||||||
}
|
}
|
||||||
|
@ -59,8 +59,8 @@ func ParseConfig(s string) (interface{}, error) {
|
|||||||
return nil, errors.New("s3: bucket name not found")
|
return nil, errors.New("s3: bucket name not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
path := strings.SplitN(url.Path[1:], "/", 2)
|
bucket, path, _ := strings.Cut(url.Path[1:], "/")
|
||||||
return createConfig(url.Host, path, url.Scheme == "http")
|
return createConfig(url.Host, bucket, path, url.Scheme == "http")
|
||||||
case strings.HasPrefix(s, "s3://"):
|
case strings.HasPrefix(s, "s3://"):
|
||||||
s = s[5:]
|
s = s[5:]
|
||||||
case strings.HasPrefix(s, "s3:"):
|
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
|
// use the first entry of the path as the endpoint and the
|
||||||
// remainder as bucket name and prefix
|
// remainder as bucket name and prefix
|
||||||
path := strings.SplitN(s, "/", 3)
|
endpoint, rest, _ := strings.Cut(s, "/")
|
||||||
return createConfig(path[0], path[1:], false)
|
bucket, prefix, _ := strings.Cut(rest, "/")
|
||||||
|
return createConfig(endpoint, bucket, prefix, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func createConfig(endpoint string, p []string, useHTTP bool) (interface{}, error) {
|
func createConfig(endpoint, bucket, prefix string, useHTTP bool) (interface{}, error) {
|
||||||
if len(p) < 1 {
|
if endpoint == "" {
|
||||||
return nil, errors.New("s3: invalid format, host/region or bucket name not found")
|
return nil, errors.New("s3: invalid format, host/region or bucket name not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
var prefix string
|
if prefix != "" {
|
||||||
if len(p) > 1 && p[1] != "" {
|
prefix = path.Clean(prefix)
|
||||||
prefix = path.Clean(p[1])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg := NewConfig()
|
cfg := NewConfig()
|
||||||
cfg.Endpoint = endpoint
|
cfg.Endpoint = endpoint
|
||||||
cfg.UseHTTP = useHTTP
|
cfg.UseHTTP = useHTTP
|
||||||
cfg.Bucket = p[0]
|
cfg.Bucket = bucket
|
||||||
cfg.Prefix = prefix
|
cfg.Prefix = prefix
|
||||||
return cfg, nil
|
return cfg, nil
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
package s3
|
package s3
|
||||||
|
|
||||||
import "testing"
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
var configTests = []struct {
|
var configTests = []struct {
|
||||||
s string
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -60,14 +60,13 @@ func ParseConfig(s string) (interface{}, error) {
|
|||||||
// "user@host:path" in s
|
// "user@host:path" in s
|
||||||
s = s[5:]
|
s = s[5:]
|
||||||
// split user@host and path at the colon
|
// split user@host and path at the colon
|
||||||
data := strings.SplitN(s, ":", 2)
|
var colon bool
|
||||||
if len(data) < 2 {
|
host, dir, colon = strings.Cut(s, ":")
|
||||||
|
if !colon {
|
||||||
return nil, errors.New("sftp: invalid format, hostname or path not found")
|
return nil, errors.New("sftp: invalid format, hostname or path not found")
|
||||||
}
|
}
|
||||||
host = data[0]
|
|
||||||
dir = data[1]
|
|
||||||
// split user and host at the "@"
|
// split user and host at the "@"
|
||||||
data = strings.SplitN(host, "@", 3)
|
data := strings.SplitN(host, "@", 3)
|
||||||
if len(data) == 3 {
|
if len(data) == 3 {
|
||||||
user = data[0] + "@" + data[1]
|
user = data[0] + "@" + data[1]
|
||||||
host = data[2]
|
host = data[2]
|
||||||
|
@ -51,17 +51,13 @@ func NewConfig() Config {
|
|||||||
|
|
||||||
// ParseConfig parses the string s and extract swift's container name and prefix.
|
// ParseConfig parses the string s and extract swift's container name and prefix.
|
||||||
func ParseConfig(s string) (interface{}, error) {
|
func ParseConfig(s string) (interface{}, error) {
|
||||||
data := strings.SplitN(s, ":", 3)
|
if !strings.HasPrefix(s, "swift:") {
|
||||||
if len(data) != 3 {
|
|
||||||
return nil, errors.New("invalid URL, expected: swift:container-name:/[prefix]")
|
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]
|
container, prefix, _ := strings.Cut(s, ":")
|
||||||
if scheme != "swift" {
|
if prefix == "" {
|
||||||
return nil, errors.Errorf("unexpected prefix: %s", data[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(prefix) == 0 {
|
|
||||||
return nil, errors.Errorf("prefix is empty")
|
return nil, errors.Errorf("prefix is empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,14 +92,10 @@ func (h helpList) Swap(i, j int) {
|
|||||||
|
|
||||||
// splitKeyValue splits at the first equals (=) sign.
|
// splitKeyValue splits at the first equals (=) sign.
|
||||||
func splitKeyValue(s string) (key string, value string) {
|
func splitKeyValue(s string) (key string, value string) {
|
||||||
data := strings.SplitN(s, "=", 2)
|
key, value, _ = strings.Cut(s, "=")
|
||||||
key = strings.ToLower(strings.TrimSpace(data[0]))
|
key = strings.ToLower(strings.TrimSpace(key))
|
||||||
if len(data) == 1 {
|
value = strings.TrimSpace(value)
|
||||||
// no equals sign is treated as the empty value
|
return key, value
|
||||||
return key, ""
|
|
||||||
}
|
|
||||||
|
|
||||||
return key, strings.TrimSpace(data[1])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse takes a slice of key=value pairs and returns an Options type.
|
// Parse takes a slice of key=value pairs and returns an Options type.
|
||||||
|
Loading…
Reference in New Issue
Block a user