Files
1Panel/agent/utils/files/ai_inventory.go

99 lines
2.0 KiB
Go

package files
import (
"errors"
"io/fs"
"os"
"path/filepath"
"github.com/1Panel-dev/1Panel/agent/constant"
)
const DefaultFileAIMaxItems = 500
type AISearchInventoryItem struct {
RelPath string `json:"relPath"`
IsDir bool `json:"isDir"`
Size int64 `json:"size"`
ModTime string `json:"modTime"`
}
func CollectDirInventory(root string, containSub bool, maxItems int) (items []AISearchInventoryItem, truncated bool, err error) {
if maxItems <= 0 {
maxItems = DefaultFileAIMaxItems
}
root = filepath.Clean(root)
st, err := os.Stat(root)
if err != nil {
return nil, false, err
}
if !st.IsDir() {
return nil, false, errors.New("path is not a directory")
}
items = make([]AISearchInventoryItem, 0, maxItems)
if !containSub {
entries, err := os.ReadDir(root)
if err != nil {
return nil, false, err
}
for _, e := range entries {
full := filepath.Join(root, e.Name())
if ShouldFilterSensitivePath(full) {
continue
}
if len(items) >= maxItems {
truncated = true
break
}
info, err := e.Info()
if err != nil {
continue
}
items = append(items, AISearchInventoryItem{
RelPath: filepath.ToSlash(e.Name()),
IsDir: e.IsDir(),
Size: info.Size(),
ModTime: info.ModTime().Format(constant.DateTimeLayout),
})
}
return items, truncated, nil
}
err = filepath.WalkDir(root, func(path string, d fs.DirEntry, walkErr error) error {
if walkErr != nil {
return nil
}
if ShouldFilterSensitivePath(path) {
if d.IsDir() {
return filepath.SkipDir
}
return nil
}
rel, err := filepath.Rel(root, path)
if err != nil || rel == "." {
return nil
}
if len(items) >= maxItems {
truncated = true
return filepath.SkipAll
}
info, err := d.Info()
if err != nil {
return nil
}
items = append(items, AISearchInventoryItem{
RelPath: filepath.ToSlash(rel),
IsDir: d.IsDir(),
Size: info.Size(),
ModTime: info.ModTime().Format(constant.DateTimeLayout),
})
return nil
})
if err != nil {
return nil, false, err
}
return items, truncated, nil
}