package main // hq as the knowledge base reads it: through the records module over the bus (to-be 55 ยง1: "it holds no // checkout of this repository; the import reads it through the records module, as the issue tracker's import // does"), or a checkout on disk for the terminal's dry run and the tests. import ( "encoding/json" "fmt" "os" "path/filepath" "strings" stdio "git.novox.be/novox/mesh-sdk/go" ) // Records is hq as the records module serves it: where its checkout stands, what a folder holds, and one // document whole with the commit it was read at. type Records interface { Standing() (string, error) List(folder string) (folders, documents []string, err error) Read(path string) (content, commit string, err error) } // busRecords is Records over the bus: the records module's tools, called as this module. type busRecords struct{} func (busRecords) Standing() (string, error) { raw, err := stdio.Ask("records.records_status", map[string]any{}) if err != nil { return "", err } var s struct { Commit string `json:"commit"` LastError string `json:"lastError"` } if err := json.Unmarshal(raw, &s); err != nil { return "", fmt.Errorf("records_status answered something else: %v", err) } if s.Commit == "" { return "", fmt.Errorf("the record's checkout stands at no commit yet (%s)", s.LastError) } return s.Commit, nil } func (busRecords) List(folder string) ([]string, []string, error) { raw, err := stdio.Ask("records.records_list", map[string]any{"folder": folder}) if err != nil { return nil, nil, err } var f struct { Folders []string `json:"folders"` Documents []string `json:"documents"` } if err := json.Unmarshal(raw, &f); err != nil { return nil, nil, fmt.Errorf("records_list answered something else: %v", err) } return f.Folders, f.Documents, nil } func (busRecords) Read(path string) (string, string, error) { raw, err := stdio.Ask("records.records_read", map[string]any{"path": path}) if err != nil { return "", "", err } var d struct { Content string `json:"content"` Commit string `json:"commit"` Truncated bool `json:"truncated"` } if err := json.Unmarshal(raw, &d); err != nil { return "", "", fmt.Errorf("records_read answered something else: %v", err) } if d.Truncated { return "", "", fmt.Errorf("%s is longer than the records module answers whole", path) } return d.Content, d.Commit, nil } // dirRecords is Records over a checkout on disk. Its commit is the file COMMIT at its root when there is one (a // fixture copied from hq at a commit), else the checkout's HEAD, else `dir:` and the directory. type dirRecords struct{ dir string } func (d dirRecords) Standing() (string, error) { if st, err := os.Stat(d.dir); err != nil || !st.IsDir() { return "", fmt.Errorf("%s is not a checkout", d.dir) } if raw, err := os.ReadFile(filepath.Join(d.dir, "COMMIT")); err == nil { return strings.TrimSpace(string(raw)), nil } if out, err := os.ReadFile(filepath.Join(d.dir, ".git", "HEAD")); err == nil { ref := strings.TrimSpace(string(out)) if strings.HasPrefix(ref, "ref: ") { if sha, err := os.ReadFile(filepath.Join(d.dir, ".git", strings.TrimPrefix(ref, "ref: "))); err == nil { return strings.TrimSpace(string(sha)), nil } } else if ref != "" { return ref, nil } } return "dir:" + d.dir, nil } func (d dirRecords) List(folder string) ([]string, []string, error) { entries, err := os.ReadDir(filepath.Join(d.dir, filepath.FromSlash(folder))) if err != nil { return nil, nil, err } var folders, docs []string for _, e := range entries { switch { case e.IsDir(): folders = append(folders, e.Name()) case strings.HasSuffix(e.Name(), ".md"): docs = append(docs, e.Name()) } } return folders, docs, nil } func (d dirRecords) Read(path string) (string, string, error) { raw, err := os.ReadFile(filepath.Join(d.dir, filepath.FromSlash(path))) if err != nil { return "", "", err } commit, _ := d.Standing() return string(raw), commit, nil }