fix(crew): use directory name as source of truth in loadState (#785)
Fixes gt crew list showing wrong names when state.json contains stale data. Always use directory name as source of truth in loadState() instead of trusting potentially stale state.json. Co-authored-by: joshuavial <git@codewithjv.com>
This commit is contained in:
@@ -315,16 +315,15 @@ func (m *Manager) loadState(name string) (*CrewWorker, error) {
|
|||||||
return nil, fmt.Errorf("parsing state: %w", err)
|
return nil, fmt.Errorf("parsing state: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Backfill essential fields if missing (handles empty or incomplete state.json)
|
// Directory name is source of truth for Name and ClonePath.
|
||||||
if crew.Name == "" {
|
// state.json can become stale after directory rename, copy, or corruption.
|
||||||
crew.Name = name
|
crew.Name = name
|
||||||
}
|
crew.ClonePath = m.crewDir(name)
|
||||||
|
|
||||||
|
// Rig only needs backfill when empty (less likely to drift)
|
||||||
if crew.Rig == "" {
|
if crew.Rig == "" {
|
||||||
crew.Rig = m.rig.Name
|
crew.Rig = m.rig.Name
|
||||||
}
|
}
|
||||||
if crew.ClonePath == "" {
|
|
||||||
crew.ClonePath = m.crewDir(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &crew, nil
|
return &crew, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -342,6 +342,56 @@ func TestManagerRemove(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestManagerGetWithStaleStateName(t *testing.T) {
|
||||||
|
// Regression test: state.json with wrong name should not affect Get() result
|
||||||
|
// See: gt-h1w - gt crew list shows wrong names
|
||||||
|
tmpDir, err := os.MkdirTemp("", "crew-test-stale-*")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create temp dir: %v", err)
|
||||||
|
}
|
||||||
|
defer func() { _ = os.RemoveAll(tmpDir) }()
|
||||||
|
|
||||||
|
rigPath := filepath.Join(tmpDir, "test-rig")
|
||||||
|
if err := os.MkdirAll(rigPath, 0755); err != nil {
|
||||||
|
t.Fatalf("failed to create rig dir: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
r := &rig.Rig{
|
||||||
|
Name: "test-rig",
|
||||||
|
Path: rigPath,
|
||||||
|
}
|
||||||
|
|
||||||
|
mgr := NewManager(r, git.NewGit(rigPath))
|
||||||
|
|
||||||
|
// Manually create a crew directory with wrong name in state.json
|
||||||
|
crewDir := filepath.Join(rigPath, "crew", "alice")
|
||||||
|
if err := os.MkdirAll(crewDir, 0755); err != nil {
|
||||||
|
t.Fatalf("failed to create crew dir: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write state.json with wrong name (simulates stale/copied state)
|
||||||
|
stateFile := filepath.Join(crewDir, "state.json")
|
||||||
|
staleState := `{"name": "bob", "rig": "test-rig", "clone_path": "/wrong/path"}`
|
||||||
|
if err := os.WriteFile(stateFile, []byte(staleState), 0644); err != nil {
|
||||||
|
t.Fatalf("failed to write state file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get should return correct name (alice) not stale name (bob)
|
||||||
|
worker, err := mgr.Get("alice")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Get failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if worker.Name != "alice" {
|
||||||
|
t.Errorf("expected name 'alice', got '%s' (stale state.json not overridden)", worker.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedPath := filepath.Join(rigPath, "crew", "alice")
|
||||||
|
if worker.ClonePath != expectedPath {
|
||||||
|
t.Errorf("expected clone_path '%s', got '%s'", expectedPath, worker.ClonePath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Helper to run commands
|
// Helper to run commands
|
||||||
func runCmd(name string, args ...string) error {
|
func runCmd(name string, args ...string) error {
|
||||||
cmd := exec.Command(name, args...)
|
cmd := exec.Command(name, args...)
|
||||||
|
|||||||
Reference in New Issue
Block a user