diff --git a/main.go b/main.go index e62b5f2..444102a 100644 --- a/main.go +++ b/main.go @@ -519,13 +519,15 @@ func (s *Server) indexJob(id, root string) { s.jobsMu.Unlock() snapshot.ID = uniqueID("snapshot") - // Only the latest snapshot is kept; older workspaces are deleted. + // Each session keeps only its latest snapshot; its older workspaces are deleted. s.snapshotsMu.Lock() var oldRoots []string - for _, old := range s.snapshots { - oldRoots = append(oldRoots, old.Root) + for key, old := range s.snapshots { + if old.Owner == snapshot.Owner { + oldRoots = append(oldRoots, old.Root) + delete(s.snapshots, key) + } } - clear(s.snapshots) s.snapshots[snapshot.ID] = snapshot s.snapshotsMu.Unlock() for _, old := range oldRoots { diff --git a/main_test.go b/main_test.go index e283a5b..795dc59 100644 --- a/main_test.go +++ b/main_test.go @@ -286,3 +286,40 @@ func TestSessionCookieFlags(t *testing.T) { } } } + +// indexLocal uploads files as a local job and waits for the snapshot. +func (c client) indexLocal(files map[string]string) (jobID, snapshotID string) { + c.t.Helper() + var created struct{ JobID string } + c.json("POST", "/api/jobs", `{"kind":"local"}`, 201, &created) + for path, content := range files { + c.json("POST", "/api/jobs/"+created.JobID+"/files?path="+path, content, 200, nil) + } + c.json("POST", "/api/jobs/"+created.JobID+"/commit", "", 202, nil) + status, raw := c.do("GET", "/api/jobs/"+created.JobID+"/events", "") + var job Job + for line := range strings.Lines(string(raw)) { + if data, ok := strings.CutPrefix(line, "data: "); ok { + json.Unmarshal([]byte(data), &job) + } + } + if status != 200 || job.SnapshotID == nil { + c.t.Fatalf("job did not finish: %d %+v", status, job) + } + return created.JobID, *job.SnapshotID +} + +func TestSessionsKeepIndependentSnapshots(t *testing.T) { + server, alice := newTestServer(t) + bob := alice.stranger() + _, aliceFirst := alice.indexLocal(map[string]string{"a.go": "package a"}) + _, bobSnapshot := bob.indexLocal(map[string]string{"b.go": "package b"}) + _, aliceSecond := alice.indexLocal(map[string]string{"c.go": "package c"}) + + alice.json("GET", "/api/snapshots/"+aliceFirst, "", 404, nil) + alice.json("GET", "/api/snapshots/"+aliceSecond, "", 200, nil) + bob.json("GET", "/api/snapshots/"+bobSnapshot, "", 200, nil) + if len(server.snapshots) != 2 { + t.Fatalf("snapshots = %d, want 2", len(server.snapshots)) + } +}