@tanagram/cli 0.4.11 → 0.4.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,6 +4,7 @@ import (
4
4
  "encoding/json"
5
5
  "os"
6
6
  "path/filepath"
7
+ "strings"
7
8
  "testing"
8
9
  )
9
10
 
@@ -31,12 +32,12 @@ func TestConfigClaude(t *testing.T) {
31
32
  }
32
33
 
33
34
  settings := readSettings(t, settingsPath)
34
- pre, post := checkHooks(settings)
35
- if !pre {
36
- t.Error("PreToolUse hook not created")
35
+ sessionStart, stop := checkHooks(settings)
36
+ if !sessionStart {
37
+ t.Error("SessionStart hook not created")
37
38
  }
38
- if !post {
39
- t.Error("PostToolUse hook not created")
39
+ if !stop {
40
+ t.Error("Stop hook not created")
40
41
  }
41
42
  })
42
43
 
@@ -47,22 +48,22 @@ func TestConfigClaude(t *testing.T) {
47
48
  }
48
49
 
49
50
  settings := readSettings(t, settingsPath)
50
- pre, post := checkHooks(settings)
51
- if !pre || !post {
51
+ sessionStart, stop := checkHooks(settings)
52
+ if !sessionStart || !stop {
52
53
  t.Error("Hooks missing after second run")
53
54
  }
54
55
 
55
56
  // Check that we didn't duplicate them (rudimentary check: count of items)
56
57
  hooks := settings["hooks"].(map[string]interface{})
57
- preToolUse := hooks["PreToolUse"].([]interface{})
58
- postToolUse := hooks["PostToolUse"].([]interface{})
58
+ sessionStartHooks := hooks["SessionStart"].([]interface{})
59
+ stopHooks := hooks["Stop"].([]interface{})
59
60
 
60
61
  // We expect exactly 1 hook in each since we started fresh
61
- if len(preToolUse) != 1 {
62
- t.Errorf("Expected 1 PreToolUse hook, got %d", len(preToolUse))
62
+ if len(sessionStartHooks) != 1 {
63
+ t.Errorf("Expected 1 SessionStart hook, got %d", len(sessionStartHooks))
63
64
  }
64
- if len(postToolUse) != 1 {
65
- t.Errorf("Expected 1 PostToolUse hook, got %d", len(postToolUse))
65
+ if len(stopHooks) != 1 {
66
+ t.Errorf("Expected 1 Stop hook, got %d", len(stopHooks))
66
67
  }
67
68
  })
68
69
 
@@ -70,9 +71,9 @@ func TestConfigClaude(t *testing.T) {
70
71
  // Reset with a file that has other hooks
71
72
  otherHook := map[string]interface{}{
72
73
  "hooks": map[string]interface{}{
73
- "PreToolUse": []interface{}{
74
+ "SessionStart": []interface{}{
74
75
  map[string]interface{}{
75
- "matcher": "Read",
76
+ "matcher": "startup|clear",
76
77
  "hooks": []interface{}{
77
78
  map[string]interface{}{"command": "echo existing"},
78
79
  },
@@ -100,19 +101,19 @@ func TestConfigClaude(t *testing.T) {
100
101
  }
101
102
 
102
103
  settings := readSettings(t, settingsPath)
103
- pre, post := checkHooks(settings)
104
- if !pre || !post {
104
+ sessionStart, stop := checkHooks(settings)
105
+ if !sessionStart || !stop {
105
106
  t.Error("Tanagram hooks missing when merging with existing config")
106
107
  }
107
108
 
108
109
  // Check if existing hook is still there
109
110
  hooks := settings["hooks"].(map[string]interface{})
110
- preToolUse := hooks["PreToolUse"].([]interface{})
111
+ sessionStartHooks := hooks["SessionStart"].([]interface{})
111
112
 
112
113
  foundExisting := false
113
- for _, h := range preToolUse {
114
+ for _, h := range sessionStartHooks {
114
115
  hMap := h.(map[string]interface{})
115
- if hMap["matcher"] == "Read" {
116
+ if hMap["matcher"] == "startup|clear" {
116
117
  // Check for the specific command to be sure it's the right one
117
118
  if commands, ok := hMap["hooks"].([]interface{}); ok {
118
119
  for _, cmd := range commands {
@@ -133,6 +134,85 @@ func TestConfigClaude(t *testing.T) {
133
134
  t.Error("Existing hook was lost")
134
135
  }
135
136
  })
137
+
138
+ t.Run("Preserve existing absolute path hooks", func(t *testing.T) {
139
+ // Reset with a file that has absolute path hooks
140
+ absHook := map[string]interface{}{
141
+ "hooks": map[string]interface{}{
142
+ "SessionStart": []interface{}{
143
+ map[string]interface{}{
144
+ "matcher": "startup|clear",
145
+ "hooks": []interface{}{
146
+ map[string]interface{}{"command": "/absolute/path/to/tanagram snapshot"},
147
+ },
148
+ },
149
+ },
150
+ "Stop": []interface{}{
151
+ map[string]interface{}{
152
+ "hooks": []interface{}{
153
+ map[string]interface{}{
154
+ "type": "command",
155
+ "command": "/absolute/path/to/tanagram",
156
+ },
157
+ },
158
+ },
159
+ },
160
+ },
161
+ }
162
+
163
+ // Clean up previous run
164
+ os.RemoveAll(filepath.Dir(settingsPath))
165
+
166
+ dir := filepath.Dir(settingsPath)
167
+ if err := os.MkdirAll(dir, 0755); err != nil {
168
+ t.Fatalf("Failed to create dir: %v", err)
169
+ }
170
+
171
+ // Write absHook to settingsPath
172
+ data, _ := json.Marshal(absHook)
173
+ if err := os.WriteFile(settingsPath, data, 0644); err != nil {
174
+ t.Fatalf("Failed to write settings: %v", err)
175
+ }
176
+
177
+ if err := ConfigClaude(settingsPath); err != nil {
178
+ t.Fatalf("ConfigClaude() failed: %v", err)
179
+ }
180
+
181
+ settings := readSettings(t, settingsPath)
182
+
183
+ // Check duplication
184
+ hooks := settings["hooks"].(map[string]interface{})
185
+ sessionStartHooks := hooks["SessionStart"].([]interface{})
186
+ stopHooks := hooks["Stop"].([]interface{})
187
+
188
+ // We expect exactly 1 hook since we started with 1 and it should match
189
+ if len(sessionStartHooks) != 1 {
190
+ t.Errorf("Expected 1 SessionStart hook, got %d", len(sessionStartHooks))
191
+ }
192
+ if len(stopHooks) != 1 {
193
+ t.Errorf("Expected 1 Stop hook, got %d", len(stopHooks))
194
+ }
195
+
196
+ // Check content
197
+ h := sessionStartHooks[0].(map[string]interface{})
198
+ innerHooks := h["hooks"].([]interface{})
199
+ cmdMap := innerHooks[0].(map[string]interface{})
200
+ cmd := cmdMap["command"].(string)
201
+
202
+ if cmd != "/absolute/path/to/tanagram snapshot" {
203
+ t.Errorf("Expected command to be preserved as '/absolute/path/to/tanagram snapshot', got '%s'", cmd)
204
+ }
205
+
206
+ // Check post content
207
+ hPost := stopHooks[0].(map[string]interface{})
208
+ innerHooksPost := hPost["hooks"].([]interface{})
209
+ cmdMapPost := innerHooksPost[0].(map[string]interface{})
210
+ cmdPost := cmdMapPost["command"].(string)
211
+
212
+ if cmdPost != "/absolute/path/to/tanagram" {
213
+ t.Errorf("Expected command to be preserved as '/absolute/path/to/tanagram', got '%s'", cmdPost)
214
+ }
215
+ })
136
216
  }
137
217
 
138
218
  func TestConfigCursor(t *testing.T) {
@@ -243,6 +323,69 @@ func TestConfigCursor(t *testing.T) {
243
323
  t.Error("Existing hook was lost")
244
324
  }
245
325
  })
326
+
327
+ t.Run("Preserve existing absolute path hooks", func(t *testing.T) {
328
+ // Reset with a file that has absolute path hooks
329
+ absHook := map[string]interface{}{
330
+ "hooks": map[string]interface{}{
331
+ "beforeSubmitPrompt": []interface{}{
332
+ map[string]interface{}{"command": "/absolute/path/to/tanagram snapshot"},
333
+ },
334
+ "stop": []interface{}{
335
+ map[string]interface{}{"command": "/absolute/path/to/tanagram"},
336
+ },
337
+ },
338
+ }
339
+
340
+ // Clean up previous run
341
+ os.RemoveAll(filepath.Dir(hooksPath))
342
+
343
+ dir := filepath.Dir(hooksPath)
344
+ if err := os.MkdirAll(dir, 0755); err != nil {
345
+ t.Fatalf("Failed to create dir: %v", err)
346
+ }
347
+
348
+ // Write absHook to hooksPath
349
+ data, _ := json.Marshal(absHook)
350
+ if err := os.WriteFile(hooksPath, data, 0644); err != nil {
351
+ t.Fatalf("Failed to write settings: %v", err)
352
+ }
353
+
354
+ if err := ConfigCursor(hooksPath); err != nil {
355
+ t.Fatalf("ConfigCursor() failed: %v", err)
356
+ }
357
+
358
+ settings := readSettings(t, hooksPath)
359
+
360
+ // Check duplication
361
+ hooks := settings["hooks"].(map[string]interface{})
362
+ beforeSubmitHooks := hooks["beforeSubmitPrompt"].([]interface{})
363
+ stopHooks := hooks["stop"].([]interface{})
364
+
365
+ // We expect exactly 1 hook since we started with 1 and it should match
366
+ if len(beforeSubmitHooks) != 1 {
367
+ t.Errorf("Expected 1 beforeSubmitPrompt hook, got %d", len(beforeSubmitHooks))
368
+ }
369
+ if len(stopHooks) != 1 {
370
+ t.Errorf("Expected 1 stop hook, got %d", len(stopHooks))
371
+ }
372
+
373
+ // Check content
374
+ h := beforeSubmitHooks[0].(map[string]interface{})
375
+ cmd, _ := h["command"].(string)
376
+
377
+ if cmd != "/absolute/path/to/tanagram snapshot" {
378
+ t.Errorf("Expected command to be preserved as '/absolute/path/to/tanagram snapshot', got '%s'", cmd)
379
+ }
380
+
381
+ // Check stop content
382
+ hStop := stopHooks[0].(map[string]interface{})
383
+ cmdStop, _ := hStop["command"].(string)
384
+
385
+ if cmdStop != "/absolute/path/to/tanagram" {
386
+ t.Errorf("Expected command to be preserved as '/absolute/path/to/tanagram', got '%s'", cmdStop)
387
+ }
388
+ })
246
389
  }
247
390
 
248
391
  func TestEnsureHooksConfigured(t *testing.T) {
@@ -277,12 +420,12 @@ func TestEnsureHooksConfigured(t *testing.T) {
277
420
  // Check Claude settings
278
421
  claudeSettingsPath := filepath.Join(tempHome, ".claude", "settings.json")
279
422
  claudeSettings := readSettings(t, claudeSettingsPath)
280
- pre, post := checkHooks(claudeSettings)
281
- if !pre {
282
- t.Error("PreToolUse hook not created")
423
+ sessionStart, stop := checkHooks(claudeSettings)
424
+ if !sessionStart {
425
+ t.Error("SessionStart hook not created")
283
426
  }
284
- if !post {
285
- t.Error("PostToolUse hook not created")
427
+ if !stop {
428
+ t.Error("Stop hook not created")
286
429
  }
287
430
 
288
431
  // Check Cursor hooks
@@ -316,16 +459,16 @@ func checkHooks(settings map[string]interface{}) (bool, bool) {
316
459
  return false, false
317
460
  }
318
461
 
319
- preExists := false
320
- if preToolUse, ok := hooks["PreToolUse"].([]interface{}); ok {
321
- for _, h := range preToolUse {
462
+ sessionStartExists := false
463
+ if sessionStart, ok := hooks["SessionStart"].([]interface{}); ok {
464
+ for _, h := range sessionStart {
322
465
  if hMap, ok := h.(map[string]interface{}); ok {
323
- if hMap["matcher"] == "Edit|Write" {
466
+ if hMap["matcher"] == "startup|clear" {
324
467
  if innerHooks, ok := hMap["hooks"].([]interface{}); ok {
325
468
  for _, ih := range innerHooks {
326
469
  if ihMap, ok := ih.(map[string]interface{}); ok {
327
- if ihMap["command"] == "tanagram snapshot" {
328
- preExists = true
470
+ if cmd, ok := ihMap["command"].(string); ok && strings.HasSuffix(cmd, "tanagram snapshot") {
471
+ sessionStartExists = true
329
472
  }
330
473
  }
331
474
  }
@@ -335,17 +478,15 @@ func checkHooks(settings map[string]interface{}) (bool, bool) {
335
478
  }
336
479
  }
337
480
 
338
- postExists := false
339
- if postToolUse, ok := hooks["PostToolUse"].([]interface{}); ok {
340
- for _, h := range postToolUse {
481
+ stopExists := false
482
+ if stopHooks, ok := hooks["Stop"].([]interface{}); ok {
483
+ for _, h := range stopHooks {
341
484
  if hMap, ok := h.(map[string]interface{}); ok {
342
- if hMap["matcher"] == "Edit|Write" {
343
- if innerHooks, ok := hMap["hooks"].([]interface{}); ok {
344
- for _, ih := range innerHooks {
345
- if ihMap, ok := ih.(map[string]interface{}); ok {
346
- if ihMap["command"] == "tanagram" {
347
- postExists = true
348
- }
485
+ if innerHooks, ok := hMap["hooks"].([]interface{}); ok {
486
+ for _, ih := range innerHooks {
487
+ if ihMap, ok := ih.(map[string]interface{}); ok {
488
+ if cmd, ok := ihMap["command"].(string); ok && strings.HasSuffix(cmd, "tanagram") {
489
+ stopExists = true
349
490
  }
350
491
  }
351
492
  }
@@ -354,7 +495,7 @@ func checkHooks(settings map[string]interface{}) (bool, bool) {
354
495
  }
355
496
  }
356
497
 
357
- return preExists, postExists
498
+ return sessionStartExists, stopExists
358
499
  }
359
500
 
360
501
  func checkCursorHooks(settings map[string]interface{}) (bool, bool) {
@@ -367,7 +508,7 @@ func checkCursorHooks(settings map[string]interface{}) (bool, bool) {
367
508
  if beforeSubmit, ok := hooks["beforeSubmitPrompt"].([]interface{}); ok {
368
509
  for _, h := range beforeSubmit {
369
510
  if hMap, ok := h.(map[string]interface{}); ok {
370
- if cmd, ok := hMap["command"].(string); ok && cmd == "tanagram snapshot" {
511
+ if cmd, ok := hMap["command"].(string); ok && strings.HasSuffix(cmd, "tanagram snapshot") {
371
512
  beforeSubmitExists = true
372
513
  }
373
514
  }
@@ -378,7 +519,7 @@ func checkCursorHooks(settings map[string]interface{}) (bool, bool) {
378
519
  if stop, ok := hooks["stop"].([]interface{}); ok {
379
520
  for _, h := range stop {
380
521
  if hMap, ok := h.(map[string]interface{}); ok {
381
- if cmd, ok := hMap["command"].(string); ok && cmd == "tanagram" {
522
+ if cmd, ok := hMap["command"].(string); ok && strings.HasSuffix(cmd, "tanagram") {
382
523
  stopExists = true
383
524
  }
384
525
  }
package/commands/login.go CHANGED
@@ -19,7 +19,7 @@ import (
19
19
  // getWebAppURL returns the web app URL based on environment
20
20
  func getWebAppURL() string {
21
21
  // Check environment variable first
22
- if url := os.Getenv("TANAGRAM_WEB_URL"); url != "" {
22
+ if url := os.Getenv("TANAGRAM_WEB_HOSTNAME"); url != "" {
23
23
  return url
24
24
  }
25
25
 
@@ -79,7 +79,7 @@ func Login() error {
79
79
 
80
80
  // Send success message to browser
81
81
  w.Header().Set("Content-Type", "text/html; charset=utf-8")
82
- fmt.Fprintf(w, `
82
+ fmt.Fprint(w, `
83
83
  <!DOCTYPE html>
84
84
  <html lang="en">
85
85
  <head>
package/commands/run.go CHANGED
@@ -3,6 +3,7 @@ package commands
3
3
  import (
4
4
  "context"
5
5
  "fmt"
6
+ "log/slog"
6
7
  "os"
7
8
  "path/filepath"
8
9
  "sync"
@@ -26,10 +27,10 @@ func spinner(stop chan bool, message string) {
26
27
  for {
27
28
  select {
28
29
  case <-stop:
29
- fmt.Fprint(os.Stderr, "\r")
30
+ slog.Info("\r")
30
31
  return
31
32
  default:
32
- fmt.Fprintf(os.Stderr, "\r%s %s", chars[i%len(chars)], message)
33
+ slog.Info("spinner", "char", chars[i%len(chars)], "message", message)
33
34
  i++
34
35
  time.Sleep(100 * time.Millisecond)
35
36
  }
@@ -80,7 +81,7 @@ func Run() error {
80
81
  return err
81
82
  }
82
83
 
83
- fmt.Fprintf(os.Stderr, "\nSyncing policies with LLM (processing %d changed file(s) in parallel)...\n", len(filesToSync))
84
+ slog.Info("Syncing policies with LLM", "files_to_process", len(filesToSync))
84
85
 
85
86
  syncStart := time.Now()
86
87
  ctx := context.Background()
@@ -102,19 +103,16 @@ func Run() error {
102
103
  var completed int
103
104
  var mu sync.Mutex
104
105
  go func() {
105
- chars := []string{"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"}
106
- i := 0
107
106
  for {
108
107
  select {
109
108
  case <-stop:
110
- fmt.Fprint(os.Stderr, "\r")
109
+ slog.Info("spinner stopped")
111
110
  return
112
111
  default:
113
112
  mu.Lock()
114
113
  c := completed
115
114
  mu.Unlock()
116
- fmt.Fprintf(os.Stderr, "\r%s Processing files... (%d/%d completed)", chars[i%len(chars)], c, len(filesToSync))
117
- i++
115
+ slog.Info("Processing files", "completed", c, "total", len(filesToSync))
118
116
  time.Sleep(100 * time.Millisecond)
119
117
  }
120
118
  }
@@ -145,7 +143,7 @@ func Run() error {
145
143
  close(stop)
146
144
  time.Sleep(50 * time.Millisecond)
147
145
  mu.Lock()
148
- fmt.Fprintf(os.Stderr, "\r\033[K✗ Failed to process %s\n", result.relPath)
146
+ slog.Error("Failed to process file", "file", result.relPath)
149
147
  mu.Unlock()
150
148
  return fmt.Errorf("failed to extract policies from %s: %w", result.file, result.err)
151
149
  }
@@ -162,7 +160,7 @@ func Run() error {
162
160
  // Atomic update of counter and output (prevents race with spinner)
163
161
  mu.Lock()
164
162
  completed++
165
- fmt.Fprintf(os.Stderr, "\r\033[K✓ %s - %d policies\n", result.relPath, len(result.policies))
163
+ slog.Info("Processed file", "file", result.relPath, "policies", len(result.policies))
166
164
  mu.Unlock()
167
165
  }
168
166
 
@@ -176,7 +174,7 @@ func Run() error {
176
174
  }
177
175
 
178
176
  syncDuration := time.Since(syncStart)
179
- fmt.Fprintf(os.Stderr, "\n✓ Synced %d policies from %d changed file(s)\n", totalPolicies, len(filesToSync))
177
+ slog.Info("Sync complete", "policies_synced", totalPolicies, "files_synced", len(filesToSync))
180
178
 
181
179
  // Track sync metrics
182
180
  metrics.Track("cli.sync.complete", map[string]interface{}{
@@ -202,10 +200,10 @@ func Run() error {
202
200
  cloudPolicies, err = cloudStorage.LoadCloudPoliciesAsParserFormat(repoInfo.Owner, repoInfo.Name)
203
201
  if err != nil {
204
202
  // Cloud policies exist but failed to load - warn but continue
205
- fmt.Fprintf(os.Stderr, "Warning: Failed to load cloud policies: %v\n", err)
203
+ slog.Warn("Failed to load cloud policies", "error", err)
206
204
  cloudPolicies = []parser.Policy{}
207
205
  } else if len(cloudPolicies) > 0 {
208
- fmt.Fprintf(os.Stderr, "Loaded %d cloud policies for %s/%s\n", len(cloudPolicies), repoInfo.Owner, repoInfo.Name)
206
+ slog.Info("Loaded cloud policies", "count", len(cloudPolicies), "owner", repoInfo.Owner, "repo", repoInfo.Name)
209
207
  }
210
208
  }
211
209
  // If repo detection failed, silently continue with local-only policies
@@ -214,7 +212,7 @@ func Run() error {
214
212
  policies := storage.MergePolicies(localPolicies, cloudPolicies)
215
213
 
216
214
  if len(policies) == 0 {
217
- fmt.Fprintln(os.Stderr, "No enforceable policies found")
215
+ slog.Info("No enforceable policies found")
218
216
  return nil
219
217
  }
220
218
 
@@ -223,9 +221,9 @@ func Run() error {
223
221
  totalMerged := len(policies)
224
222
 
225
223
  if totalCloud > 0 {
226
- fmt.Fprintf(os.Stderr, "Total policies: %d (%d local, %d cloud, %d after merge)\n", totalMerged, totalLocal, totalCloud, totalMerged)
224
+ slog.Info("Total policies", "total", totalMerged, "local", totalLocal, "cloud", totalCloud, "after_merge", totalMerged)
227
225
  } else {
228
- fmt.Fprintf(os.Stderr, "Loaded %d local policies\n", totalLocal)
226
+ slog.Info("Loaded local policies", "count", totalLocal)
229
227
  }
230
228
 
231
229
  // Check if a snapshot exists (from PreToolUse hook)
@@ -233,7 +231,7 @@ func Run() error {
233
231
  useSnapshot := false
234
232
 
235
233
  if snapshot.Exists(gitRoot) {
236
- fmt.Fprintln(os.Stderr, "Snapshot detected - checking only Claude's changes...")
234
+ slog.Info("Snapshot detected - checking only Claude's changes")
237
235
 
238
236
  // Load snapshot
239
237
  snap, err := snapshot.Load(gitRoot)
@@ -265,13 +263,13 @@ func Run() error {
265
263
 
266
264
  // Delete snapshot after using it
267
265
  if err := snapshot.Delete(gitRoot); err != nil {
268
- fmt.Fprintf(os.Stderr, "Warning: failed to delete snapshot: %v\n", err)
266
+ slog.Warn("Failed to delete snapshot", "error", err)
269
267
  }
270
268
 
271
269
  useSnapshot = true
272
270
  } else {
273
271
  // No snapshot - fall back to checking all git changes
274
- fmt.Fprintln(os.Stderr, "Checking all changes (unstaged + staged)...")
272
+ slog.Info("Checking all changes (unstaged + staged)")
275
273
  diffResult, err := gitpkg.GetAllChanges()
276
274
  if err != nil {
277
275
  return fmt.Errorf("error getting git diff: %w", err)
@@ -282,14 +280,14 @@ func Run() error {
282
280
 
283
281
  if len(changesToCheck) == 0 {
284
282
  if useSnapshot {
285
- fmt.Fprintln(os.Stderr, "No changes detected since snapshot")
283
+ fmt.Fprint(os.Stdout, "No changes detected since snapshot\n")
286
284
  } else {
287
- fmt.Fprintln(os.Stderr, "No changes to check")
285
+ fmt.Fprint(os.Stdout, "No changes to check\n")
288
286
  }
289
287
  return nil
290
288
  }
291
289
 
292
- fmt.Fprintf(os.Stderr, "Scanning %d changed lines...\n\n", len(changesToCheck))
290
+ slog.Info("Scanning changed lines", "count", len(changesToCheck))
293
291
 
294
292
  // Get API key once upfront before checking
295
293
  apiKey, err := config.GetAPIKey()
@@ -337,6 +335,6 @@ func Run() error {
337
335
  }
338
336
 
339
337
  // No violations found - output success message
340
- fmt.Fprintln(os.Stderr, "No policy violations found")
338
+ fmt.Fprint(os.Stdout, "No policy violations found")
341
339
  return nil
342
340
  }
@@ -10,11 +10,11 @@ import (
10
10
  func TestSnapshot_Cursor(t *testing.T) {
11
11
  // Save original functions
12
12
  origFindGitRoot := findGitRoot
13
- origCreateSnapshot := createSnapshot
13
+ origCreateSnapshot := createOptimized
14
14
  origGetParentProcess := getParentProcess
15
15
  defer func() {
16
16
  findGitRoot = origFindGitRoot
17
- createSnapshot = origCreateSnapshot
17
+ createOptimized = origCreateSnapshot
18
18
  getParentProcess = origGetParentProcess
19
19
  }()
20
20
 
@@ -22,7 +22,7 @@ func TestSnapshot_Cursor(t *testing.T) {
22
22
  findGitRoot = func() (string, error) {
23
23
  return "/tmp/mock-git-root", nil
24
24
  }
25
- createSnapshot = func(root string) error {
25
+ createOptimized = func(root string, files []string) error {
26
26
  return nil
27
27
  }
28
28
 
package/go.mod CHANGED
@@ -43,6 +43,7 @@ require (
43
43
  github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
44
44
  github.com/yusufpapurcu/wmi v1.2.4 // indirect
45
45
  github.com/zalando/go-keyring v0.2.6 // indirect
46
- golang.org/x/sys v0.36.0 // indirect
46
+ golang.org/x/sys v0.38.0 // indirect
47
+ golang.org/x/term v0.37.0 // indirect
47
48
  golang.org/x/text v0.27.0 // indirect
48
49
  )
package/go.sum CHANGED
@@ -97,6 +97,10 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
97
97
  golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
98
98
  golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
99
99
  golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
100
+ golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
101
+ golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
102
+ golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU=
103
+ golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=
100
104
  golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
101
105
  golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
102
106
  golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=