@@ -34,6 +34,11 @@ type unmountOptions struct {
3434 deleteLocal bool
3535}
3636
37+ var (
38+ startMountServicesForWorkspaceMount = startMountServices
39+ startSyncMountForWorkspaceMount = startSyncMount
40+ )
41+
3742func cmdMountArgs (args []string ) error {
3843 if len (args ) > 0 && isHelpArg (args [0 ]) {
3944 fmt .Fprint (os .Stderr , mountUsageText (filepath .Base (os .Args [0 ])))
@@ -165,11 +170,22 @@ func mountWorkspace(opts mountOptions) error {
165170 if err != nil {
166171 return err
167172 }
168- cfg .Mode = modeSync
169- cfg .MountBackend = mountBackendNone
173+ mode , err := effectiveMode (cfg )
174+ if err != nil {
175+ return err
176+ }
177+ if mode == modeNone {
178+ return fmt .Errorf ("mode is set to none; update config first" )
179+ }
170180 cfg .CurrentWorkspace = opts .workspace
171181 cfg .CurrentWorkspaceID = ""
172182 cfg .LocalPath = localPath
183+ if mode == modeSync {
184+ cfg .Mode = modeSync
185+ cfg .MountBackend = mountBackendNone
186+ } else {
187+ cfg .Mode = modeMount
188+ }
173189
174190 ctx := context .Background ()
175191 resolvedCfg , service , closeStore , err := openAFSControlPlaneForConfig (ctx , cfg )
@@ -189,9 +205,80 @@ func mountWorkspace(opts mountOptions) error {
189205 resolvedCfg .CurrentWorkspace = selection .Name
190206 resolvedCfg .CurrentWorkspaceID = selection .ID
191207 resolvedCfg .LocalPath = localPath
208+ if mode == modeMount {
209+ if err := applyWorkspaceSelection (& resolvedCfg , selection ); err != nil {
210+ return err
211+ }
212+ resolvedCfg .LocalPath = localPath
213+ resolvedCfg .Mode = modeMount
214+ resolvedCfg .ReadOnly = opts .readonly
215+ return startLiveMount (resolvedCfg , selection , opts )
216+ }
192217 resolvedCfg .Mode = modeSync
193218 resolvedCfg .MountBackend = mountBackendNone
194- return startSyncMount (ctx , resolvedCfg , selection , opts )
219+ return startSyncMountForWorkspaceMount (ctx , resolvedCfg , selection , opts )
220+ }
221+
222+ func startLiveMount (cfg config , selection workspaceSelection , opts mountOptions ) error {
223+ if opts .dryRun {
224+ return fmt .Errorf ("--dry-run is only available for sync-mode mounts" )
225+ }
226+ if strings .TrimSpace (cfg .LocalPath ) == "" {
227+ return errors .New ("mount requires a local directory" )
228+ }
229+ if err := validateUpModeSelection (cfg ); err != nil {
230+ return err
231+ }
232+ st , err := startMountServicesForWorkspaceMount (cfg , opts .sessionName )
233+ if err != nil {
234+ return err
235+ }
236+ if strings .TrimSpace (st .CurrentWorkspace ) == "" {
237+ st .CurrentWorkspace = selection .Name
238+ }
239+ if strings .TrimSpace (st .CurrentWorkspaceID ) == "" {
240+ st .CurrentWorkspaceID = selection .ID
241+ }
242+ if err := registerLiveMount (st ); err != nil {
243+ _ = stopMount (mountRecordFromLiveState (st , "" ), false )
244+ return err
245+ }
246+ recordMountShellDirectory (st .LocalPath )
247+ return nil
248+ }
249+
250+ func registerLiveMount (st state ) error {
251+ reg , err := loadMountRegistry ()
252+ if err != nil {
253+ return err
254+ }
255+ id , err := randomSuffix ()
256+ if err != nil {
257+ return err
258+ }
259+ upsertMount (& reg , mountRecordFromLiveState (st , "mnt_" + id ))
260+ return saveMountRegistry (reg )
261+ }
262+
263+ func mountRecordFromLiveState (st state , id string ) mountRecord {
264+ return mountRecord {
265+ ID : id ,
266+ Workspace : st .CurrentWorkspace ,
267+ WorkspaceID : st .CurrentWorkspaceID ,
268+ LocalPath : st .LocalPath ,
269+ Mode : modeMount ,
270+ MountBackend : st .MountBackend ,
271+ ProductMode : st .ProductMode ,
272+ ControlPlaneURL : st .ControlPlaneURL ,
273+ ControlPlaneDatabase : st .ControlPlaneDatabase ,
274+ SessionID : st .SessionID ,
275+ RedisAddr : st .RedisAddr ,
276+ RedisDB : st .RedisDB ,
277+ RedisKey : st .RedisKey ,
278+ PID : st .MountPID ,
279+ ReadOnly : st .ReadOnly ,
280+ StartedAt : st .StartedAt ,
281+ }
195282}
196283
197284func startSyncMount (ctx context.Context , cfg config , selection workspaceSelection , opts mountOptions ) error {
@@ -829,6 +916,18 @@ func unmountPromptRows(records []mountRecord) [][]string {
829916}
830917
831918func stopMount (rec mountRecord , deleteLocal bool ) error {
919+ if strings .TrimSpace (rec .Mode ) == modeMount {
920+ cfg := configFromMount (rec )
921+ backend , _ , err := backendForConfig (cfg )
922+ if err != nil {
923+ return err
924+ }
925+ if localPath := strings .TrimSpace (rec .LocalPath ); localPath != "" && backend .IsMounted (localPath ) {
926+ if err := backend .Unmount (localPath ); err != nil {
927+ return err
928+ }
929+ }
930+ }
832931 if rec .PID > 0 && processAlive (rec .PID ) {
833932 if err := terminatePID (rec .PID , 5 * time .Second ); err != nil {
834933 return err
@@ -879,6 +978,9 @@ func configFromMount(rec mountRecord) config {
879978 cfg .CurrentWorkspaceID = rec .WorkspaceID
880979 cfg .LocalPath = rec .LocalPath
881980 cfg .Mode = rec .Mode
981+ if strings .TrimSpace (rec .MountBackend ) != "" {
982+ cfg .MountBackend = rec .MountBackend
983+ }
882984 cfg .SyncLog = rec .SyncLog
883985 return cfg
884986}
0 commit comments