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
|
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,
|
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 (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"slices"
|
|
||||||
|
|
||||||
"git.tswf.io/incredible-go/incredible-go-core/pkg/container/optional"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (self *ArrayList[T]) Add(element T) {
|
func (self *ArrayList[T]) Add(element T) {
|
||||||
@ -18,42 +15,21 @@ func (self *ArrayList[T]) Add(element T) {
|
|||||||
self.size++
|
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) {
|
func (self *ArrayList[T]) Remove(element T) {
|
||||||
indexFromMove := -1
|
indexFromMove := -1
|
||||||
for index, value := range self.content {
|
for index, value := range self.content {
|
||||||
|
|
||||||
if any(value) == any(element) {
|
if any(value) == any(element) {
|
||||||
indexFromMove = index
|
indexFromMove = index + 1
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.RemoveByIndex(indexFromMove)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *ArrayList[T]) RemoveByIndex(index int) {
|
|
||||||
contentSize := len(self.content)
|
contentSize := len(self.content)
|
||||||
|
|
||||||
if index >= 0 {
|
if indexFromMove >= 0 {
|
||||||
for i := index + 1; i < contentSize; i++ {
|
|
||||||
|
for i := indexFromMove; i < contentSize; i++ {
|
||||||
self.content[i-1] = self.content[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 {
|
func (self *ArrayList[T]) Any(test func(T) bool) bool {
|
||||||
for index, value := range self.content {
|
for index, value := range self.content {
|
||||||
if index >= self.size {
|
if index >= self.size {
|
||||||
@ -167,67 +127,3 @@ func (self *ArrayList[T]) IsEmpty() bool {
|
|||||||
func (self *ArrayList[T]) String() string {
|
func (self *ArrayList[T]) String() string {
|
||||||
return fmt.Sprintf("%v", self.content)
|
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