@@ -153,6 +153,90 @@ public static async Task<bool> LaunchGame(string gameName)
153153 return await SshCommand ( cmd ) ;
154154 }
155155
156+ public static async Task < bool > Push (
157+ string localPath ,
158+ string remotePath ,
159+ string extraArgs = null
160+ )
161+ {
162+ var settings = SteamDeckDeploySettings . Instance ;
163+ if ( ! settings . Validate ( out var error ) )
164+ {
165+ Debug . LogError ( $ "{ Tag } { error } ") ;
166+ return false ;
167+ }
168+
169+ var sshCmd = $ "ssh -i \" { settings . ResolvedSshKeyPath } \" -o StrictHostKeyChecking=accept-new";
170+ var remote = $ "{ settings . username } @{ settings . ipAddress } :{ remotePath } /";
171+
172+ var args = $ "-avz { extraArgs ?? "" } -e \" { sshCmd } \" \" { localPath } /\" \" { remote } \" ". Trim ( ) ;
173+
174+ Debug . Log ( $ "{ Tag } push → { settings . ipAddress } :{ remotePath } ") ;
175+ var result = await ProcessRunner . RunAsync ( "rsync" , args ) ;
176+
177+ if ( ! result . Success )
178+ Debug . LogError ( $ "{ Tag } push failed (exit { result . ExitCode } ):\n { result . Error } ") ;
179+
180+ return result . Success ;
181+ }
182+
183+ public static async Task < bool > Pull (
184+ string remotePath ,
185+ string localPath ,
186+ string extraArgs = null
187+ )
188+ {
189+ var settings = SteamDeckDeploySettings . Instance ;
190+ if ( ! settings . Validate ( out var error ) )
191+ {
192+ Debug . LogError ( $ "{ Tag } { error } ") ;
193+ return false ;
194+ }
195+
196+ var sshCmd = $ "ssh -i \" { settings . ResolvedSshKeyPath } \" -o StrictHostKeyChecking=accept-new";
197+ var remote = $ "{ settings . username } @{ settings . ipAddress } :{ remotePath } /";
198+
199+ Directory . CreateDirectory ( localPath ) ;
200+
201+ var args = $ "-avz { extraArgs ?? "" } -e \" { sshCmd } \" \" { remote } \" \" { localPath } /\" ". Trim ( ) ;
202+
203+ Debug . Log ( $ "{ Tag } pull ← { settings . ipAddress } :{ remotePath } ") ;
204+ var result = await ProcessRunner . RunAsync ( "rsync" , args ) ;
205+
206+ if ( ! result . Success )
207+ Debug . LogError ( $ "{ Tag } pull failed (exit { result . ExitCode } ):\n { result . Error } ") ;
208+
209+ return result . Success ;
210+ }
211+
212+ public static async Task < ( bool success , string output ) > Ssh ( string command , int timeoutMs = 30_000 )
213+ {
214+ var settings = SteamDeckDeploySettings . Instance ;
215+ if ( ! settings . Validate ( out var error ) )
216+ {
217+ Debug . LogError ( $ "{ Tag } { error } ") ;
218+ return ( false , error ) ;
219+ }
220+
221+ var result = await ProcessRunner . RunAsync (
222+ "ssh" ,
223+ new [ ]
224+ {
225+ "-i" , settings . ResolvedSshKeyPath ,
226+ "-o" , "StrictHostKeyChecking=accept-new" ,
227+ "-o" , "ConnectTimeout=10" ,
228+ $ "{ settings . username } @{ settings . ipAddress } ",
229+ command ,
230+ } ,
231+ timeoutMs
232+ ) ;
233+
234+ if ( ! result . Success )
235+ Debug . LogError ( $ "{ Tag } SSH failed (exit { result . ExitCode } ):\n { result . Error } ") ;
236+
237+ return ( result . Success , result . Output ) ;
238+ }
239+
156240 static async Task < bool > UploadScripts ( )
157241 {
158242 // Find Scripts~ directory relative to the package
0 commit comments