Skip to content

Commit 4f45e40

Browse files
author
simuleite
committed
Get Mono Current Repo
1 parent 7291598 commit 4f45e40

2 files changed

Lines changed: 64 additions & 49 deletions

File tree

internal/cmd/cli/list_repos.go

Lines changed: 61 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"fmt"
2020
"os"
2121
"path/filepath"
22+
"sort"
2223
"strings"
2324

2425
"github.com/bytedance/sonic"
@@ -32,7 +33,7 @@ func newListReposCmd() *cobra.Command {
3233
Short: "List available repositories",
3334
Long: `List all available repositories in the AST directory.
3435
35-
The repositories are loaded from .repo_index.json or *.json files in the --asts-dir directory.`,
36+
The repositories are loaded from *.json files in the --asts-dir directory.`,
3637
Example: `abcoder cli list-repos`,
3738
RunE: func(cmd *cobra.Command, args []string) error {
3839
astsDir, err := getASTsDir(cmd)
@@ -45,77 +46,89 @@ The repositories are loaded from .repo_index.json or *.json files in the --asts-
4546
if err != nil {
4647
return err
4748
}
48-
49-
// 尝试从 .repo_index.json 读取映射
50-
indexFile := filepath.Join(astsDir, ".repo_index.json")
51-
var repoNames []string
52-
var currentRepo string
53-
54-
if data, err := os.ReadFile(indexFile); err == nil {
55-
// 用 sonic 解析 mappings
56-
mappingsVal, err := sonic.Get(data, "mappings")
57-
if err == nil {
58-
mappings, err := mappingsVal.Map()
59-
if err == nil {
60-
for name, v := range mappings {
61-
repoNames = append(repoNames, name)
62-
// 检查当前目录是否匹配 (mappings value 是文件名,需要检查对应的 json 文件)
63-
if pathMatchesCwd(astsDir, v.(string), cwd) {
64-
currentRepo = name
65-
}
66-
}
67-
}
68-
}
49+
if verbose {
50+
fmt.Fprintf(os.Stderr, "[VERBOSE] cwd: %s\n", cwd)
6951
}
7052

71-
// 扫描 JSON 文件,使用 sonic 快速读取
53+
// 扫描所有 JSON 文件,读取 id 和 path
7254
repoNamesMap := make(map[string]struct{})
55+
var currentRepos []string
56+
type pathItem struct {
57+
id string
58+
path string
59+
}
60+
var pathItems []pathItem
61+
7362
files, err := filepath.Glob(filepath.Join(astsDir, "*.json"))
7463
if err != nil {
7564
return err
7665
}
66+
if verbose {
67+
fmt.Fprintf(os.Stderr, "[VERBOSE] found %d json files\n", len(files))
68+
}
7769
for _, f := range files {
7870
// 跳过 _repo_index.json
7971
if strings.HasSuffix(f, "_repo_index.json") || strings.HasSuffix(f, ".repo_index.json") {
8072
continue
8173
}
82-
// 使用 sonic 快速读取 id 字段,避免加载整个 JSON
74+
// 使用 sonic 快速读取 id 和 path 字段
8375
if data, err := os.ReadFile(f); err == nil {
84-
val, err := sonic.Get(data, "id")
76+
// 读取 id
77+
idVal, err := sonic.Get(data, "id")
78+
if err != nil {
79+
continue
80+
}
81+
id, err := idVal.String()
82+
if err != nil || id == "" {
83+
continue
84+
}
85+
repoNamesMap[id] = struct{}{}
86+
87+
// 读取 path
88+
pathVal, err := sonic.Get(data, "Path")
8589
if err == nil {
86-
id, err := val.String()
87-
if err == nil && id != "" {
88-
repoNamesMap[id] = struct{}{}
90+
path, err := pathVal.String()
91+
if err == nil && path != "" {
92+
pathItems = append(pathItems, pathItem{id: id, path: path})
8993
}
9094
}
91-
// 尝试读取 Path 字段,检查是否匹配当前目录
92-
if currentRepo == "" {
93-
val, err := sonic.Get(data, "Path")
94-
if err == nil {
95-
path, err := val.String()
96-
if err == nil && path == cwd {
97-
// 从 id 字段获取名称
98-
val, err := sonic.Get(data, "id")
99-
if err == nil {
100-
id, err := val.String()
101-
if err == nil && id != "" {
102-
currentRepo = id
103-
}
104-
}
105-
}
106-
}
95+
}
96+
}
97+
98+
// 按 path 排序,用于前缀匹配时提前退出
99+
sort.Slice(pathItems, func(i, j int) bool {
100+
return pathItems[i].path < pathItems[j].path
101+
})
102+
103+
// 查找 cwd 前缀匹配的 repo
104+
for _, item := range pathItems {
105+
if verbose {
106+
fmt.Fprintf(os.Stderr, "[VERBOSE] checking: id=%s, path=%s\n", item.id, item.path)
107+
}
108+
// 如果 path 比 cwd 短,不可能匹配,提前退出
109+
if len(item.path) < len(cwd) {
110+
if verbose {
111+
fmt.Fprintf(os.Stderr, "[VERBOSE] early exit: path shorter than cwd\n")
112+
}
113+
continue
114+
}
115+
if strings.HasPrefix(item.path, cwd) {
116+
currentRepos = append(currentRepos, item.id)
117+
if verbose {
118+
fmt.Fprintf(os.Stderr, "[VERBOSE] MATCH: id=%s, path=%s\n", item.id, item.path)
107119
}
108120
}
109121
}
110-
repoNames = maps.Keys(repoNamesMap)
122+
123+
repoNames := maps.Keys(repoNamesMap)
111124

112125
type ListReposOutput struct {
113126
RepoNames []string `json:"repo_names"`
114-
CurrentRepo string `json:"current_repo,omitempty"`
127+
CurrentRepos []string `json:"current_repos,omitempty"`
115128
}
116129
resp := ListReposOutput{
117-
RepoNames: repoNames,
118-
CurrentRepo: currentRepo,
130+
RepoNames: repoNames,
131+
CurrentRepos: currentRepos,
119132
}
120133
b, _ := json.MarshalIndent(resp, "", " ")
121134
fmt.Fprintf(os.Stdout, "%s\n", b)

internal/cmd/cli/utils.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ func loadRepoModules(repoFile string) (map[string]interface{}, error) {
102102
}
103103

104104
// pathMatchesCwd 检查 mappings 中的文件名对应的 json 文件的 Path 字段是否匹配 cwd
105+
// 支持前缀匹配:cwd 以 path 开头(支持 monorepo 场景)
105106
func pathMatchesCwd(astsDir, filename, cwd string) bool {
106107
repoFile := filepath.Join(astsDir, filename)
107108
data, err := os.ReadFile(repoFile)
@@ -116,7 +117,8 @@ func pathMatchesCwd(astsDir, filename, cwd string) bool {
116117
if err != nil {
117118
return false
118119
}
119-
return path == cwd
120+
// 前缀匹配:cwd 以 path 开头
121+
return strings.HasPrefix(cwd, path)
120122
}
121123

122124
// loadRepoFileData 读取整个 repo JSON 文件,返回 raw data 供后续 sonic.Get 按需读取

0 commit comments

Comments
 (0)