ai_xiaopei
9 days ago 6078b81fbe0331683ee0ecc1242df7e72709a99f
feat: add git sync command

- Implement git sync to add, commit, and push knowledge base changes
- Auto-generate commit message with timestamp
- Check for changes before committing
2 files modified
70 ■■■■■ changed files
bin/kb patch | view | raw | blame | history
cmd/index.go 70 ●●●●● patch | view | raw | blame | history
bin/kb
Binary files differ
cmd/index.go
@@ -3,8 +3,10 @@
import (
    "fmt"
    "os"
    "os/exec"
    "path/filepath"
    "strings"
    "time"
    "github.com/aisim/kb-cli/internal/index"
    "github.com/spf13/cobra"
@@ -33,11 +35,25 @@
    RunE:  runIndexGc,
}
var gitCmd = &cobra.Command{
    Use:   "git",
    Short: "Git 同步操作",
}
var gitSyncCmd = &cobra.Command{
    Use:   "sync",
    Short: "同步知识库到 Git 仓库",
    RunE:  runGitSync,
}
func init() {
    rootCmd.AddCommand(indexCmd)
    indexCmd.AddCommand(indexBuildCmd)
    indexCmd.AddCommand(indexStatusCmd)
    indexCmd.AddCommand(indexGcCmd)
    rootCmd.AddCommand(gitCmd)
    gitCmd.AddCommand(gitSyncCmd)
}
func runIndexBuild(cmd *cobra.Command, args []string) error {
@@ -173,3 +189,57 @@
    fmt.Fprintf(os.Stderr, "已清理 %d 个孤立节点\n", deletedCount)
    return nil
}
func runGitSync(cmd *cobra.Command, args []string) error {
    // 展开 ~ 为实际路径
    expandedVaultPath := vaultPath
    if strings.HasPrefix(vaultPath, "~/") {
        home, err := os.UserHomeDir()
        if err != nil {
            return fmt.Errorf("获取用户目录失败: %w", err)
        }
        expandedVaultPath = filepath.Join(home, vaultPath[2:])
    }
    fmt.Fprintln(os.Stderr, "正在同步知识库到 Git 仓库...")
    // 检查是否是 git 仓库
    gitDir := filepath.Join(expandedVaultPath, ".git")
    if _, err := os.Stat(gitDir); os.IsNotExist(err) {
        return fmt.Errorf("知识库目录不是 Git 仓库: %s", expandedVaultPath)
    }
    // 执行 git add -A
    addCmd := exec.Command("git", "-C", expandedVaultPath, "add", "-A")
    if output, err := addCmd.CombinedOutput(); err != nil {
        return fmt.Errorf("git add 失败: %w\n%s", err, output)
    }
    // 检查是否有变更
    statusCmd := exec.Command("git", "-C", expandedVaultPath, "status", "--porcelain")
    statusOutput, err := statusCmd.Output()
    if err != nil {
        return fmt.Errorf("git status 失败: %w", err)
    }
    if len(statusOutput) == 0 {
        fmt.Fprintln(os.Stderr, "没有变更需要提交")
        return nil
    }
    // 生成 commit 信息
    commitMsg := fmt.Sprintf("kb-cli: 自动同步 %s", time.Now().Format("2006-01-02 15:04:05"))
    commitCmd := exec.Command("git", "-C", expandedVaultPath, "commit", "-m", commitMsg)
    if output, err := commitCmd.CombinedOutput(); err != nil {
        return fmt.Errorf("git commit 失败: %w\n%s", err, output)
    }
    // 执行 git push
    pushCmd := exec.Command("git", "-C", expandedVaultPath, "push")
    if output, err := pushCmd.CombinedOutput(); err != nil {
        return fmt.Errorf("git push 失败: %w\n%s", err, output)
    }
    fmt.Fprintln(os.Stderr, "Git 同步完成")
    return nil
}