1
0
mirror of https://github.com/osmarks/mycorrhiza.git synced 2024-12-05 02:29:54 +00:00

Introduce EmptyHypha

This commit is contained in:
Timur Ismagilov 2022-02-04 16:14:53 +05:00 committed by Timur Ismagilov
parent a30d581bfd
commit 6b3e8a245c
4 changed files with 101 additions and 72 deletions

36
hyphae/empty_hypha.go Normal file
View File

@ -0,0 +1,36 @@
package hyphae
import "sync"
type EmptyHypha struct {
sync.RWMutex
canonicalName string
}
func (e *EmptyHypha) CanonicalName() string {
return e.canonicalName
}
func (e *EmptyHypha) Kind() HyphaKind {
return HyphaEmpty
}
func (e *EmptyHypha) DoesExist() bool {
return false
}
func (e *EmptyHypha) HasTextPart() bool {
return false
}
func (e *EmptyHypha) TextPartPath() string {
return ""
}
// NewEmptyHypha returns an empty hypha struct with given name.
func NewEmptyHypha(hyphaName string) *EmptyHypha {
return &EmptyHypha{
canonicalName: hyphaName,
}
}

View File

@ -1,6 +1,26 @@
package hyphae
import "sync"
import (
"regexp"
"strings"
"sync"
)
// HyphaPattern is a pattern which all hyphae names must match.
var HyphaPattern = regexp.MustCompile(`[^?!:#@><*|"'&%{}]+`)
// IsValidName checks for invalid characters and path traversals.
func IsValidName(hyphaName string) bool {
if !HyphaPattern.MatchString(hyphaName) {
return false
}
for _, segment := range strings.Split(hyphaName, "/") {
if segment == ".git" || segment == ".." {
return false
}
}
return true
}
type HyphaKind int
@ -42,3 +62,43 @@ func RenameHyphaTo(h Hypher, newName string) {
byNamesMutex.Unlock()
h.Unlock()
}
// insert inserts the hypha into the storage. A previous record is used if possible. Count incrementation is done if needed.
func insert(h Hypher) (madeNewRecord bool) {
hp, recorded := byNames[h.CanonicalName()]
if recorded {
hp.(*MediaHypha).mergeIn(h)
} else {
storeHypha(h)
incrementCount()
}
return !recorded
}
// InsertIfNew checks whether hypha exists and returns `true` if it didn't and has been created.
func InsertIfNew(h Hypher) (madeNewRecord bool) {
if h.DoesExist() {
return false
}
return insert(h)
}
func storeHypha(h Hypher) {
byNamesMutex.Lock()
byNames[h.CanonicalName()] = h
byNamesMutex.Unlock()
h.Lock()
h.(*MediaHypha).Exists = true
h.Unlock()
}
// ByName returns a hypha by name. It may have been recorded to the storage.
func ByName(hyphaName string) (h Hypher) {
h, recorded := byNames[hyphaName]
if recorded {
return h
}
return NewEmptyHypha(hyphaName)
}

View File

@ -5,8 +5,12 @@ package hyphae
import (
"sort"
"strings"
"sync"
)
var byNames = make(map[string]Hypher)
var byNamesMutex = sync.Mutex{}
// YieldExistingHyphae iterates over all hyphae and yields all existing ones.
func YieldExistingHyphae() chan Hypher {
ch := make(chan Hypher)

View File

@ -4,29 +4,11 @@ package hyphae
import (
"log"
"path/filepath"
"regexp"
"strings"
"sync"
"github.com/bouncepaw/mycorrhiza/files"
)
// HyphaPattern is a pattern which all hyphae names must match.
var HyphaPattern = regexp.MustCompile(`[^?!:#@><*|"'&%{}]+`)
// IsValidName checks for invalid characters and path traversals.
func IsValidName(hyphaName string) bool {
if !HyphaPattern.MatchString(hyphaName) {
return false
}
for _, segment := range strings.Split(hyphaName, "/") {
if segment == ".git" || segment == ".." {
return false
}
}
return true
}
// MediaHypha keeps vital information about a media hypha
type MediaHypha struct {
sync.RWMutex
@ -77,59 +59,6 @@ func (h *MediaHypha) HasAttachment() bool {
return h.binaryPath != ""
}
var byNames = make(map[string]Hypher)
var byNamesMutex = sync.Mutex{}
// EmptyHypha returns an empty hypha struct with given name.
func EmptyHypha(hyphaName string) *MediaHypha {
return &MediaHypha{
name: hyphaName,
Exists: false,
TextPath: "",
binaryPath: "",
}
}
// ByName returns a hypha by name. It may have been recorded to the storage.
func ByName(hyphaName string) (h Hypher) {
h, recorded := byNames[hyphaName]
if recorded {
return h
}
return EmptyHypha(hyphaName)
}
func storeHypha(h Hypher) {
byNamesMutex.Lock()
byNames[h.CanonicalName()] = h
byNamesMutex.Unlock()
h.Lock()
h.(*MediaHypha).Exists = true
h.Unlock()
}
// insert inserts the hypha into the storage. A previous record is used if possible. Count incrementation is done if needed.
func insert(h Hypher) (madeNewRecord bool) {
hp, recorded := byNames[h.CanonicalName()]
if recorded {
hp.(*MediaHypha).mergeIn(h)
} else {
storeHypha(h)
incrementCount()
}
return !recorded
}
// InsertIfNew checks whether hypha exists and returns `true` if it didn't and has been created.
func InsertIfNew(h Hypher) (madeNewRecord bool) {
if h.DoesExist() {
return false
}
return insert(h)
}
// mergeIn merges in content file paths from a different hypha object. Prints warnings sometimes.
func (h *MediaHypha) mergeIn(oh Hypher) {
if h == oh {