Select Git revision
tag.go 4.22 KiB
package store
import (
"encoding/json"
"fmt"
log "github.com/sirupsen/logrus"
"os"
"time"
)
const (
// ArtistType is the tag type artist.
ArtistType = "artist"
// CharacterType is the tag type character.
CharacterType = "character"
// CopyrightType is the tag type copyright.
CopyrightType = "copyright"
// MetaType is the tag type meta.
MetaType = "meta"
// GenericType is the tag type generic.
GenericType = "generic"
)
// Tag represents metadata of a tag.
type Tag struct {
Type string `json:"type"`
CreationTime time.Time `json:"creation_time"`
}
// Tags returns a slice of tag names.
func (s *Store) Tags() []string {
var tags []string
if entries, err := os.ReadDir(s.TagsDir()); err != nil {
s.fatalClose(fmt.Sprintf("Error reading tags, %s", err))
} else {
for _, entry := range entries {
if entry.IsDir() {
tags = append(tags, entry.Name())
}
}
}
return tags
}
// Tag returns a slice of image snowflakes in a specific tag.
func (s *Store) Tag(tag string) []string {
if !nameRegex.MatchString(tag) || !s.dir(s.TagPath(tag)) {
return nil
}
var images []string
if entries, err := os.ReadDir(s.TagPath(tag)); err != nil {
s.fatalClose(fmt.Sprintf("Error reading tag %s, %s", tag, err))
} else {
for _, entry := range entries {
if entry.Name() == infoJson {
continue
}
images = append(images, entry.Name())
}
}
return images
}
// TagCreate creates a tag and returns ok value.
func (s *Store) TagCreate(tag string) bool {
if len(tag) > 128 || !nameRegex.MatchString(tag) {
return false
}
if !s.dir(s.TagPath(tag)) {
s.getLock("tag_" + tag).Lock()
defer s.getLock("tag_" + tag).Unlock()
if err := os.Mkdir(s.TagPath(tag), s.PermissionDir); err != nil {
s.fatalClose(fmt.Sprintf("Error creating tag %s, %s", tag, err))
}
if payload, err := json.Marshal(Tag{Type: GenericType, CreationTime: time.Now().UTC()}); err != nil {
s.fatalClose(fmt.Sprintf("Error generating tag %s metadata, %s", tag, err))
} else {
if err = os.WriteFile(s.TagMetadataPath(tag), payload, s.PermissionFile); err != nil {
s.fatalClose(fmt.Sprintf("Error writing tag %s metadata, %s", tag, err))
}
}
log.Infof("Tag %s created.", tag)
return true
}
return true
}
// TagDestroy removes all references from a tag and removes it.
func (s *Store) TagDestroy(tag string) {
if !nameRegex.MatchString(tag) || !s.dir(s.TagPath(tag)) {
return
}
flakes := s.Tag(tag)
for _, flake := range flakes {
s.ImageTagRemove(flake, tag)
}
if err := os.Remove(s.TagMetadataPath(tag)); err != nil {
s.fatalClose(fmt.Sprintf("Error removing tag %s metadata, %s", tag, err))
}
if err := os.Remove(s.TagPath(tag)); err != nil {
s.fatalClose(fmt.Sprintf("Error removing tag %s, %s", tag, err))
}
log.Infof("Tag %s destroyed.", tag)
}
// TagInfo returns information of a tag.
func (s *Store) TagInfo(tag string) Tag {
if !nameRegex.MatchString(tag) || !s.file(s.TagMetadataPath(tag)) {
return Tag{}
}
s.getLock("tag_" + tag).RLock()
defer s.getLock("tag_" + tag).RUnlock()
if payload, err := os.ReadFile(s.TagMetadataPath(tag)); err != nil {
s.fatalClose(fmt.Sprintf("Error reading tag %s metadata, %s", tag, err))
} else {
var info Tag
if err = json.Unmarshal(payload, &info); err != nil {
s.fatalClose(fmt.Sprintf("Error parsing tag %s metadata, %s", tag, err))
} else {
return info
}
}
return Tag{}
}
// TagType sets type of a tag.
func (s *Store) TagType(tag, t string) {
if !nameRegex.MatchString(tag) || !s.file(s.TagMetadataPath(tag)) {
return
}
s.getLock("tag_" + tag).Lock()
defer s.getLock("tag_" + tag).Unlock()
if t != ArtistType &&
t != CharacterType &&
t != CopyrightType &&
t != GenericType &&
t != MetaType {
log.Warnf("Invalid tag change on tag %s, got %s, expecting {%s,%s,%s,%s,%s}", tag, t,
ArtistType, CharacterType, CopyrightType, GenericType, MetaType)
return
}
info := s.TagInfo(tag)
info.Type = t
if payload, err := json.Marshal(info); err != nil {
s.fatalClose(fmt.Sprintf("Error updating tag %s metadata, %s", tag, err))
} else {
if err = os.WriteFile(s.TagMetadataPath(tag), payload, s.PermissionFile); err != nil {
s.fatalClose(fmt.Sprintf("Error writing tag %s metadata, %s", tag, err))
}
}
log.Infof("Tag %s type set to %s.", tag, t)
}