s3browser-backend/internal/types/id.go

115 lines
2.3 KiB
Go

package types
import (
"fmt"
"path/filepath"
"regexp"
"strings"
)
var (
idRegex = regexp.MustCompile(`(.*?)(@(.*))?:(.*)`)
)
// ID an id of a file consists of at least a Bucket and a Key. Version is optional.
// Can also be used as an ID for a directory. When the key ends with "/" it is treated as dir.
type ID struct {
Bucket string `json:"bucket"` // Name of the bucket
Key string `json:"key"` // Key of the object
Version string `json:"version"` // Version of the object. For now we ignore it
}
// String Return String representation of an ID
// Looks like this: "bucketName@version:/id/of/obj" or "bucketName:/id/of/obj"
func (i ID) String() string {
if i.Version == "" {
return fmt.Sprintf("%s:%s", i.Bucket, i.Key)
} else {
return fmt.Sprintf("%s@%s:%s", i.Bucket, i.Version, i.Key)
}
}
// Normalize normalzes the key to have a "/" prefix
func (i *ID) Normalize() {
if i.Key == "." {
i.Key = "/"
} else if !strings.HasPrefix(i.Key, "/") {
i.Key = "/" + i.Key
}
}
// Valid checks if bucket and key is not empty
func (i *ID) Valid() bool {
return i.Bucket != "" && i.Key != ""
}
func (i *ID) IsDirectory() bool {
return strings.HasSuffix(i.Key, "/")
}
// Raw for the Key interface for the dataloaders so ID can be used as a dataloader key
func (i ID) Raw() interface{} {
return i
}
// Parent returns the parent dir ID. If its a file then return containing directory.
// If this is a directory then return the dir one up.
func (i ID) Parent() *ID {
if i.Key == "/" {
// Already at root. We dont have a parent
return nil
}
var parent *ID
if i.IsDirectory() {
parts := strings.Split(i.Key, "/")
parent = &ID{
Bucket: i.Bucket,
Key: strings.Join(parts[:len(parts)-2], "/") + "/",
}
} else {
dir := filepath.Dir(i.Key)
if dir != "/" {
dir += "/"
}
parent = &ID{
Bucket: i.Bucket,
Key: dir,
}
}
parent.Normalize()
return parent
}
// Name returns filename or directory name
func (i ID) Name() string {
return filepath.Base(i.Key)
}
// ParseID parses a string to an ID. Null if invalid
func ParseID(id string) *ID {
match := idRegex.FindStringSubmatch(id)
if match == nil {
return nil
}
rtn := &ID{
Bucket: match[1],
Version: match[3],
Key: match[4],
}
if !rtn.Valid() {
return nil
}
rtn.Normalize()
return rtn
}