Skip to content

Commit 57d4885

Browse files
committed
refactor: query instead of tx
1 parent f57d31f commit 57d4885

File tree

3 files changed

+164
-34
lines changed

3 files changed

+164
-34
lines changed

client/client.go

Lines changed: 105 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -98,45 +98,123 @@ func (c *Client) Run(gnoCode string) error {
9898
}
9999

100100
func (c *Client) RunQuery(realmPath string, expression string) ([]byte, error) {
101-
gnoCode := fmt.Sprintf(`package main
101+
parts := strings.Split(realmPath, "/")
102+
packageAlias := parts[len(parts)-1]
102103

103-
import (
104-
"%s"
105-
)
104+
queryExpression := strings.Replace(expression, packageAlias+".", realmPath+".", 1)
105+
106+
if strings.Contains(expression, ".Repository.Pull(") {
107+
return c.QueryFileInChunks(queryExpression)
108+
}
106109

107-
func main() {
108-
result := %s
109-
content := make([]byte, len(result))
110-
copy(content, result)
111-
println(string(content))
110+
return c.QueryDirectInChunks(queryExpression)
112111
}
113-
`, realmPath, expression)
114112

115-
tmpFile := "/tmp/gnit_query.gno"
116-
if err := os.WriteFile(tmpFile, []byte(gnoCode), 0644); err != nil {
117-
return nil, fmt.Errorf("failed to create temp file: %w", err)
113+
func (c *Client) QueryFileInChunks(expression string) ([]byte, error) {
114+
sizeQuery := strings.Replace(expression, "Repository.Pull(", "Repository.GetFileSize(", 1)
115+
sizeOutput, err := c.QueryEval(sizeQuery)
116+
if err != nil {
117+
return nil, fmt.Errorf("failed to get file size: %w", err)
118118
}
119-
defer os.Remove(tmpFile)
120119

121-
cmd := exec.Command("gnokey", "maketx", "run",
122-
"-gas-fee", c.config.GasFee,
123-
"-gas-wanted", c.config.GasWanted,
124-
"-broadcast",
125-
"-chainid", c.config.ChainID,
126-
"-remote", c.config.Remote,
127-
c.config.Account,
128-
tmpFile)
120+
sizeOutput = strings.TrimPrefix(sizeOutput, "data: ")
121+
var size int
122+
if _, err := fmt.Sscanf(sizeOutput, "(%d int)", &size); err != nil {
123+
return nil, fmt.Errorf("failed to parse file size: %w", err)
124+
}
129125

130-
cmd.Stdin = os.Stdin
131-
cmd.Stderr = os.Stderr
126+
if size < 0 {
127+
return nil, fmt.Errorf("file not found")
128+
}
129+
130+
if size == 0 {
131+
return []byte{}, nil
132+
}
133+
134+
var content []byte
135+
chunkSize := 200
136+
for offset := 0; offset < size; offset += chunkSize {
137+
chunkQuery := strings.Replace(expression, "Repository.Pull(", "Repository.GetFileChunk(", 1)
138+
chunkQuery = strings.Replace(chunkQuery, ")", fmt.Sprintf(", %d, %d)", offset, chunkSize), 1)
139+
140+
chunkOutput, err := c.QueryEval(chunkQuery)
141+
if err != nil {
142+
return nil, fmt.Errorf("failed to get chunk at offset %d: %w", offset, err)
143+
}
144+
145+
chunk := extractStringFromQuery(chunkOutput)
146+
content = append(content, []byte(chunk)...)
147+
}
148+
149+
return content, nil
150+
}
151+
152+
func (c *Client) QueryEval(expression string) (string, error) {
153+
cmd := exec.Command("gnokey", "query", "vm/qeval",
154+
"-data", expression,
155+
"-remote", c.config.Remote)
132156

133157
output, err := cmd.Output()
134158
if err != nil {
135-
return nil, fmt.Errorf("run query failed: %w", err)
159+
return "", fmt.Errorf("query failed: %w", err)
160+
}
161+
162+
return extractDataLine(string(output))
163+
}
164+
165+
func extractStringFromQuery(output string) string {
166+
output = strings.TrimPrefix(output, "data: ")
167+
168+
startIdx := strings.Index(output, `("`)
169+
if startIdx == -1 {
170+
return ""
171+
}
172+
startIdx += 2
173+
174+
endIdx := strings.LastIndex(output, `" string)`)
175+
if endIdx == -1 {
176+
return ""
177+
}
178+
179+
content := output[startIdx:endIdx]
180+
181+
var result strings.Builder
182+
for i := 0; i < len(content); i++ {
183+
if content[i] == '\\' && i+1 < len(content) {
184+
switch content[i+1] {
185+
case 'n':
186+
result.WriteByte('\n')
187+
i++
188+
case 't':
189+
result.WriteByte('\t')
190+
i++
191+
case 'r':
192+
result.WriteByte('\r')
193+
i++
194+
case '\\':
195+
result.WriteByte('\\')
196+
i++
197+
case '"':
198+
result.WriteByte('"')
199+
i++
200+
default:
201+
result.WriteByte(content[i])
202+
}
203+
} else {
204+
result.WriteByte(content[i])
205+
}
206+
}
207+
208+
return result.String()
209+
}
210+
211+
func (c *Client) QueryDirectInChunks(expression string) ([]byte, error) {
212+
output, err := c.QueryEval(expression)
213+
if err != nil {
214+
return nil, err
136215
}
137216

138-
content := extractTransactionOutput(string(output))
139-
return []byte(content), nil
217+
return []byte(output), nil
140218
}
141219

142220
func extractTransactionOutput(output string) string {

client/cmd/gnit/pull.go

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,28 +58,38 @@ func (p *Pull) ExecuteAll() error {
5858
fmt.Println("Pulling all files from repository...")
5959

6060
packageAlias := config.PackageAlias(p.config.RealmPath)
61-
query := fmt.Sprintf("%s.Repository.SerializePullAll()", packageAlias)
6261

63-
serializedData, err := p.client.RunQuery(p.config.RealmPath, query)
62+
listQuery := fmt.Sprintf("%s.Repository.ListFiles()", packageAlias)
63+
listData, err := p.client.RunQuery(p.config.RealmPath, listQuery)
6464
if err != nil {
6565
if p.sourceMode {
6666
fmt.Println("Repository not found or empty, trying to pull realm source files...")
6767
return p.pullRealmSource()
6868
}
69-
return fmt.Errorf("failed to pull files: %w", err)
69+
return fmt.Errorf("failed to list files: %w", err)
7070
}
7171

72-
if len(serializedData) == 0 {
72+
filenames, err := parseFileList(string(listData))
73+
if err != nil {
74+
return fmt.Errorf("failed to parse file list: %w", err)
75+
}
76+
77+
if len(filenames) == 0 {
7378
fmt.Println("No files found in repository")
7479
if p.sourceMode {
7580
return p.pullRealmSource()
7681
}
7782
return nil
7883
}
7984

80-
files, err := parseSerializedFiles(string(serializedData))
81-
if err != nil {
82-
return fmt.Errorf("failed to parse files: %w", err)
85+
files := make(map[string][]byte)
86+
for _, filename := range filenames {
87+
pullQuery := fmt.Sprintf("%s.Repository.Pull(\"%s\")", packageAlias, filename)
88+
content, err := p.client.RunQuery(p.config.RealmPath, pullQuery)
89+
if err != nil {
90+
return fmt.Errorf("failed to pull file %s: %w", filename, err)
91+
}
92+
files[filename] = content
8393
}
8494

8595
if len(files) == 0 {

realms/src/api.gno

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,3 +208,45 @@ func escapeString(s string) string {
208208
}
209209
return result
210210
}
211+
212+
func (r *Repository) Render(path string) string {
213+
if path == "" {
214+
files := r.ListFiles()
215+
result := "# Repository Files\n\n"
216+
for i := 0; i < len(files); i++ {
217+
result += "- " + files[i] + "\n"
218+
}
219+
return result
220+
}
221+
222+
content := r.Pull(path)
223+
if content == nil {
224+
return "File not found: " + path
225+
}
226+
return string(content)
227+
}
228+
229+
func (r *Repository) GetFileChunk(filename string, offset, size int) string {
230+
content := r.Pull(filename)
231+
if content == nil {
232+
return ""
233+
}
234+
235+
end := offset + size
236+
if end > len(content) {
237+
end = len(content)
238+
}
239+
if offset >= len(content) {
240+
return ""
241+
}
242+
243+
return string(content[offset:end])
244+
}
245+
246+
func (r *Repository) GetFileSize(filename string) int {
247+
content := r.Pull(filename)
248+
if content == nil {
249+
return -1
250+
}
251+
return len(content)
252+
}

0 commit comments

Comments
 (0)