Compare commits
	
		
			No commits in common. "master" and "1.0.0" have entirely different histories.
		
	
	
		
	
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@ -1 +0,0 @@
 | 
			
		||||
/cmd/
 | 
			
		||||
							
								
								
									
										10
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								go.mod
									
									
									
									
									
								
							@ -1,3 +1,11 @@
 | 
			
		||||
module git.tswf.io/incredible-go/incredible-go-core
 | 
			
		||||
 | 
			
		||||
go 1.20
 | 
			
		||||
go 1.22.0
 | 
			
		||||
 | 
			
		||||
//replace (
 | 
			
		||||
//	"git.tswf.io/incredible-go/incredible-go-core" lateswhict => "C:\Soft\intellij\workspaces\golang\go-workspace\library\incredible-go\incredible-go-core"
 | 
			
		||||
//)
 | 
			
		||||
//
 | 
			
		||||
//require (
 | 
			
		||||
//	"git.tswf.io/incredible-go/incredible-go-core" latest
 | 
			
		||||
//)
 | 
			
		||||
@ -6,10 +6,3 @@ func NewArrayList[T any]() *ArrayList[T] {
 | 
			
		||||
		size:    0,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewArrayListWithContent[T any](content ...T) *ArrayList[T] {
 | 
			
		||||
	result := NewArrayList[T]()
 | 
			
		||||
	result.AddAllS(&content)
 | 
			
		||||
 | 
			
		||||
	return result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,20 +0,0 @@
 | 
			
		||||
package array_list
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func (a *ArrayList[T]) MarshalJSON() ([]byte, error) {
 | 
			
		||||
	return json.Marshal(a.content[:a.size])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a *ArrayList[T]) UnmarshalJSON(data []byte) error {
 | 
			
		||||
	var content []T
 | 
			
		||||
	if err := json.Unmarshal(data, &content); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	a.content = content
 | 
			
		||||
	a.size = len(content)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
@ -3,9 +3,6 @@ package array_list
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"slices"
 | 
			
		||||
 | 
			
		||||
	"git.tswf.io/incredible-go/incredible-go-core/pkg/container/optional"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func (self *ArrayList[T]) Add(element T) {
 | 
			
		||||
@ -18,42 +15,21 @@ func (self *ArrayList[T]) Add(element T) {
 | 
			
		||||
	self.size++
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *ArrayList[T]) RemoveIf(filter func(T) bool) {
 | 
			
		||||
	index := 0
 | 
			
		||||
	for {
 | 
			
		||||
		if index >= self.size {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		element := self.content[index]
 | 
			
		||||
		shouldRemove := filter(element)
 | 
			
		||||
 | 
			
		||||
		if shouldRemove {
 | 
			
		||||
			self.RemoveByIndex(index)
 | 
			
		||||
		} else {
 | 
			
		||||
			index++
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *ArrayList[T]) Remove(element T) {
 | 
			
		||||
	indexFromMove := -1
 | 
			
		||||
	for index, value := range self.content {
 | 
			
		||||
 | 
			
		||||
		if any(value) == any(element) {
 | 
			
		||||
			indexFromMove = index
 | 
			
		||||
			indexFromMove = index + 1
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	self.RemoveByIndex(indexFromMove)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *ArrayList[T]) RemoveByIndex(index int) {
 | 
			
		||||
	contentSize := len(self.content)
 | 
			
		||||
 | 
			
		||||
	if index >= 0 {
 | 
			
		||||
		for i := index + 1; i < contentSize; i++ {
 | 
			
		||||
	if indexFromMove >= 0 {
 | 
			
		||||
 | 
			
		||||
		for i := indexFromMove; i < contentSize; i++ {
 | 
			
		||||
			self.content[i-1] = self.content[i]
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -101,22 +77,6 @@ func (self *ArrayList[T]) AddAll(list *ArrayList[T]) {
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *ArrayList[T]) AddAllS(slice *[]T) {
 | 
			
		||||
	for _, v := range *slice {
 | 
			
		||||
		self.Add(v)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *ArrayList[T]) SetAll(list *ArrayList[T]) {
 | 
			
		||||
	self.Clear()
 | 
			
		||||
	self.AddAll(list)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *ArrayList[T]) SetAllS(list *[]T) {
 | 
			
		||||
	self.Clear()
 | 
			
		||||
	self.AddAllS(list)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *ArrayList[T]) Any(test func(T) bool) bool {
 | 
			
		||||
	for index, value := range self.content {
 | 
			
		||||
		if index >= self.size {
 | 
			
		||||
@ -167,67 +127,3 @@ func (self *ArrayList[T]) IsEmpty() bool {
 | 
			
		||||
func (self *ArrayList[T]) String() string {
 | 
			
		||||
	return fmt.Sprintf("%v", self.content)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *ArrayList[T]) Clear() {
 | 
			
		||||
	self.content = self.content[:0]
 | 
			
		||||
	self.size = 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *ArrayList[T]) GetLast() T {
 | 
			
		||||
	if self.IsEmpty() {
 | 
			
		||||
		panic(any(errors.New("trying to get last element from empty array list")))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return self.Get(self.Size() - 1)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *ArrayList[T]) GetFirst() T {
 | 
			
		||||
	if self.IsEmpty() {
 | 
			
		||||
		panic(any(errors.New("trying to get first element from empty array list")))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return self.Get(0)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *ArrayList[T]) ToSlice() []T {
 | 
			
		||||
	result := slices.Clone(self.content)[:self.size]
 | 
			
		||||
	return result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *ArrayList[T]) ToSliceUnsafe() []T {
 | 
			
		||||
	return self.content[:self.size]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *ArrayList[T]) Find(filter func(T) bool) *optional.Optional[T] {
 | 
			
		||||
	for index, value := range self.content {
 | 
			
		||||
		if index >= self.size {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		passed := filter(value)
 | 
			
		||||
 | 
			
		||||
		if passed {
 | 
			
		||||
			return optional.OfAny(value)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return optional.Empty[T]()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *ArrayList[T]) Filter(filter func(T) bool) *ArrayList[T] {
 | 
			
		||||
	return self.FilterTo(filter, NewArrayList[T]())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *ArrayList[T]) FilterTo(filter func(T) bool, resultList *ArrayList[T]) *ArrayList[T] {
 | 
			
		||||
	if resultList == nil {
 | 
			
		||||
		panic(fmt.Errorf("can not filter %v to nil list", self))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	self.ForEach(func(value T) {
 | 
			
		||||
		if filter(value) {
 | 
			
		||||
			resultList.Add(value)
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	return resultList
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,20 +0,0 @@
 | 
			
		||||
package array_list
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func (a *ArrayList[T]) MarshalXML() ([]byte, error) {
 | 
			
		||||
	return json.Marshal(a.content[:a.size])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a *ArrayList[T]) UnmarshalXML(data []byte) error {
 | 
			
		||||
	var content []T
 | 
			
		||||
	if err := json.Unmarshal(data, &content); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	a.content = content
 | 
			
		||||
	a.size = len(content)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
@ -1,20 +0,0 @@
 | 
			
		||||
package array_list
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func (a *ArrayList[T]) MarshalYAML() ([]byte, error) {
 | 
			
		||||
	return json.Marshal(a.content[:a.size])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a *ArrayList[T]) UnmarshalYAML(data []byte) error {
 | 
			
		||||
	var content []T
 | 
			
		||||
	if err := json.Unmarshal(data, &content); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	a.content = content
 | 
			
		||||
	a.size = len(content)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
@ -1,6 +0,0 @@
 | 
			
		||||
package optional
 | 
			
		||||
 | 
			
		||||
type Optional[T any] struct {
 | 
			
		||||
	Present bool
 | 
			
		||||
	Value   T
 | 
			
		||||
}
 | 
			
		||||
@ -1,23 +0,0 @@
 | 
			
		||||
package optional
 | 
			
		||||
 | 
			
		||||
func Empty[T any]() *Optional[T] {
 | 
			
		||||
	return &Optional[T]{
 | 
			
		||||
		Present: false,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func OfAny[T any](value T) *Optional[T] {
 | 
			
		||||
	return &Optional[T]{
 | 
			
		||||
		Present: true,
 | 
			
		||||
		Value:   value,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func OfNonDefault[T comparable](value T) *Optional[T] {
 | 
			
		||||
	var defaultValue T
 | 
			
		||||
	if value != defaultValue {
 | 
			
		||||
		return Empty[T]()
 | 
			
		||||
	} else {
 | 
			
		||||
		return OfAny[T](value)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -1,59 +0,0 @@
 | 
			
		||||
package optional
 | 
			
		||||
 | 
			
		||||
import "log"
 | 
			
		||||
 | 
			
		||||
func (self *Optional[T]) IfPresent(action func(T)) {
 | 
			
		||||
	if self.Present {
 | 
			
		||||
		action(self.Value)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *Optional[T]) OrElsePanic(err error) T {
 | 
			
		||||
	return self.OrElsePanicF(func() error {
 | 
			
		||||
		return err
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *Optional[T]) OrElsePanicF(errorSupplier func() error) T {
 | 
			
		||||
	if self.Present {
 | 
			
		||||
		return self.Value
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := errorSupplier()
 | 
			
		||||
	panic(err)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *Optional[T]) OrElseFatal(err error) T {
 | 
			
		||||
	return self.OrElseFatalF(func() error {
 | 
			
		||||
		return err
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *Optional[T]) OrElseFatalF(errorSupplier func() error) T {
 | 
			
		||||
	if self.Present {
 | 
			
		||||
		return self.Value
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := errorSupplier()
 | 
			
		||||
	var returnStub T
 | 
			
		||||
	log.Fatal(err)
 | 
			
		||||
 | 
			
		||||
	// Компилятор без return не пропустит, но сюда никогда не дойдет из-за фатала выше.
 | 
			
		||||
	return returnStub
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *Optional[T]) OrElse(defaultValue T) T {
 | 
			
		||||
	if self.Present {
 | 
			
		||||
		return self.Value
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return defaultValue
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *Optional[T]) OrElseGet(defaultValueSupplier func() T) T {
 | 
			
		||||
	if self.Present {
 | 
			
		||||
		return self.Value
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return defaultValueSupplier()
 | 
			
		||||
}
 | 
			
		||||
@ -1,37 +0,0 @@
 | 
			
		||||
package progress
 | 
			
		||||
 | 
			
		||||
import "io"
 | 
			
		||||
 | 
			
		||||
type WriteProgressCallback func(uint64, uint64)
 | 
			
		||||
 | 
			
		||||
type WriteProgressListener struct {
 | 
			
		||||
	BytesWritten     uint64
 | 
			
		||||
	ProgressCallback WriteProgressCallback
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *WriteProgressListener) Write(p []byte) (int, error) {
 | 
			
		||||
	n := len(p)
 | 
			
		||||
	newTotal := self.BytesWritten + uint64(n)
 | 
			
		||||
 | 
			
		||||
	if self.ProgressCallback != nil {
 | 
			
		||||
		self.ProgressCallback(self.BytesWritten, newTotal)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	self.BytesWritten = newTotal
 | 
			
		||||
	return n, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *WriteProgressListener) WrapReader(reader io.Reader) io.Reader {
 | 
			
		||||
	return io.TeeReader(reader, self)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewProgressListener(callback WriteProgressCallback) *WriteProgressListener {
 | 
			
		||||
	return &WriteProgressListener{
 | 
			
		||||
		BytesWritten:     0,
 | 
			
		||||
		ProgressCallback: callback,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func WrapReader(reader io.Reader, callback WriteProgressCallback) io.Reader {
 | 
			
		||||
	return NewProgressListener(callback).WrapReader(reader)
 | 
			
		||||
}
 | 
			
		||||
@ -1,77 +0,0 @@
 | 
			
		||||
package hasher
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto/md5"
 | 
			
		||||
	"crypto/sha256"
 | 
			
		||||
	"encoding/hex"
 | 
			
		||||
	"hash"
 | 
			
		||||
	"io"
 | 
			
		||||
	"os"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Hasher struct {
 | 
			
		||||
	HashSupplier func() hash.Hash
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewSha256Hasher() *Hasher {
 | 
			
		||||
	return NewHasher(func() hash.Hash {
 | 
			
		||||
		return sha256.New()
 | 
			
		||||
	},
 | 
			
		||||
	)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewMd5Hasher() *Hasher {
 | 
			
		||||
	return NewHasher(func() hash.Hash {
 | 
			
		||||
		return md5.New()
 | 
			
		||||
	},
 | 
			
		||||
	)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewHasher(hashSupplier func() hash.Hash) *Hasher {
 | 
			
		||||
	return &Hasher{
 | 
			
		||||
		HashSupplier: hashSupplier,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *Hasher) GetFileHashString(fileLocation string) (string, error) {
 | 
			
		||||
	bytes, err := self.GetFileHashBytes(fileLocation)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return convertBytesToString(bytes), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *Hasher) GetFileHashBytes(fileLocation string) ([]byte, error) {
 | 
			
		||||
	file, err := os.Open(fileLocation)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	defer file.Close()
 | 
			
		||||
 | 
			
		||||
	return self.GetHashBytes(file)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *Hasher) GetHashString(reader io.Reader) (string, error) {
 | 
			
		||||
	bytes, err := self.GetHashBytes(reader)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return convertBytesToString(bytes), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *Hasher) GetHashBytes(reader io.Reader) ([]byte, error) {
 | 
			
		||||
	hasher := self.HashSupplier()
 | 
			
		||||
	_, err := io.Copy(hasher, reader)
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return hasher.Sum(nil), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func convertBytesToString(bytes []byte) string {
 | 
			
		||||
	return hex.EncodeToString(bytes)
 | 
			
		||||
}
 | 
			
		||||
@ -1,17 +0,0 @@
 | 
			
		||||
package files
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func GetPermForDir(dirLocation string) os.FileMode {
 | 
			
		||||
	userHome, err := os.UserHomeDir()
 | 
			
		||||
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		if IsFileLocatedIn(dirLocation, userHome) {
 | 
			
		||||
			return DirUserPermitted
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return DirAllPermitted
 | 
			
		||||
}
 | 
			
		||||
@ -1,10 +0,0 @@
 | 
			
		||||
package files
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func MkdirsAutoPerm(dirLocation string) error {
 | 
			
		||||
	perm := GetPermForDir(dirLocation)
 | 
			
		||||
	return os.MkdirAll(dirLocation, perm)
 | 
			
		||||
}
 | 
			
		||||
@ -1,43 +0,0 @@
 | 
			
		||||
package files
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func IsFileExists(fileLocation string) bool {
 | 
			
		||||
	if _, err := os.Stat(fileLocation); errors.Is(err, os.ErrNotExist) {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetFirstIndexedNonExistingFilePath(parentDir string, fileBaseName string) string {
 | 
			
		||||
	filePath := filepath.Join(parentDir, fileBaseName)
 | 
			
		||||
 | 
			
		||||
	if !IsFileExists(filePath) {
 | 
			
		||||
		return filePath
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fileIndex := 0
 | 
			
		||||
	fileBaseNameWithoutExtension := GetSimpleNameWithoutExtension(fileBaseName)
 | 
			
		||||
	fileExtension := GetExtension(fileBaseName)
 | 
			
		||||
	if fileExtension != "" {
 | 
			
		||||
		fileExtension = "." + fileExtension
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for {
 | 
			
		||||
		if !IsFileExists(filePath) {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		fileIndex++
 | 
			
		||||
 | 
			
		||||
		filePath = filepath.Join(parentDir, fmt.Sprintf("%s-%d%s", fileBaseNameWithoutExtension, fileIndex, fileExtension))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return filePath
 | 
			
		||||
}
 | 
			
		||||
@ -1,22 +0,0 @@
 | 
			
		||||
package files
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func IsFileLocatedIn(fileToCheck string, dirInWhichLocated string) bool {
 | 
			
		||||
	fileToCheck = TryAbs(fileToCheck)
 | 
			
		||||
	dirInWhichLocated = TryAbs(dirInWhichLocated)
 | 
			
		||||
 | 
			
		||||
	if runtime.GOOS == "windows" {
 | 
			
		||||
		fileToCheck = strings.ToLower(fileToCheck)
 | 
			
		||||
		dirInWhichLocated = strings.ToLower(dirInWhichLocated)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fileToCheck = filepath.ToSlash(fileToCheck)
 | 
			
		||||
	dirInWhichLocated = filepath.ToSlash(dirInWhichLocated)
 | 
			
		||||
 | 
			
		||||
	return strings.HasPrefix(fileToCheck, dirInWhichLocated+"/")
 | 
			
		||||
}
 | 
			
		||||
@ -1,84 +0,0 @@
 | 
			
		||||
package files
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"slices"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"git.tswf.io/incredible-go/incredible-go-core/pkg/collections/array_list"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var RestrictedFilepathCharactersReplacements = map[string]string{
 | 
			
		||||
	"<":  "<",
 | 
			
		||||
	">":  ">",
 | 
			
		||||
	":":  ":",
 | 
			
		||||
	"\"": """,
 | 
			
		||||
	"/":  "/",
 | 
			
		||||
	"\\": "\",
 | 
			
		||||
	"|":  "|",
 | 
			
		||||
	"?":  "?",
 | 
			
		||||
	"*":  "*",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetSimpleName(filePath string) string {
 | 
			
		||||
	return SplitFileName(filePath).GetLast()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetExtension(filePath string) string {
 | 
			
		||||
	split := strings.Split(filePath, ".")
 | 
			
		||||
	if len(split) == 1 {
 | 
			
		||||
		return ""
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return split[len(split)-1]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetSimpleNameWithoutExtension(filePath string) string {
 | 
			
		||||
	simpleName := GetSimpleName(filePath)
 | 
			
		||||
	split := slices.DeleteFunc(strings.Split(simpleName, "."), func(s string) bool {
 | 
			
		||||
		return s == ""
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	if len(split) == 1 {
 | 
			
		||||
		return filePath
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return strings.Join(split[:len(split)-1], "")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func SplitFileName(filePath string) *array_list.ArrayList[string] {
 | 
			
		||||
	filePath = filepath.ToSlash(filePath)
 | 
			
		||||
	split := strings.Split(filePath, "/")
 | 
			
		||||
 | 
			
		||||
	return array_list.NewArrayListWithContent[string](split...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ReplaceAllRestrictedCharacters(filePath string) string {
 | 
			
		||||
	for k, v := range RestrictedFilepathCharactersReplacements {
 | 
			
		||||
		filePath = strings.ReplaceAll(filePath, k, v)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return filePath
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ReplaceAllRestrictedCharactersNoSlashes(filePath string) string {
 | 
			
		||||
	for k, v := range RestrictedFilepathCharactersReplacements {
 | 
			
		||||
		if k == "\\" || k == "/" {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		filePath = strings.ReplaceAll(filePath, k, v)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return filePath
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TryAbs(filePath string) string {
 | 
			
		||||
	if !filepath.IsAbs(filePath) {
 | 
			
		||||
		abs, err := filepath.Abs(filePath)
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			return abs
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return filePath
 | 
			
		||||
}
 | 
			
		||||
@ -1,15 +0,0 @@
 | 
			
		||||
package files
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func OpenFileForWriting(fileLocation string) (*os.File, error) {
 | 
			
		||||
	err := MkdirParent(fileLocation)
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return os.Create(fileLocation)
 | 
			
		||||
}
 | 
			
		||||
@ -1,8 +0,0 @@
 | 
			
		||||
package files
 | 
			
		||||
 | 
			
		||||
import "os"
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	DirUserPermitted os.FileMode = 0755
 | 
			
		||||
	DirAllPermitted              = os.ModePerm
 | 
			
		||||
)
 | 
			
		||||
@ -1,93 +0,0 @@
 | 
			
		||||
package files
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func CopyDir(src, dst string) error {
 | 
			
		||||
	src = filepath.Clean(src)
 | 
			
		||||
	dst = filepath.Clean(dst)
 | 
			
		||||
 | 
			
		||||
	si, err := os.Stat(src)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if !si.IsDir() {
 | 
			
		||||
		return fmt.Errorf("source is not a directory")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_, err = os.Stat(dst)
 | 
			
		||||
	if err != nil && !os.IsNotExist(err) {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		return fmt.Errorf("destination already exists")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = os.MkdirAll(dst, si.Mode())
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	entries, err := os.ReadDir(src)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, entry := range entries {
 | 
			
		||||
		srcPath := filepath.Join(src, entry.Name())
 | 
			
		||||
		dstPath := filepath.Join(dst, entry.Name())
 | 
			
		||||
 | 
			
		||||
		if entry.IsDir() {
 | 
			
		||||
			err = CopyDir(srcPath, dstPath)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			err = CopyFile(srcPath, dstPath)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func CopyFile(src, dst string) error {
 | 
			
		||||
	srcFile, err := os.Open(src)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	defer srcFile.Close()
 | 
			
		||||
 | 
			
		||||
	dstFile, err := os.Create(dst)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	defer dstFile.Close()
 | 
			
		||||
 | 
			
		||||
	_, err = io.Copy(dstFile, srcFile)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = dstFile.Sync()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	si, err := os.Stat(src)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	err = os.Chmod(dst, si.Mode())
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
@ -1,14 +0,0 @@
 | 
			
		||||
package files
 | 
			
		||||
 | 
			
		||||
func MkdirParent(fileLocation string) error {
 | 
			
		||||
	parentDir := GetParentDir(fileLocation)
 | 
			
		||||
	if parentDir != "" {
 | 
			
		||||
		parentDirCreationErr := MkdirsAutoPerm(parentDir)
 | 
			
		||||
 | 
			
		||||
		if parentDirCreationErr != nil {
 | 
			
		||||
			return parentDirCreationErr
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
@ -1,16 +0,0 @@
 | 
			
		||||
package files
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func GetParentDir(fileLocation string) string {
 | 
			
		||||
	fileLocation = filepath.ToSlash(fileLocation)
 | 
			
		||||
	indexOfSlash := strings.LastIndex(fileLocation, "/")
 | 
			
		||||
	if indexOfSlash > 0 {
 | 
			
		||||
		return fileLocation[:indexOfSlash]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ""
 | 
			
		||||
}
 | 
			
		||||
@ -1,58 +0,0 @@
 | 
			
		||||
package files
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io/fs"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
 | 
			
		||||
	"git.tswf.io/incredible-go/incredible-go-core/pkg/collections/array_list"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type FileFilter func(fileInfo os.FileInfo, fileName string) bool
 | 
			
		||||
 | 
			
		||||
func ListFiles(dirPath string) (*array_list.ArrayList[string], error) {
 | 
			
		||||
	dirInfo, err := os.Stat(dirPath)
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !dirInfo.IsDir() {
 | 
			
		||||
		return nil, fmt.Errorf("'%s' is not directory", dirPath)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dirEntries, err := os.ReadDir(dirPath)
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	result := array_list.NewArrayList[string]()
 | 
			
		||||
 | 
			
		||||
	if len(dirEntries) > 0 {
 | 
			
		||||
		for _, dirEntry := range dirEntries {
 | 
			
		||||
			result.Add(dirEntry.Name())
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return result, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func FindSubFilesByFilter(rootPath string, filter FileFilter) (*array_list.ArrayList[string], error) {
 | 
			
		||||
	result := array_list.NewArrayList[string]()
 | 
			
		||||
 | 
			
		||||
	err := filepath.Walk(rootPath, func(path string, info fs.FileInfo, err error) error {
 | 
			
		||||
		if err == nil && filter(info, path) {
 | 
			
		||||
			result.Add(path)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return err
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return result, nil
 | 
			
		||||
}
 | 
			
		||||
@ -1,84 +0,0 @@
 | 
			
		||||
package process_environment
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"log"
 | 
			
		||||
	"os"
 | 
			
		||||
	"os/exec"
 | 
			
		||||
	"slices"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"git.tswf.io/incredible-go/incredible-go-core/pkg/collections/array_list"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var PathEnvironmentVariableName = "PATH"
 | 
			
		||||
 | 
			
		||||
func AppendPath(cmd *exec.Cmd, newElements ...string) {
 | 
			
		||||
	pathEntries := array_list.NewArrayList[string]()
 | 
			
		||||
	for _, newPathEntry := range newElements {
 | 
			
		||||
		if !pathEntries.Contains(newPathEntry) {
 | 
			
		||||
			pathEntries.Add(newPathEntry)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pathEntries.AddAll(GetPath(cmd))
 | 
			
		||||
 | 
			
		||||
	SetPath(cmd, pathEntries.ToSliceUnsafe()...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func SetPath(cmd *exec.Cmd, entries ...string) {
 | 
			
		||||
	pathEntries := GetPath(cmd)
 | 
			
		||||
	for _, entry := range entries {
 | 
			
		||||
		if !pathEntries.Contains(entry) {
 | 
			
		||||
			pathEntries.Add(entry)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	newPathEnvValue := strings.Join(pathEntries.ToSliceUnsafe(), string(os.PathListSeparator))
 | 
			
		||||
	SetEnvironmentVariable(cmd, PathEnvironmentVariableName, newPathEnvValue)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetPath(cmd *exec.Cmd) *array_list.ArrayList[string] {
 | 
			
		||||
	oldPathEnvValue := GetEnvironmentVariable(cmd, PathEnvironmentVariableName)
 | 
			
		||||
	pathListSeparatorString := string(os.PathListSeparator)
 | 
			
		||||
 | 
			
		||||
	oldPathEnvEntries := array_list.NewArrayListWithContent(strings.Split(oldPathEnvValue, pathListSeparatorString)...)
 | 
			
		||||
 | 
			
		||||
	oldPathEnvEntries.RemoveIf(func(s string) bool {
 | 
			
		||||
		return s == ""
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	return oldPathEnvEntries
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func SetEnvironmentVariable(cmd *exec.Cmd, envName string, envValue string) *exec.Cmd {
 | 
			
		||||
	envPrefix := getEnvironmentVariablePrefix(envName)
 | 
			
		||||
	cmd.Env = slices.DeleteFunc(cmd.Env, func(s string) bool {
 | 
			
		||||
		return strings.HasPrefix(strings.ToLower(s), envPrefix)
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	cmd.Env = append(cmd.Env, envPrefix+envValue)
 | 
			
		||||
 | 
			
		||||
	return cmd
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetEnvironmentVariable(cmd *exec.Cmd, envName string) string {
 | 
			
		||||
	envPrefix := getEnvironmentVariablePrefix(envName)
 | 
			
		||||
	for _, env := range cmd.Env {
 | 
			
		||||
		if strings.HasPrefix(strings.ToLower(env), envPrefix) {
 | 
			
		||||
			split := strings.SplitN(env, "=", 2)
 | 
			
		||||
			if len(split) < 2 {
 | 
			
		||||
				log.Printf("%v is not valid split for env '%s'", cmd.Env, env)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ""
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func IsEnvironmentVariablePresent(cmd *exec.Cmd, envName string) bool {
 | 
			
		||||
	return GetEnvironmentVariable(cmd, envName) != ""
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getEnvironmentVariablePrefix(envName string) string {
 | 
			
		||||
	return strings.ToLower(envName + "=")
 | 
			
		||||
}
 | 
			
		||||
@ -1,24 +0,0 @@
 | 
			
		||||
package process_execution
 | 
			
		||||
 | 
			
		||||
import "os/exec"
 | 
			
		||||
 | 
			
		||||
func ExecuteAndGetOutput(command string, args ...string) (string, error) {
 | 
			
		||||
	return ExecuteAndGetOutputC(nil, command, args...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ExecuteAndGetOutputC(cfg func(*exec.Cmd), command string, args ...string) (string, error) {
 | 
			
		||||
	process := exec.Command(command, args...)
 | 
			
		||||
 | 
			
		||||
	if cfg != nil {
 | 
			
		||||
		cfg(process)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	outputBytes, err := process.CombinedOutput()
 | 
			
		||||
	outputString := ""
 | 
			
		||||
 | 
			
		||||
	if outputBytes != nil && len(outputBytes) > 0 {
 | 
			
		||||
		outputString = string(outputBytes)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return outputString, err
 | 
			
		||||
}
 | 
			
		||||
@ -1,85 +0,0 @@
 | 
			
		||||
package json_io
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
 | 
			
		||||
	"git.tswf.io/incredible-go/incredible-go-core/pkg/io/files"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func ReadFromJsonBytes[T any](jsonBytes []byte) (*T, error) {
 | 
			
		||||
	var result T
 | 
			
		||||
 | 
			
		||||
	err := json.Unmarshal(jsonBytes, &result)
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &result, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func WriteToJsonBytes[T any](value *T) ([]byte, error) {
 | 
			
		||||
	content, err := json.Marshal(value)
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return content, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ReadFromJsonString[T any](jsonString string) (*T, error) {
 | 
			
		||||
	return ReadFromJsonBytes[T]([]byte(jsonString))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func WriteToJsonString[T any](value *T) (string, error) {
 | 
			
		||||
	jsonBytes, err := WriteToJsonBytes(value)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return string(jsonBytes), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ReadFromJsonFile[T any](jsonFileLocation string) (*T, error) {
 | 
			
		||||
	fileInfo, err := os.Stat(jsonFileLocation)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if fileInfo.IsDir() {
 | 
			
		||||
		return nil, fmt.Errorf("json file '%s' can not be a directory", jsonFileLocation)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	jsonFileContentBytes, err := os.ReadFile(jsonFileLocation)
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ReadFromJsonBytes[T](jsonFileContentBytes)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func WriteToJsonFile[T any](jsonFileLocation string, value *T) ([]byte, error) {
 | 
			
		||||
	jsonBytes, err := WriteToJsonBytes(value)
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	file, err := files.OpenFileForWriting(jsonFileLocation)
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_, err = file.Write(jsonBytes)
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return jsonBytes, nil
 | 
			
		||||
}
 | 
			
		||||
@ -1,14 +0,0 @@
 | 
			
		||||
package string_utils
 | 
			
		||||
 | 
			
		||||
import "runtime"
 | 
			
		||||
 | 
			
		||||
func GetLineSeparator() string {
 | 
			
		||||
	switch runtime.GOOS {
 | 
			
		||||
	case "windows":
 | 
			
		||||
		return "\r\n"
 | 
			
		||||
	case "darwin":
 | 
			
		||||
		return "\r"
 | 
			
		||||
	default:
 | 
			
		||||
		return "\n"
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user