mirror of
https://github.com/danielmiessler/Fabric.git
synced 2026-01-10 06:48:04 -05:00
## CHANGES - Add prompt strategies like Chain of Thought (CoT) - Implement strategy selection with `--strategy` flag - Improve README with platform-specific installation instructions - Fix web interface documentation link - Refactor git operations with new githelper package - Add `--liststrategies` command to view available strategies - Support applying strategies to system prompts - Fix YouTube configuration check - Improve error handling in session management
112 lines
2.7 KiB
Go
112 lines
2.7 KiB
Go
package githelper
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/go-git/go-git/v5"
|
|
"github.com/go-git/go-git/v5/plumbing/object"
|
|
"github.com/go-git/go-git/v5/storage/memory"
|
|
)
|
|
|
|
// FetchOptions defines options for fetching files from a git repo
|
|
type FetchOptions struct {
|
|
// RepoURL is the URL of the git repository
|
|
RepoURL string
|
|
|
|
// PathPrefix is the folder within the repo to extract (e.g. "patterns/")
|
|
PathPrefix string
|
|
|
|
// DestDir is where the files will be saved locally
|
|
DestDir string
|
|
|
|
// SingleDirectory if true, only fetch files directly in the specified directory
|
|
// without recursing into subdirectories
|
|
SingleDirectory bool
|
|
}
|
|
|
|
// FetchFilesFromRepo clones a git repo and extracts files from a specific folder
|
|
func FetchFilesFromRepo(opts FetchOptions) error {
|
|
// Ensure path prefix ends with slash
|
|
if !strings.HasSuffix(opts.PathPrefix, "/") {
|
|
opts.PathPrefix = opts.PathPrefix + "/"
|
|
}
|
|
|
|
// Clone the repository in memory
|
|
r, err := git.Clone(memory.NewStorage(), nil, &git.CloneOptions{
|
|
URL: opts.RepoURL,
|
|
Depth: 1,
|
|
})
|
|
if err != nil {
|
|
return fmt.Errorf("failed to clone repository: %w", err)
|
|
}
|
|
|
|
// Get HEAD reference
|
|
ref, err := r.Head()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get repository HEAD: %w", err)
|
|
}
|
|
|
|
// Get commit object
|
|
commit, err := r.CommitObject(ref.Hash())
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get commit: %w", err)
|
|
}
|
|
|
|
// Get the file tree
|
|
tree, err := commit.Tree()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get tree: %w", err)
|
|
}
|
|
|
|
// Ensure destination directory exists
|
|
if err := os.MkdirAll(opts.DestDir, 0755); err != nil {
|
|
return fmt.Errorf("failed to create destination directory: %w", err)
|
|
}
|
|
|
|
// Extract files from the tree
|
|
return tree.Files().ForEach(func(f *object.File) error {
|
|
// Only process files in the specified path
|
|
if !strings.HasPrefix(f.Name, opts.PathPrefix) {
|
|
return nil
|
|
}
|
|
|
|
// For SingleDirectory mode, skip files in subdirectories
|
|
if opts.SingleDirectory {
|
|
remainingPath := strings.TrimPrefix(f.Name, opts.PathPrefix)
|
|
if strings.Contains(remainingPath, "/") {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// Create local path for the file, removing the prefix
|
|
relativePath := strings.TrimPrefix(f.Name, opts.PathPrefix)
|
|
localPath := filepath.Join(opts.DestDir, relativePath)
|
|
|
|
// Ensure directory structure exists
|
|
if err := os.MkdirAll(filepath.Dir(localPath), 0755); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Get file contents
|
|
reader, err := f.Reader()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer reader.Close()
|
|
|
|
// Create and write to local file
|
|
file, err := os.Create(localPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer file.Close()
|
|
|
|
_, err = io.Copy(file, reader)
|
|
return err
|
|
})
|
|
}
|