-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdiff.go
More file actions
86 lines (80 loc) · 2.41 KB
/
diff.go
File metadata and controls
86 lines (80 loc) · 2.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
package cli
import (
"encoding/json"
"fmt"
"path/filepath"
"github.com/randomcodespace/codeiq/internal/analyzer"
"github.com/randomcodespace/codeiq/internal/cache"
"github.com/randomcodespace/codeiq/internal/detector"
"github.com/spf13/cobra"
)
func init() {
registerSubcommand(func() *cobra.Command {
var cachePath string
cmd := &cobra.Command{
Use: "diff [path]",
Short: "Show the cache vs disk delta without touching the graph.",
Long: `Walk the project at [path] and classify each file against the
SQLite analysis cache:
- Added -- on disk, not in cache
- Modified -- path in cache but content hash differs from disk
- Deleted -- in cache, missing from disk
- Unchanged -- path + content hash match cache exactly
Useful for previewing what an incremental ` + "`codeiq index`" + ` /
` + "`codeiq enrich`" + ` run would do. The cache is not modified.`,
Example: ` codeiq diff .
codeiq diff /path/to/repo
codeiq diff /path/to/repo --cache-path /tmp/scratch.sqlite`,
Args: cobra.MaximumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
root, err := resolvePath(args)
if err != nil {
return err
}
cp := cachePath
if cp == "" {
cp = filepath.Join(root, ".codeiq", "cache", "codeiq.sqlite")
}
c, err := cache.Open(cp)
if err != nil {
return fmt.Errorf("open cache %s: %w", cp, err)
}
defer c.Close()
a := analyzer.NewAnalyzer(analyzer.Options{
Cache: c,
Registry: detector.Default,
})
d, err := a.Diff(root)
if err != nil {
return err
}
out := map[string]any{
"added": stringsOrEmpty(d.Added),
"modified": stringsOrEmpty(d.Modified),
"deleted": stringsOrEmpty(d.Deleted),
"unchanged": stringsOrEmpty(d.Unchanged),
"counts": map[string]int{
"added": len(d.Added),
"modified": len(d.Modified),
"deleted": len(d.Deleted),
"unchanged": len(d.Unchanged),
},
}
enc := json.NewEncoder(cmd.OutOrStdout())
enc.SetIndent("", " ")
return enc.Encode(out)
},
}
cmd.Flags().StringVar(&cachePath, "cache-path", "",
"Path to the cache file (default: <path>/.codeiq/cache/codeiq.sqlite).")
return cmd
})
}
// stringsOrEmpty replaces a nil slice with an empty one so JSON output is
// `[]` instead of `null` for empty buckets.
func stringsOrEmpty(s []string) []string {
if s == nil {
return []string{}
}
return s
}