mirror of
https://github.com/osmarks/mycorrhiza.git
synced 2025-07-05 11:02:49 +00:00
Introduce EmptyHypha
This commit is contained in:
parent
a30d581bfd
commit
6b3e8a245c
36
hyphae/empty_hypha.go
Normal file
36
hyphae/empty_hypha.go
Normal 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,
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,26 @@
|
|||||||
package hyphae
|
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
|
type HyphaKind int
|
||||||
|
|
||||||
@ -42,3 +62,43 @@ func RenameHyphaTo(h Hypher, newName string) {
|
|||||||
byNamesMutex.Unlock()
|
byNamesMutex.Unlock()
|
||||||
h.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)
|
||||||
|
}
|
||||||
|
@ -5,8 +5,12 @@ package hyphae
|
|||||||
import (
|
import (
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var byNames = make(map[string]Hypher)
|
||||||
|
var byNamesMutex = sync.Mutex{}
|
||||||
|
|
||||||
// YieldExistingHyphae iterates over all hyphae and yields all existing ones.
|
// YieldExistingHyphae iterates over all hyphae and yields all existing ones.
|
||||||
func YieldExistingHyphae() chan Hypher {
|
func YieldExistingHyphae() chan Hypher {
|
||||||
ch := make(chan Hypher)
|
ch := make(chan Hypher)
|
||||||
|
@ -4,29 +4,11 @@ package hyphae
|
|||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/bouncepaw/mycorrhiza/files"
|
"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
|
// MediaHypha keeps vital information about a media hypha
|
||||||
type MediaHypha struct {
|
type MediaHypha struct {
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
@ -77,59 +59,6 @@ func (h *MediaHypha) HasAttachment() bool {
|
|||||||
return h.binaryPath != ""
|
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.
|
// mergeIn merges in content file paths from a different hypha object. Prints warnings sometimes.
|
||||||
func (h *MediaHypha) mergeIn(oh Hypher) {
|
func (h *MediaHypha) mergeIn(oh Hypher) {
|
||||||
if h == oh {
|
if h == oh {
|
Loading…
x
Reference in New Issue
Block a user