274 lines
5.4 KiB
Go
274 lines
5.4 KiB
Go
package file
|
|
|
|
import (
|
|
"bufio"
|
|
"io"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
type FileInfo struct {
|
|
Name string
|
|
FullName string
|
|
IsDir bool
|
|
Size int64
|
|
ModTime int64
|
|
}
|
|
|
|
func EnsureParentDir(filename string) {
|
|
pos := strings.LastIndexByte(filename, os.PathSeparator)
|
|
if pos < 0 {
|
|
return
|
|
}
|
|
path := filename[0:pos]
|
|
if _, err := os.Stat(path); err != nil {
|
|
_ = os.MkdirAll(path, 0755)
|
|
}
|
|
}
|
|
|
|
func EnsureDirSuffix(path string) string {
|
|
const spe = string(os.PathSeparator)
|
|
if !strings.HasSuffix(path, spe) {
|
|
return path + spe
|
|
}
|
|
return path
|
|
}
|
|
|
|
func Exists(filename string) bool {
|
|
if mf := ReadFileFromMemory(filename); mf != nil {
|
|
return true
|
|
}
|
|
fi, err := os.Stat(filename)
|
|
return err == nil && fi != nil
|
|
}
|
|
|
|
func GetFileInfo(filename string) *FileInfo {
|
|
if mf := ReadFileFromMemory(filename); mf != nil {
|
|
return &FileInfo{
|
|
Name: mf.Name,
|
|
FullName: mf.AbsName,
|
|
IsDir: mf.IsDir,
|
|
Size: mf.Size,
|
|
ModTime: mf.ModTime.Unix(),
|
|
}
|
|
}
|
|
if fi, err := os.Stat(filename); err == nil {
|
|
fullName := filename
|
|
if !filepath.IsAbs(filename) {
|
|
fullName, _ = filepath.Abs(filename)
|
|
}
|
|
return &FileInfo{
|
|
Name: filename,
|
|
FullName: fullName,
|
|
IsDir: fi.IsDir(),
|
|
Size: fi.Size(),
|
|
ModTime: fi.ModTime().Unix(),
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func ReadBytes(filename string) ([]byte, error) {
|
|
if mf := ReadFileFromMemory(filename); mf != nil {
|
|
return mf.GetData(), nil
|
|
}
|
|
return os.ReadFile(filename)
|
|
}
|
|
|
|
func MustReadBytes(filename string) []byte {
|
|
buf, _ := ReadBytes(filename)
|
|
return buf
|
|
}
|
|
|
|
func Read(filename string) (string, error) {
|
|
buf, err := ReadBytes(filename)
|
|
return string(buf), err
|
|
}
|
|
|
|
func MustRead(filename string) string {
|
|
buf, _ := Read(filename)
|
|
return buf
|
|
}
|
|
|
|
func ReadLines(filename string) ([]string, error) {
|
|
if mf := ReadFileFromMemory(filename); mf != nil {
|
|
return strings.Split(string(mf.GetData()), "\n"), nil
|
|
}
|
|
file, err := os.Open(filename)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer file.Close()
|
|
|
|
var lines []string
|
|
scanner := bufio.NewScanner(file)
|
|
for scanner.Scan() {
|
|
lines = append(lines, scanner.Text())
|
|
}
|
|
return lines, scanner.Err()
|
|
}
|
|
|
|
func MustReadLines(filename string) []string {
|
|
lines, _ := ReadLines(filename)
|
|
return lines
|
|
}
|
|
|
|
func WriteBytes(filename string, content []byte) error {
|
|
absFilename := GetAbsFilename(filename)
|
|
memFilesLock.RLock()
|
|
mf := memFiles[absFilename]
|
|
memFilesLock.RUnlock()
|
|
if mf != nil {
|
|
memFilesLock.Lock()
|
|
mf.Data = content
|
|
mf.Size = int64(len(content))
|
|
mf.ModTime = time.Now()
|
|
memFilesLock.Unlock()
|
|
}
|
|
EnsureParentDir(filename)
|
|
return os.WriteFile(filename, content, 0644)
|
|
}
|
|
|
|
func Write(filename string, content string) error {
|
|
return WriteBytes(filename, []byte(content))
|
|
}
|
|
|
|
func Copy(from, to string) error {
|
|
fromStat, err := os.Stat(from)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if fromStat.IsDir() {
|
|
entries, err := os.ReadDir(from)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, entry := range entries {
|
|
err := Copy(filepath.Join(from, entry.Name()), filepath.Join(to, entry.Name()))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
toStat, err := os.Stat(to)
|
|
if err == nil && toStat.IsDir() {
|
|
to = filepath.Join(to, filepath.Base(from))
|
|
}
|
|
EnsureParentDir(to)
|
|
|
|
src, err := os.Open(from)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer src.Close()
|
|
|
|
dst, err := os.OpenFile(to, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer dst.Close()
|
|
|
|
_, err = io.Copy(dst, src)
|
|
return err
|
|
}
|
|
|
|
func CopyToFile(from io.Reader, to string) error {
|
|
EnsureParentDir(to)
|
|
fp, err := os.OpenFile(to, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer fp.Close()
|
|
_, err = io.Copy(fp, from)
|
|
return err
|
|
}
|
|
|
|
func Remove(path string) error {
|
|
return os.RemoveAll(path)
|
|
}
|
|
|
|
func Move(src, dst string) error {
|
|
EnsureParentDir(dst)
|
|
return os.Rename(src, dst)
|
|
}
|
|
|
|
func Replace(filename, old, new string) error {
|
|
content, err := Read(filename)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
newContent := strings.ReplaceAll(content, old, new)
|
|
return Write(filename, newContent)
|
|
}
|
|
|
|
func Search(dir, pattern string) []string {
|
|
var matches []string
|
|
_ = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
if !info.IsDir() {
|
|
matched, _ := filepath.Match(pattern, filepath.Base(path))
|
|
if matched {
|
|
matches = append(matches, path)
|
|
}
|
|
}
|
|
return nil
|
|
})
|
|
return matches
|
|
}
|
|
|
|
func ReadDir(filename string) ([]FileInfo, error) {
|
|
var out []FileInfo
|
|
if mfList := ReadDirFromMemory(filename); mfList != nil {
|
|
for _, f := range mfList {
|
|
out = append(out, FileInfo{
|
|
Name: filepath.Base(f.Name),
|
|
FullName: f.Name,
|
|
IsDir: f.IsDir,
|
|
Size: f.Size,
|
|
ModTime: f.ModTime.Unix(),
|
|
})
|
|
}
|
|
return out, nil
|
|
}
|
|
|
|
files, err := os.ReadDir(filename)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, f := range files {
|
|
info, _ := f.Info()
|
|
if info != nil {
|
|
out = append(out, FileInfo{
|
|
Name: f.Name(),
|
|
FullName: filepath.Join(filename, f.Name()),
|
|
IsDir: info.IsDir(),
|
|
Size: info.Size(),
|
|
ModTime: info.ModTime().Unix(),
|
|
})
|
|
}
|
|
}
|
|
return out, nil
|
|
}
|
|
|
|
func MustReadDir(filename string) []FileInfo {
|
|
files, _ := ReadDir(filename)
|
|
return files
|
|
}
|
|
|
|
func RunCommand(command string, args ...string) ([]string, error) {
|
|
cmd := exec.Command(command, args...)
|
|
out, err := cmd.CombinedOutput()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
lines := strings.Split(strings.TrimSpace(string(out)), "\n")
|
|
return lines, nil
|
|
}
|