返回 DeepSeek-Reasonix
desktop_project_file_lock.go
根目录 / desktop / desktop_project_file_lock.go
1 package main
2
3 import (
4 "context"
5 "fmt"
6 "os"
7 "path/filepath"
8 "time"
9
10 filelock "reasonix/internal/identitylock"
11 )
12
13 const desktopProjectsFileLockTimeout = 2 * time.Second
14
15 func acquireDesktopProjectsFileLock() (func(), error) {
16 dir := desktopConfigDir()
17 if err := os.MkdirAll(dir, 0o700); err != nil {
18 return nil, err
19 }
20 ctx, cancel := context.WithTimeout(context.Background(), desktopProjectsFileLockTimeout)
21 defer cancel()
22 return filelock.Acquire(ctx, filepath.Join(dir, desktopProjectsFile)+".lock")
23 }
24
25 // updateProjectsFileCrossProcessLocked requires desktopProjectsFileMu and the
26 // desktop-projects cross-process file lock.
27 func updateProjectsFileCrossProcessLocked(mutator func(*desktopProjectFile) (bool, error), assignCollisions bool) error {
28 f := loadProjectsFile()
29 previous := make([]string, 0, len(f.Projects))
30 for _, project := range f.Projects {
31 previous = append(previous, project.Root)
32 }
33 changed, err := mutator(&f)
34 if err != nil {
35 return err
36 }
37 if !changed {
38 return nil
39 }
40 if assignCollisions {
41 if err := assignAddedProjectStateCollisions(previous, f.Projects); err != nil {
42 return fmt.Errorf("%w: %w", errProjectStateCollisionAssignment, err)
43 }
44 }
45 return saveProjectsFile(f)
46 }
47
47 lines GO