Skip to content

Commit b3dc66f

Browse files
committed
refactor(cmd): pull all files
1 parent 7b4b786 commit b3dc66f

File tree

6 files changed

+154
-17
lines changed

6 files changed

+154
-17
lines changed

cmd/commands/pull.go

Lines changed: 96 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package commands
22

33
import (
44
"fmt"
5+
"strings"
56

67
"gnit/config"
78
"gnit/filesystem"
@@ -29,14 +30,105 @@ func (p *Pull) Execute(filename string) error {
2930
return fmt.Errorf("failed to query file: %w", err)
3031
}
3132

32-
if len(content) == 0 {
33-
return fmt.Errorf("file '%s' not found or empty", filename)
34-
}
35-
3633
if err := filesystem.WriteFile(filename, content); err != nil {
3734
return err
3835
}
3936

4037
fmt.Printf("File '%s' fetched successfully (%d bytes)\n", filename, len(content))
4138
return nil
4239
}
40+
41+
func (p *Pull) ExecuteAll() error {
42+
fmt.Println("Fetching list of files...")
43+
44+
query := fmt.Sprintf("%s.Repo.ListFiles()", p.config.RealmPath)
45+
result, err := p.client.QueryRaw(query)
46+
if err != nil {
47+
return fmt.Errorf("failed to list files: %w", err)
48+
}
49+
50+
if len(result) == 0 {
51+
fmt.Println("No files found in repository")
52+
return nil
53+
}
54+
55+
files, err := parseFileList(result)
56+
if err != nil {
57+
return fmt.Errorf("failed to parse file list: %w", err)
58+
}
59+
60+
if len(files) == 0 {
61+
fmt.Println("No files found in repository")
62+
return nil
63+
}
64+
65+
fmt.Printf("Found %d file(s), pulling all...\n", len(files))
66+
67+
for _, filename := range files {
68+
if err := p.Execute(filename); err != nil {
69+
return fmt.Errorf("failed to pull '%s': %w", filename, err)
70+
}
71+
}
72+
73+
fmt.Printf("\nSuccessfully pulled %d file(s)\n", len(files))
74+
return nil
75+
}
76+
77+
func parseFileList(data string) ([]string, error) {
78+
str := strings.TrimSpace(data)
79+
80+
str = strings.TrimPrefix(str, "data: ")
81+
82+
sliceStart := strings.Index(str, "slice[")
83+
if sliceStart == -1 {
84+
return []string{}, fmt.Errorf("invalid format: missing 'slice['")
85+
}
86+
87+
sliceStart += len("slice[")
88+
sliceEnd := strings.LastIndex(str, "]")
89+
if sliceEnd == -1 || sliceEnd <= sliceStart {
90+
return []string{}, fmt.Errorf("invalid format: missing closing ']'")
91+
}
92+
93+
content := str[sliceStart:sliceEnd]
94+
if strings.TrimSpace(content) == "" {
95+
return []string{}, nil
96+
}
97+
98+
var files []string
99+
var currentFile strings.Builder
100+
inQuotes := false
101+
escaped := false
102+
103+
for i := 0; i < len(content); i++ {
104+
ch := content[i]
105+
106+
if escaped {
107+
currentFile.WriteByte(ch)
108+
escaped = false
109+
continue
110+
}
111+
112+
if ch == '\\' {
113+
escaped = true
114+
continue
115+
}
116+
117+
if ch == '"' {
118+
if inQuotes {
119+
files = append(files, currentFile.String())
120+
currentFile.Reset()
121+
inQuotes = false
122+
} else {
123+
inQuotes = true
124+
}
125+
continue
126+
}
127+
128+
if inQuotes {
129+
currentFile.WriteByte(ch)
130+
}
131+
}
132+
133+
return files, nil
134+
}

cmd/filesystem/filesystem.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,23 +22,19 @@ func CollectFiles() (map[string][]byte, error) {
2222
return err
2323
}
2424

25-
// Skip directories
2625
if info.IsDir() {
2726
return nil
2827
}
2928

30-
// Normalize path
3129
cleanPath := filepath.Clean(path)
3230
if strings.HasPrefix(cleanPath, "./") {
3331
cleanPath = cleanPath[2:]
3432
}
3533

36-
// Check if file should be ignored
3734
if matcher.Match(cleanPath) {
3835
return nil
3936
}
4037

41-
// Read file content
4238
content, readErr := os.ReadFile(path)
4339
if readErr != nil {
4440
fmt.Printf("Warning: unable to read %s: %v\n", path, readErr)
@@ -57,7 +53,6 @@ func CollectFiles() (map[string][]byte, error) {
5753
}
5854

5955
func WriteFile(path string, content []byte) error {
60-
// Create parent directories if they don't exist
6156
dir := filepath.Dir(path)
6257
if dir != "." && dir != "" {
6358
if err := os.MkdirAll(dir, 0755); err != nil {

cmd/gnokey/client.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,19 @@ func (c *Client) Query(expression string) ([]byte, error) {
3232
return parseHexOutput(string(output))
3333
}
3434

35+
func (c *Client) QueryRaw(expression string) (string, error) {
36+
cmd := exec.Command("gnokey", "query", "vm/qeval",
37+
"-data", expression,
38+
"-remote", c.config.Remote)
39+
40+
output, err := cmd.Output()
41+
if err != nil {
42+
return "", fmt.Errorf("query failed: %w", err)
43+
}
44+
45+
return extractDataLine(string(output))
46+
}
47+
3548
func (c *Client) Run(gnoCode string) error {
3649
tmpFile := "/tmp/gnit_tx.gno"
3750
if err := os.WriteFile(tmpFile, []byte(gnoCode), 0644); err != nil {
@@ -77,6 +90,10 @@ func parseHexOutput(output string) ([]byte, error) {
7790
return []byte{}, nil
7891
}
7992

93+
if strings.Contains(dataLine, "slice[]") {
94+
return []byte{}, nil
95+
}
96+
8097
re := regexp.MustCompile(`slice\[0x([0-9a-fA-F]+)\]`)
8198
matches := re.FindStringSubmatch(dataLine)
8299

@@ -91,3 +108,13 @@ func parseHexOutput(output string) ([]byte, error) {
91108

92109
return data, nil
93110
}
111+
112+
func extractDataLine(output string) (string, error) {
113+
lines := strings.Split(output, "\n")
114+
for _, line := range lines {
115+
if strings.HasPrefix(line, "data: ") {
116+
return line, nil
117+
}
118+
}
119+
return "", fmt.Errorf("data: line not found in output")
120+
}

cmd/ignore/ignore.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ func NewMatcher(root string) (*Matcher, error) {
4343
}
4444

4545
func (m *Matcher) Match(path string) bool {
46-
// Only ignore .git directory, not files starting with .git
4746
if strings.Contains(path, ".git/") || path == ".git" {
4847
return true
4948
}

cmd/main.go

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,17 @@ func main() {
3737
}
3838

3939
func handlePull(client *gnokey.Client, cfg *config.Config) {
40+
cmd := commands.NewPull(client, cfg)
41+
4042
if len(os.Args) < 3 {
41-
fmt.Println("Error: filename required for pull")
42-
fmt.Println("Usage: gnit pull <file>")
43-
os.Exit(1)
43+
if err := cmd.ExecuteAll(); err != nil {
44+
fmt.Printf("Error: %v\n", err)
45+
os.Exit(1)
46+
}
47+
return
4448
}
4549

4650
filename := os.Args[2]
47-
cmd := commands.NewPull(client, cfg)
48-
4951
if err := cmd.Execute(filename); err != nil {
5052
fmt.Printf("Error: %v\n", err)
5153
os.Exit(1)
@@ -74,11 +76,12 @@ func printUsage() {
7476
fmt.Println("Usage: gnit <command> [options]")
7577
fmt.Println()
7678
fmt.Println("Available commands:")
77-
fmt.Println(" pull <file> Fetch a file from the repository")
79+
fmt.Println(" pull [file] Fetch file(s) from the repository (all files if no file specified)")
7880
fmt.Println(" commit <message> Commit changes with a message")
7981
fmt.Println(" help Display this help")
8082
fmt.Println()
8183
fmt.Println("Examples:")
82-
fmt.Println(" gnit pull example.gno")
84+
fmt.Println(" gnit pull # Pull all files")
85+
fmt.Println(" gnit pull example.gno # Pull specific file")
8386
fmt.Println(" gnit commit \"My commit message\"")
8487
}

realms/src/api.gno

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,3 +117,24 @@ func (r *Repository) GetHeadCommit() *Commit {
117117
func (r *Repository) GetCurrentBranch() string {
118118
return r.head
119119
}
120+
121+
func (r *Repository) ListFiles() []string {
122+
headCommit := r.GetHeadCommit()
123+
if headCommit == nil {
124+
return []string{}
125+
}
126+
127+
treeValue, exists := r.objects.Get(headCommit.Tree)
128+
if !exists {
129+
return []string{}
130+
}
131+
132+
tree := treeValue.(map[string]string)
133+
files := make([]string, 0, len(tree))
134+
135+
for path := range tree {
136+
files = append(files, path)
137+
}
138+
139+
return files
140+
}

0 commit comments

Comments
 (0)