Skip to content

Commit 032b93c

Browse files
committed
add update by ssh
1 parent c08a343 commit 032b93c

23 files changed

Lines changed: 776 additions & 157 deletions

.github-task-workflow-diagnosis.md

Lines changed: 0 additions & 126 deletions
This file was deleted.

AGENTS.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ spark git init # 初始化仓库并创建 GitHub 远程
9999
spark git batch-clone # 克隆用户/组织/群组所有仓库 (GitHub + GitLab)
100100
spark git issues # 从 Markdown 文档/任务创建 GitHub Issue
101101
spark git push-all # 提交并推送所有仓库的更改
102+
spark git scan # 扫描 Git 仓库并保存到 SQLite
102103
```
103104

104105
#### `spark git clone`
@@ -300,6 +301,24 @@ spark git push-all -p ~/workspace # 指定目录
300301
- 自动 `git add -A``git commit``git push`
301302
- 遇到冲突时提示并继续处理下一个仓库
302303

304+
#### `spark git scan`
305+
递归扫描目录中的 Git 仓库,可选从 GitHub/GitLab API 获取元数据,并保存到 SQLite 数据库。
306+
307+
```bash
308+
spark git scan # 扫描当前目录
309+
spark git scan ~/workspace # 扫描指定目录
310+
spark git scan . --skip-api # 仅本地扫描
311+
spark git scan . --db ~/.innate/feeds.db # 指定数据库路径
312+
```
313+
314+
| 选项 | 说明 |
315+
|------|------|
316+
| `[folder-path]` | 要扫描的目录(默认当前目录) |
317+
| `-d, --db` | SQLite 数据库路径(默认 `~/.innate/feeds.db`|
318+
| `--skip-api` | 跳过 API 调用,仅扫描本地仓库 |
319+
320+
也可在 `~/.spark.yaml` 中配置 `git.scanner.db` 作为默认数据库路径。设置 `GITHUB_TOKEN` 可提高 GitHub API 速率限制。
321+
303322
### 脚本管理
304323

305324
#### `spark script`
@@ -567,6 +586,8 @@ work-dir: ./workspace
567586
git:
568587
username: your-name # 默认 Git 用户名
569588
email: your@email.com # 默认 Git 邮箱
589+
scanner:
590+
db: ~/.innate/feeds.db # git scan 默认 SQLite 数据库路径
570591
```
571592
572593
## 助手指令参考

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ Spark is a Go CLI tool (`module spark`, binary `spark`) for managing multiple Gi
4444

4545
```
4646
spark
47-
├── git [init|update|submodule [add]|sync|gitcode|config|url|batch-clone|issues|update-org-status]
47+
├── git [init|update|submodule [add]|sync|gitcode|config|url|batch-clone|issues|update-org-status|push-all|scan]
4848
├── task [list|init|dispatch|sync|create|delete|impl]
4949
├── script [list|run]
5050
└── magic [flush-dns|pip|go|node] # Mirror source switching + DNS

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ go test ./internal/git/... -v -run TestFunctionName
8383
| `spark git batch-clone <account> [--ssh] [--include] [--exclude] [-o <dir>]` | Clone all repos from GitHub org/user |
8484
| `spark git update-org-status <org> [--dry-run] [--update-dot-github] [--section <name>]` | Update org README with repo list |
8585
| `spark git issues [-r <owner/repo>] (-d <dir> \| -f <file>) [--dry-run] [-l <labels>]` | Create GitHub issues from markdown docs/tasks |
86+
| `spark git scan [folder-path] [-d <db>] [--skip-api]` | Scan git repos and save to SQLite |
8687

8788
---
8889

cmd/git/git.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ This includes:
2020
- url: Get repository remote URL
2121
- batch-clone: Clone all repos from a GitHub organization or user
2222
- issues: Create GitHub issues from markdown files or tasks
23-
- push-all: Commit and push all changes in repositories`,
23+
- push-all: Commit and push all changes in repositories
24+
- scan: Scan folders for git repositories and save to SQLite`,
2425
}
2526

2627
func init() {

cmd/git/scan.go

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
package git
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"path/filepath"
7+
8+
"spark/internal/git/scanner"
9+
10+
"github.com/spf13/cobra"
11+
"github.com/spf13/viper"
12+
)
13+
14+
var (
15+
scanDBPath string
16+
scanSkipAPI bool
17+
)
18+
19+
var scanCmd = &cobra.Command{
20+
Use: "scan [folder-path]",
21+
Short: "Scan folders for git repositories and save to SQLite",
22+
Long: `Recursively scan a folder for git repositories, optionally fetch metadata
23+
from GitHub/GitLab APIs, and save results to a SQLite database.
24+
25+
The default database path is ~/.innate/feeds.db and can be overridden via
26+
the --db flag or the 'git.scanner.db' config key in ~/.spark.yaml.`,
27+
Args: cobra.MaximumNArgs(1),
28+
RunE: func(cmd *cobra.Command, args []string) error {
29+
folderPath := "."
30+
if len(args) > 0 {
31+
folderPath = args[0]
32+
}
33+
34+
absPath, err := filepath.Abs(folderPath)
35+
if err != nil {
36+
return fmt.Errorf("resolve path: %w", err)
37+
}
38+
39+
dbPath := scanDBPath
40+
if dbPath == "" {
41+
dbPath = viper.GetString("git.scanner.db")
42+
}
43+
if dbPath == "" {
44+
dbPath, err = scanner.DefaultDBPath()
45+
if err != nil {
46+
return fmt.Errorf("resolve default database path: %w", err)
47+
}
48+
} else if len(dbPath) >= 2 && dbPath[0] == '~' && (dbPath[1] == '/' || dbPath[1] == '\\') {
49+
home, err := os.UserHomeDir()
50+
if err != nil {
51+
return fmt.Errorf("resolve home directory: %w", err)
52+
}
53+
dbPath = filepath.Join(home, dbPath[2:])
54+
}
55+
56+
fmt.Printf("Scanning folder: %s\n", absPath)
57+
fmt.Println("Looking for git repositories...")
58+
if !scanSkipAPI {
59+
fmt.Println("Fetching repository information from APIs...")
60+
}
61+
62+
repos, err := scanner.Scan(absPath, scanner.Options{SkipAPI: scanSkipAPI})
63+
if err != nil {
64+
return err
65+
}
66+
67+
if len(repos) == 0 {
68+
fmt.Println("No git repositories found.")
69+
return nil
70+
}
71+
72+
fmt.Printf("\nFound %d repositories\n", len(repos))
73+
74+
store, err := scanner.OpenStore(dbPath)
75+
if err != nil {
76+
return err
77+
}
78+
defer store.Close()
79+
80+
if err := store.SaveRepos(repos); err != nil {
81+
return err
82+
}
83+
84+
fmt.Printf("\nSaved %d repositories to: %s\n", len(repos), dbPath)
85+
printScanSummary(repos)
86+
87+
return nil
88+
},
89+
}
90+
91+
func printScanSummary(repos []scanner.RepoInfo) {
92+
fmt.Println("\nSummary:")
93+
94+
reposByType := make(map[string]int)
95+
for _, repo := range repos {
96+
reposByType[repo.RepoType]++
97+
}
98+
99+
for repoType, count := range reposByType {
100+
fmt.Printf(" - %s: %d repositories\n", repoType, count)
101+
}
102+
103+
totalStars := 0
104+
for _, repo := range repos {
105+
totalStars += repo.Stars
106+
}
107+
if totalStars > 0 {
108+
fmt.Printf(" - Total stars: %d\n", totalStars)
109+
}
110+
}
111+
112+
func init() {
113+
scanCmd.Flags().StringVarP(&scanDBPath, "db", "d", "", "SQLite database path (default: ~/.innate/feeds.db)")
114+
scanCmd.Flags().BoolVar(&scanSkipAPI, "skip-api", false, "Skip API calls, only scan local repos")
115+
116+
viper.SetDefault("git.scanner.db", "")
117+
viper.BindPFlag("git.scanner.db", scanCmd.Flags().Lookup("db"))
118+
119+
GitCmd.AddCommand(scanCmd)
120+
}

cmd/git/update.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import (
88
"github.com/spf13/viper"
99
)
1010

11+
var updateUseSSH bool
12+
1113
var updateCmd = &cobra.Command{
1214
Use: "update",
1315
Short: "Update all git repositories to the latest version",
@@ -44,7 +46,7 @@ var updateCmd = &cobra.Command{
4446

4547
for _, repo := range uniqueRepos {
4648
fmt.Printf("Updating: %s\n", repo)
47-
if err := git.UpdateRepository(repo); err != nil {
49+
if err := git.UpdateRepository(repo, updateUseSSH); err != nil {
4850
fmt.Printf(" Error: %v\n", err)
4951
} else {
5052
fmt.Printf(" Success!\n")
@@ -58,4 +60,6 @@ var updateCmd = &cobra.Command{
5860

5961
func init() {
6062
GitCmd.AddCommand(updateCmd)
63+
64+
updateCmd.Flags().BoolVar(&updateUseSSH, "ssh", false, "Force updates over SSH by rewriting HTTPS GitHub URLs to SSH")
6165
}

docs/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ go test ./internal/git/... -v -run TestFunctionName
8080
| `spark git update-org-status <org> [--dry-run] [--update-dot-github] [--section <name>]` | Update org README with repo list |
8181
| `spark git issues [-r <owner/repo>] (-d <dir> \| -f <file>) [--dry-run] [-l <labels>]` | Create GitHub issues from markdown docs/tasks |
8282
| `spark git push-all [-p <path>]` | Commit and push all changes in repositories |
83+
| `spark git scan [folder-path] [-d <db>] [--skip-api]` | Scan git repos and save to SQLite |
8384

8485
---
8586

docs/features/git.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,19 @@ spark git push-all -p ~/workspace
112112
- 跳过非 GitHub 仓库和无更改的仓库
113113
- 遇到错误继续处理下一个仓库
114114

115+
### Git 仓库扫描
116+
117+
递归扫描目录中的 Git 仓库,从 API 获取 stars、forks、语言等信息,并保存到 SQLite 数据库。
118+
119+
```bash
120+
spark git scan ~/workspace
121+
spark git scan . --skip-api --db ~/.innate/feeds.db
122+
```
123+
124+
- 默认数据库路径:`~/.innate/feeds.db`
125+
- 可通过 `--db` 或配置项 `git.scanner.db` 自定义
126+
- 设置 `GITHUB_TOKEN` 可提高 GitHub API 速率限制
127+
115128
## 使用参数
116129

117130
| 参数 | 说明 |
@@ -130,6 +143,8 @@ spark git push-all -p ~/workspace
130143
| `-f, --file` | 任务文件(任务模式) |
131144
| `-l, --labels` | Issue 标签(逗号分隔) |
132145
| `--dry-run` | 仅预览,不创建 Issue |
146+
| `-d, --db` | SQLite 数据库路径(scan),默认 `~/.innate/feeds.db` |
147+
| `--skip-api` | 跳过 API 调用(scan) |
133148

134149
## 依赖
135150

docs/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ go test ./internal/git/... -v -run TestFunctionName
8585
| `spark git update-org-status <org> [--dry-run] [--update-dot-github] [--section <name>]` | Update org README with repo list |
8686
| `spark git issues [-r <owner/repo>] (-d <dir> \| -f <file>) [--dry-run] [-l <labels>]` | Create GitHub issues from markdown docs/tasks |
8787
| `spark git push-all [-p <path>]` | Commit and push all changes in repositories |
88+
| `spark git scan [folder-path] [-d <db>] [--skip-api]` | Scan git repos and save to SQLite |
8889

8990
---
9091

0 commit comments

Comments
 (0)