@@ -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 )
0 commit comments