homebox/backend/pkgs/pathlib/pathlib.go
Hayden 31b34241e0
feat: item-attachments CRUD (#22)
* change /content/ -> /homebox/

* add cache to code generators

* update env variables to set data storage

* update env variables

* set env variables in prod container

* implement attachment post route (WIP)

* get attachment endpoint

* attachment download

* implement string utilities lib

* implement generic drop zone

* use explicit truncate

* remove clean dir

* drop strings composable for lib

* update item types and add attachments

* add attachment API

* implement service context

* consolidate API code

* implement editing attachments

* implement upload limit configuration

* improve error handling

* add docs for max upload size

* fix test cases
2022-09-24 11:33:38 -08:00

64 lines
1.3 KiB
Go

package pathlib
import (
"fmt"
"os"
"path/filepath"
"strings"
)
type dirReaderFunc func(name string) []string
var dirReader dirReaderFunc = func(directory string) []string {
f, err := os.Open(directory)
if err != nil {
return nil
}
defer f.Close()
names, err := f.Readdirnames(-1)
if err != nil {
return nil
}
return names
}
func hasConflict(path string, neighbors []string) bool {
filename := strings.ToLower(filepath.Base(path))
for _, n := range neighbors {
if strings.ToLower(n) == filename {
return true
}
}
return false
}
// Safe will take a destination path and return a validated path that is safe to use.
// without overwriting any existing files. If a conflict exists, it will append a number
// to the end of the file name. If the parent directory does not exist this function will
// return the original path.
func Safe(path string) string {
parent := filepath.Dir(path)
neighbors := dirReader(parent)
if neighbors == nil {
return path
}
if hasConflict(path, neighbors) {
ext := filepath.Ext(path)
name := strings.TrimSuffix(filepath.Base(path), ext)
for i := 1; i < 1000; i++ {
newName := fmt.Sprintf("%s (%d)%s", name, i, ext)
newPath := filepath.Join(parent, newName)
if !hasConflict(newPath, neighbors) {
return newPath
}
}
}
return path
}