@@ -2,16 +2,19 @@ package main
22
33import (
44 "errors"
5+ "fmt"
56 "os"
67 "path/filepath"
8+ "strings"
9+ "syscall"
10+ "time"
711)
812
913func cmdReset () error {
10- if st , err := loadState (); err == nil {
11- if st .MountPID > 0 || st .SyncPID > 0 {
12- if err := unmountAllActive (false ); err != nil {
13- return err
14- }
14+ targetStatePath := statePath ()
15+ if st , err := loadStateFromPath (targetStatePath ); err == nil {
16+ if err := stopRuntimeForReset (st , targetStatePath ); err != nil {
17+ return err
1518 }
1619 } else if ! errors .Is (err , os .ErrNotExist ) {
1720 return err
@@ -24,13 +27,10 @@ func cmdReset() error {
2427 return err
2528 }
2629
27- removedState := false
28- if err := os . RemoveAll ( stateDir ()); err != nil {
30+ removedState , err := removeResetScopedState ( targetStatePath )
31+ if err != nil {
2932 return err
3033 }
31- if _ , err := os .Stat (stateDir ()); errors .Is (err , os .ErrNotExist ) {
32- removedState = true
33- }
3434
3535 rows := []outputRow {
3636 {Label : "config" , Value : ternaryString (removedConfig , compactDisplayPath (configPath ()), "already clear" )},
@@ -40,3 +40,113 @@ func cmdReset() error {
4040 printSection (markerSuccess + " " + clr (ansiBold , "local state reset" ), rows )
4141 return nil
4242}
43+
44+ func stopRuntimeForReset (st state , targetStatePath string ) error {
45+ reg , err := loadMountRegistry ()
46+ if err != nil {
47+ return err
48+ }
49+ if localPath := st .LocalPath ; localPath != "" {
50+ if rec , ok := removeMountByPath (& reg , localPath ); ok {
51+ return unmountMountRecord (reg , rec , false )
52+ }
53+ }
54+ if handled , err := stopSyncServicesIfActiveAtPath (st , targetStatePath , false ); handled || err != nil {
55+ return err
56+ }
57+ return nil
58+ }
59+
60+ func stopSyncServicesIfActiveAtPath (st state , targetStatePath string , deleteLocal bool ) (bool , error ) {
61+ if strings .TrimSpace (st .Mode ) != modeSync {
62+ return false , nil
63+ }
64+
65+ fmt .Println ()
66+
67+ if st .SyncPID > 0 && processAlive (st .SyncPID ) {
68+ s := startStep ("Stopping sync daemon" )
69+ if err := terminatePID (st .SyncPID , 5 * time .Second ); err != nil {
70+ s .fail (err .Error ())
71+ } else {
72+ s .succeed (fmt .Sprintf ("pid %d" , st .SyncPID ))
73+ }
74+ }
75+ if localPath := strings .TrimSpace (st .LocalPath ); localPath != "" && deleteLocal {
76+ if err := os .RemoveAll (localPath ); err != nil {
77+ fmt .Printf (" %s local sync folder preserved at %s (%v)\n " , clr (ansiYellow , "!" ), localPath , err )
78+ }
79+ }
80+
81+ if deleteLocal {
82+ workspace := strings .TrimSpace (st .CurrentWorkspace )
83+ _ = removeSyncState (workspace )
84+ }
85+ closeManagedWorkspaceSession (configFromState (st ), strings .TrimSpace (st .CurrentWorkspace ), strings .TrimSpace (st .SessionID ))
86+
87+ if err := os .Remove (targetStatePath ); err != nil && ! errors .Is (err , os .ErrNotExist ) {
88+ return true , err
89+ }
90+ local := "preserved"
91+ if deleteLocal {
92+ local = "deleted"
93+ }
94+ fmt .Printf ("Unmounted workspace %s\n " , currentWorkspaceLabel (st .CurrentWorkspace ))
95+ fmt .Printf ("path %s\n " , homeRelativeDisplayPath (st .LocalPath ))
96+ fmt .Printf ("local %s\n " , local )
97+ return true , nil
98+ }
99+
100+ func removeResetScopedState (targetStatePath string ) (bool , error ) {
101+ removed := false
102+ if err := os .Remove (targetStatePath ); err == nil {
103+ removed = true
104+ } else if ! errors .Is (err , os .ErrNotExist ) {
105+ return false , err
106+ }
107+
108+ reg , err := loadMountRegistry ()
109+ if err != nil {
110+ return removed , err
111+ }
112+ if len (reg .Mounts ) == 0 {
113+ if err := os .Remove (mountRegistryPath ()); err == nil {
114+ removed = true
115+ } else if ! errors .Is (err , os .ErrNotExist ) {
116+ return false , err
117+ }
118+ if err := os .Remove (legacyMountRegistryPath ()); err == nil {
119+ removed = true
120+ } else if ! errors .Is (err , os .ErrNotExist ) {
121+ return false , err
122+ }
123+ }
124+
125+ for _ , dir := range []string {filepath .Dir (targetStatePath ), syncStateDir (), stateDir ()} {
126+ if err := removeDirIfEmpty (dir ); err != nil {
127+ return false , err
128+ }
129+ }
130+ if _ , err := os .Stat (stateDir ()); errors .Is (err , os .ErrNotExist ) {
131+ removed = true
132+ }
133+ return removed , nil
134+ }
135+
136+ func removeDirIfEmpty (path string ) error {
137+ if strings .TrimSpace (path ) == "" {
138+ return nil
139+ }
140+ err := os .Remove (path )
141+ if err == nil || errors .Is (err , os .ErrNotExist ) {
142+ return nil
143+ }
144+ if errors .Is (err , os .ErrExist ) || errors .Is (err , syscall .ENOTEMPTY ) {
145+ return nil
146+ }
147+ var pathErr * os.PathError
148+ if errors .As (err , & pathErr ) && pathErr .Err == syscall .ENOTEMPTY {
149+ return nil
150+ }
151+ return err
152+ }
0 commit comments