package main import ( "fmt" "os" "os/exec" "path/filepath" "text/tabwriter" ) func cmdAnalysis(args []string) { if len(args) < 1 { printAnalysisUsage() os.Exit(1) } switch args[0] { case "list": analysisList() case "clone": if len(args) < 2 { fmt.Fprintln(os.Stderr, "usage: fn analysis clone ") os.Exit(1) } analysisClone(args[1]) case "pull": if len(args) < 2 { fmt.Fprintln(os.Stderr, "usage: fn analysis pull ") os.Exit(1) } analysisPull(args[1]) case "help", "-h": printAnalysisUsage() default: fmt.Fprintf(os.Stderr, "unknown analysis command: %s\n", args[0]) printAnalysisUsage() os.Exit(1) } } func printAnalysisUsage() { fmt.Println(`fn analysis — manage registry analyses Usage: fn analysis list List all analyses (local + remote) fn analysis clone Clone analysis repo to analysis// fn analysis pull Git pull in existing clone`) } func analysisList() { db := openDB() defer db.Close() items, err := db.ListAllAnalysis() if err != nil { fmt.Fprintf(os.Stderr, "error: %v\n", err) os.Exit(1) } if len(items) == 0 { fmt.Println("No analyses registered.") return } r := root() w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) fmt.Fprintln(w, "ID\tLANG\tDOMAIN\tSTATUS\tREPO_URL") for _, a := range items { status := "local" if a.RepoURL != "" { dirPath := filepath.Join(r, "analysis", a.Name) if _, err := os.Stat(dirPath); os.IsNotExist(err) { status = "remote" } else { status = "cloned" } } fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n", a.ID, a.Lang, a.Domain, status, a.RepoURL) } w.Flush() } func analysisClone(id string) { db := openDB() defer db.Close() a, err := db.GetAnalysis(id) if err != nil { fmt.Fprintf(os.Stderr, "error: %v\n", err) os.Exit(1) } if a.RepoURL == "" { fmt.Fprintf(os.Stderr, "analysis %s has no repo_url set\n", id) os.Exit(1) } r := root() target := filepath.Join(r, "analysis", a.Name) if _, err := os.Stat(target); err == nil { fmt.Fprintf(os.Stderr, "directory already exists: %s\n", target) os.Exit(1) } fmt.Printf("Cloning %s → %s\n", a.RepoURL, target) cmd := exec.Command("git", "clone", a.RepoURL, target) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if err := cmd.Run(); err != nil { fmt.Fprintf(os.Stderr, "git clone failed: %v\n", err) os.Exit(1) } fmt.Println("Done. Run 'fn index' to re-index.") } func analysisPull(id string) { db := openDB() defer db.Close() a, err := db.GetAnalysis(id) if err != nil { fmt.Fprintf(os.Stderr, "error: %v\n", err) os.Exit(1) } r := root() dir := filepath.Join(r, "analysis", a.Name) if _, err := os.Stat(dir); os.IsNotExist(err) { fmt.Fprintf(os.Stderr, "analysis not cloned locally: %s\n", dir) fmt.Fprintln(os.Stderr, "Run 'fn analysis clone "+id+"' first.") os.Exit(1) } fmt.Printf("Pulling %s\n", dir) cmd := exec.Command("git", "-C", dir, "pull") cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if err := cmd.Run(); err != nil { fmt.Fprintf(os.Stderr, "git pull failed: %v\n", err) os.Exit(1) } fmt.Println("Done. Run 'fn index' to re-index.") }