83 lines
1.8 KiB
Go
83 lines
1.8 KiB
Go
package builtin
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io/fs"
|
|
"os"
|
|
"sort"
|
|
|
|
"github.com/bmatcuk/doublestar/v4"
|
|
|
|
"nub/internal/tool"
|
|
)
|
|
|
|
type GlobTool struct{}
|
|
|
|
func (GlobTool) Name() string { return "glob" }
|
|
func (GlobTool) Description() string {
|
|
return "Findet Dateien per Glob-Pattern, .gitignore respektiert, nach mtime absteigend sortiert."
|
|
}
|
|
|
|
func (GlobTool) Schema() json.RawMessage {
|
|
return json.RawMessage(`{
|
|
"type": "object",
|
|
"properties": {
|
|
"pattern": {"type": "string", "description": "doublestar-Pattern, z.B. **/*.go"}
|
|
},
|
|
"required": ["pattern"]
|
|
}`)
|
|
}
|
|
|
|
type globInput struct {
|
|
Pattern string `json:"pattern"`
|
|
}
|
|
|
|
func (GlobTool) Run(ctx context.Context, input json.RawMessage, env tool.Env) (tool.Result, error) {
|
|
var in globInput
|
|
if err := json.Unmarshal(input, &in); err != nil {
|
|
return tool.Result{ForModel: "invalid input: " + err.Error(), IsError: true}, nil
|
|
}
|
|
|
|
ignore := loadGitignore(env.RepoRoot)
|
|
|
|
type match struct {
|
|
path string
|
|
mtime int64
|
|
}
|
|
var matches []match
|
|
|
|
err := doublestar.GlobWalk(os.DirFS(env.RepoRoot), in.Pattern, func(path string, d fs.DirEntry) error {
|
|
if d.IsDir() || ignore.match(path) {
|
|
return nil
|
|
}
|
|
info, err := d.Info()
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
matches = append(matches, match{path: path, mtime: info.ModTime().Unix()})
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
return tool.Result{ForModel: fmt.Sprintf("glob %s: %v", in.Pattern, err), IsError: true}, nil
|
|
}
|
|
|
|
sort.Slice(matches, func(i, j int) bool { return matches[i].mtime > matches[j].mtime })
|
|
|
|
paths := make([]string, len(matches))
|
|
out := ""
|
|
for i, m := range matches {
|
|
paths[i] = m.path
|
|
out += m.path + "\n"
|
|
}
|
|
if len(matches) == 0 {
|
|
out = fmt.Sprintf("no matches for %s", in.Pattern)
|
|
}
|
|
|
|
return tool.Result{ForModel: out, ForUI: GlobResult{Paths: paths}}, nil
|
|
}
|
|
|
|
type GlobResult struct {
|
|
Paths []string
|
|
}
|