返回 DeepSeek-Reasonix
historical_archive_recovery.go
根目录 / desktop / historical_archive_recovery.go
1 package main
2
3 import (
4 "context"
5 "slices"
6
7 "reasonix/desktop/internal/workspacestate"
8 )
9
10 // Recovery takes source guards in the same order as initial archive staging,
11 // and retains them until the parent commit has finished.
12 func freezeArchiveDependencies(ctx context.Context, state workspacestate.State, op workspacestate.Operation) (func(), error) {
13 releases := []func(){}
14 release := func() {
15 for _, done := range slices.Backward(releases) {
16 done()
17 }
18 }
19 seen := map[string]bool{}
20 for _, id := range op.Dependencies {
21 child := state.PendingOperations[id]
22 if child.Kind != "archive-import" || child.Mapping == nil {
23 release()
24 return nil, workspacestate.ErrMutationConflict
25 }
26 mapping := child.Mapping
27 key := desktopSourceKey(mapping.Path, mapping.HeadID)
28 if seen[key] {
29 continue
30 }
31 seen[key] = true
32 done, err := acquireHistoricalSource(ctx, key, historicalSource{path: mapping.Path, format: mapping.Format, head: mapping.HeadID})
33 if err != nil {
34 release()
35 return nil, err
36 }
37 releases = append(releases, done)
38 }
39 return release, nil
40 }
41
42 func (a *App) validateRecoveredHistoricalArchive(ctx context.Context, state workspacestate.State, op workspacestate.Operation) error {
43 // Older topic archives used their existing snapshot/fingerprint contract.
44 // This deterministic parent ID identifies the stronger source-archive flow.
45 if len(op.Dependencies) != 1 || op.ID != "archive-"+op.Dependencies[0] {
46 return nil
47 }
48 child := state.PendingOperations[op.Dependencies[0]]
49 if child.Mapping == nil {
50 return workspacestate.ErrMutationConflict
51 }
52 mapping := child.Mapping
53 return a.validateHistoricalArchiveContent(ctx, historicalSource{path: mapping.Path, format: mapping.Format, head: mapping.HeadID}, child)
54 }
55
55 lines GO