mirror of
https://github.com/lordmathis/lemma.git
synced 2025-11-06 07:54:22 +00:00
141 lines
3.3 KiB
Go
141 lines
3.3 KiB
Go
package filesystem
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"novamd/internal/models"
|
|
)
|
|
|
|
// FileNode represents a file or directory in the file system
|
|
type FileNode struct {
|
|
ID string `json:"id"`
|
|
Name string `json:"name"`
|
|
Path string `json:"path"`
|
|
Children []FileNode `json:"children,omitempty"`
|
|
}
|
|
|
|
// ValidatePath ensures the given path is within the workspace
|
|
func ValidatePath(workspace *models.Workspace, path string) (string, error) {
|
|
workspacePath := GetWorkspacePath(workspace)
|
|
fullPath := filepath.Join(workspacePath, path)
|
|
cleanPath := filepath.Clean(fullPath)
|
|
|
|
if !strings.HasPrefix(cleanPath, workspacePath) {
|
|
return "", fmt.Errorf("invalid path: outside of workspace")
|
|
}
|
|
|
|
return cleanPath, nil
|
|
}
|
|
|
|
// ListFilesRecursively returns a list of all files in the workspace
|
|
func ListFilesRecursively(workspace *models.Workspace) ([]FileNode, error) {
|
|
workspacePath := GetWorkspacePath(workspace)
|
|
return walkDirectory(workspacePath, "")
|
|
}
|
|
|
|
func walkDirectory(dir, prefix string) ([]FileNode, error) {
|
|
entries, err := os.ReadDir(dir)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var nodes []FileNode
|
|
for _, entry := range entries {
|
|
name := entry.Name()
|
|
path := filepath.Join(prefix, name)
|
|
fullPath := filepath.Join(dir, name)
|
|
|
|
node := FileNode{
|
|
ID: path,
|
|
Name: name,
|
|
Path: path,
|
|
}
|
|
|
|
if entry.IsDir() {
|
|
children, err := walkDirectory(fullPath, path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
node.Children = children
|
|
}
|
|
|
|
nodes = append(nodes, node)
|
|
}
|
|
|
|
return nodes, nil
|
|
}
|
|
|
|
// FindFileByName searches for a file in the workspace by name
|
|
func FindFileByName(workspace *models.Workspace, filename string) ([]string, error) {
|
|
var foundPaths []string
|
|
workspacePath := GetWorkspacePath(workspace)
|
|
|
|
err := filepath.Walk(workspacePath, func(path string, info os.FileInfo, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !info.IsDir() {
|
|
relPath, err := filepath.Rel(workspacePath, path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if strings.EqualFold(info.Name(), filename) {
|
|
foundPaths = append(foundPaths, relPath)
|
|
}
|
|
}
|
|
return nil
|
|
})
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if len(foundPaths) == 0 {
|
|
return nil, errors.New("file not found")
|
|
}
|
|
|
|
return foundPaths, nil
|
|
}
|
|
|
|
// GetFileContent retrieves the content of a file in the workspace
|
|
func GetFileContent(workspace *models.Workspace, filePath string) ([]byte, error) {
|
|
fullPath, err := ValidatePath(workspace, filePath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return os.ReadFile(fullPath)
|
|
}
|
|
|
|
// SaveFile saves content to a file in the workspace
|
|
func SaveFile(workspace *models.Workspace, filePath string, content []byte) error {
|
|
fullPath, err := ValidatePath(workspace, filePath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
dir := filepath.Dir(fullPath)
|
|
if err := os.MkdirAll(dir, 0755); err != nil {
|
|
return err
|
|
}
|
|
|
|
return os.WriteFile(fullPath, content, 0644)
|
|
}
|
|
|
|
// DeleteFile removes a file from the workspace
|
|
func DeleteFile(workspace *models.Workspace, filePath string) error {
|
|
fullPath, err := ValidatePath(workspace, filePath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return os.Remove(fullPath)
|
|
}
|
|
|
|
// CreateWorkspaceDirectory creates the directory for a new workspace
|
|
func CreateWorkspaceDirectory(workspace *models.Workspace) error {
|
|
dir := GetWorkspacePath(workspace)
|
|
return os.MkdirAll(dir, 0755)
|
|
} |