mirror of
				https://github.com/osmarks/mycorrhiza.git
				synced 2025-10-30 23:23:04 +00:00 
			
		
		
		
	Introduce EmptyHypha
This commit is contained in:
		 Timur Ismagilov
					Timur Ismagilov
				
			
				
					committed by
					
						 Timur Ismagilov
						Timur Ismagilov
					
				
			
			
				
	
			
			
			 Timur Ismagilov
						Timur Ismagilov
					
				
			
						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 | ||||
|  | ||||
| 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) | ||||
| } | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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 { | ||||
		Reference in New Issue
	
	Block a user