33using System . Collections . Generic ;
44using System . IO ;
55using System . Threading . Tasks ;
6- using Microsoft . VisualStudio ;
76using Microsoft . VisualStudio . Shell ;
8- using Microsoft . VisualStudio . Shell . Interop ;
97using Renci . SshNet ;
108using SharpCompress . Common ;
119using SharpCompress . Writers ;
@@ -55,12 +53,19 @@ public string Bash(string command)
5553 /// <param name="fullScrub">Clear entire base deployment folder (TRUE) or just our project.</param>
5654 public void CleanDeploymentFolder ( bool fullScrub = false )
5755 {
58- //// Bash($"sudo rm -rf {_opts.RemoteDeployBasePath}/*");
59-
56+ // Whole deployment folder and hidden files
57+ // rm -rf xxx/* == Contents of the folder but not the folder itself
58+ // rm -rf xxx/{*,.*} == All hidden files and folders
59+ var filesAndFolders = "{*,.*}" ;
60+
6061 if ( fullScrub )
61- Bash ( $ "rm -rf { _opts . RemoteDeployBasePath } /*") ;
62+ {
63+ Bash ( $ "rm -rf \" { _opts . RemoteDeployBasePath } /{ filesAndFolders } \" ") ;
64+ }
6265 else
63- Bash ( $ "rm -rf \" { _launch . RemoteDeployAppPath } /*\" ") ;
66+ {
67+ Bash ( $ "rm -rf { _launch . RemoteDeployProjectFolder } /{ filesAndFolders } ") ;
68+ }
6469 }
6570
6671 public bool Connect ( )
@@ -76,7 +81,6 @@ public bool Connect()
7681 else
7782 keyFile = new PrivateKeyFile ( _opts . UserPrivateKeyPath , _opts . UserPrivateKeyPassword ) ;
7883 }
79-
8084 }
8185 catch ( Exception ex )
8286 {
@@ -177,30 +181,28 @@ public async Task<string> UploadFilesAsync()
177181 {
178182 try
179183 {
180- Bash ( $@ "mkdir -p { _launch . RemoteDeployFolder } ") ;
184+ // Clean output folder just incase
185+ //// Bash($@"rm -rf {_launch.RemoteDeployFolder}");
181186
182187 // TODO: Rev1 - Iterate through each file and upload it via SCP client or SFTP.
183188 // TODO: Rev2 - Compress _localHost.OutputDirFullName, upload ZIP, and unzip it.
184189 // TODO: Rev3 - Allow for both SFTP and SCP as a backup. This separating connection to a new disposable class.
185- //// LogOutput ($"Connected to {_connectionInfo.Username}@{_connectionInfo.Host}:{_connectionInfo.Port} via SSH and {(_sftpClient != null ? "SFTP" : "SCP")}");
190+ //// Logger.Output ($"Connected to {_connectionInfo.Username}@{_connectionInfo.Host}:{_connectionInfo.Port} via SSH and {(_sftpClient != null ? "SFTP" : "SCP")}");
186191
187- Bash ( $@ "mkdir -p { _launch . RemoteDeployFolder } ") ;
192+ Bash ( $@ "mkdir -p { _launch . RemoteDeployProjectFolder } ") ;
188193
189194 var srcDirInfo = new DirectoryInfo ( _launch . OutputDirFullPath ) ;
190195 if ( ! srcDirInfo . Exists )
191196 throw new DirectoryNotFoundException ( $ "Directory '{ _launch . OutputDirFullPath } ' not found!") ;
192197
193198 // Compress files to upload as single `tar.gz`.
194- // TODO: Use base folder path: var pathTarGz = $"{_opts.RemoteDeployBasePath}/{_tarGzFileName}";
195-
196- //// var destTarGz = $"{RemoteDeployPath}/{_tarGzFileName}";
197- var destTarGz = LinuxPath . Combine ( _launch . RemoteDeployFolder , _tarGzFileName ) ;
199+ var destTarGz = LinuxPath . Combine ( _launch . RemoteDeployProjectFolder , _tarGzFileName ) ;
198200 Logger . Output ( $ "Destination Tar.GZ: '{ destTarGz } '") ;
199201
200- var success = PayloadCompressAndUpload ( _sftp , srcDirInfo , destTarGz ) ;
202+ var success = await PayloadCompressAndUploadAsync ( _sftp , srcDirInfo , destTarGz ) ;
201203
202204 // Decompress file
203- PayloadDecompress ( destTarGz , false ) ;
205+ await PayloadDecompressAsync ( destTarGz , false ) ;
204206
205207 return string . Empty ;
206208 }
@@ -295,93 +297,98 @@ private ConcurrentDictionary<string, FileInfo> GetLocalFiles(DirectoryInfo srcDi
295297 return localFileCache ;
296298 }
297299
298- private void LogOutput ( string message )
299- {
300- Console . WriteLine ( $ ">> { message } ") ;
301- Logger . Output ( message ) ;
302- }
303-
304300 /// <summary>Compress build contents and upload to remote host.</summary>
305301 /// <param name="sftp">SFTP connection.</param>
306302 /// <param name="srcDirInfo">Build (source) contents directory info.</param>
307303 /// <param name="pathBuildTarGz">Upload path and filename of build's tar.gz file.</param>
308304 /// <returns></returns>
309- private bool PayloadCompressAndUpload ( SftpClient sftp , DirectoryInfo srcDirInfo , string pathBuildTarGz )
305+ private async Task < bool > PayloadCompressAndUploadAsync ( SftpClient sftp , DirectoryInfo srcDirInfo , string pathBuildTarGz )
310306 {
311307 var success = false ;
312308 var localFiles = GetLocalFiles ( srcDirInfo ) ;
313309
314310 // TODO: Delta remote files against local files for changes.
315311 using ( Stream tarGzStream = new MemoryStream ( ) )
316312 {
317- try
313+ var outputMsg = string . Empty ;
314+
315+ await Task . Run ( ( ) =>
318316 {
319- using ( var tarGzWriter = WriterFactory . Open ( tarGzStream , ArchiveType . Tar , CompressionType . GZip ) )
317+ try
320318 {
321- using ( MemoryStream fileStream = new MemoryStream ( ) )
319+ using ( var tarGzWriter = WriterFactory . Open ( tarGzStream , ArchiveType . Tar , CompressionType . GZip ) )
322320 {
323- using ( BinaryWriter fileWriter = new BinaryWriter ( fileStream ) )
321+ using ( MemoryStream fileStream = new MemoryStream ( ) )
324322 {
325- fileWriter . Write ( localFiles . Count ) ;
326-
327- var updateFileCount = 0 ;
328- long updateFileSize = 0 ;
329- var allFileCount = 0 ;
330- long allFileSize = 0 ;
331-
332- foreach ( var file in localFiles )
323+ using ( BinaryWriter fileWriter = new BinaryWriter ( fileStream ) )
333324 {
334- allFileCount ++ ;
335- allFileSize += file . Value . Length ;
336-
337- // TODO: Add new cache file entry
338- //// UpdateCacheEntry.WriteToStream(newCacheFileWriter, file.Key, file.Value);
325+ fileWriter . Write ( localFiles . Count ) ;
339326
340- updateFileCount ++ ;
341- updateFileSize += file . Value . Length ;
327+ var updateFileCount = 0 ;
328+ long updateFileSize = 0 ;
329+ var allFileCount = 0 ;
330+ long allFileSize = 0 ;
342331
343- try
344- {
345- tarGzWriter . Write ( file . Key , file . Value ) ;
346- }
347- catch ( IOException ioEx )
332+ foreach ( var file in localFiles )
348333 {
349- LogOutput ( $ "Exception: { ioEx . Message } ") ;
334+ allFileCount ++ ;
335+ allFileSize += file . Value . Length ;
336+
337+ // TODO: Add new cache file entry
338+ //// UpdateCacheEntry.WriteToStream(newCacheFileWriter, file.Key, file.Value);
339+
340+ updateFileCount ++ ;
341+ updateFileSize += file . Value . Length ;
342+
343+ try
344+ {
345+ tarGzWriter . Write ( file . Key , file . Value ) ;
346+ }
347+ catch ( IOException ioEx )
348+ {
349+ outputMsg += $ "Exception: { ioEx . Message } { Environment . NewLine } ";
350+ }
351+ catch ( Exception ex )
352+ {
353+ outputMsg += $ "Exception: { ex . Message } { Environment . NewLine } { ex . StackTrace } { Environment . NewLine } ";
354+ }
350355 }
351- catch ( Exception ex )
352- {
353- LogOutput ( $ "Exception: { ex . Message } \n { ex . StackTrace } ") ;
354- }
355- }
356356
357- LogOutput ( $ "{ updateFileCount , 7 : n0} [{ updateFileSize , 13 : n0} bytes] of { allFileCount , 7 : n0} [{ allFileSize , 13 : n0} bytes] files need to be updated") ;
357+ outputMsg += $ "Update file count: { updateFileCount } ; File Size: [{ updateFileSize } bytes] of Total Files: { allFileCount } [{ allFileSize } bytes] need to be updated";
358+ }
358359 }
359360 }
361+
362+ success = true ;
363+ }
364+ catch ( Exception ex )
365+ {
366+ outputMsg += $ "Error while compressing file contents. { ex . Message } \n { ex . StackTrace } ";
360367 }
368+ } ) ;
361369
362- success = true ;
363- }
364- catch ( Exception ex )
365- {
366- LogOutput ( $ "Error while compressing file contents. { ex . Message } \n { ex . StackTrace } ") ;
367- }
370+ Logger . Output ( outputMsg ) ;
368371
369372 // Upload the file
370373 if ( success )
371374 {
372375 try
373376 {
374377 var tarGzSize = tarGzStream . Length ;
375- tarGzStream . Seek ( 0 , SeekOrigin . Begin ) ;
376378
377- sftp . UploadFile ( tarGzStream , pathBuildTarGz ) ;
379+ await Task . Run ( ( ) =>
380+ {
381+ tarGzStream . Seek ( 0 , SeekOrigin . Begin ) ;
378382
379- LogOutput ( $ "Uploaded '{ _tarGzFileName } ' [{ tarGzSize , 13 : n0} bytes].") ;
383+ sftp . UploadFile ( tarGzStream , pathBuildTarGz ) ;
384+ } ) ;
385+
386+ Logger . Output ( $ "Uploaded '{ _tarGzFileName } ' [{ tarGzSize , 13 : n0} bytes].") ;
380387 success = true ;
381388 }
382389 catch ( Exception ex )
383390 {
384- LogOutput ( $ "Error while uploading file. { ex . Message } \n { ex . StackTrace } ") ;
391+ Logger . Output ( $ "Error while uploading file. { ex . Message } \n { ex . StackTrace } ") ;
385392 success = false ;
386393 }
387394 }
@@ -394,20 +401,26 @@ private bool PayloadCompressAndUpload(SftpClient sftp, DirectoryInfo srcDirInfo,
394401 /// <param name="pathBuildTarGz">Path to upload to.</param>
395402 /// <param name="removeTarGz">Remove our build's tar.gz file. Set to FALSE for debugging. (default=true)</param>
396403 /// <returns>Returns true on success.</returns>
397- private bool PayloadDecompress ( string pathBuildTarGz , bool removeTarGz = true )
404+ private async Task < bool > PayloadDecompressAsync ( string pathBuildTarGz , bool removeTarGz = true )
398405 {
399406 try
400407 {
408+ var decompressOutput = string . Empty ;
409+
401410 var cmd = "set -e" ;
402- cmd += $ ";cd \" { _launch . RemoteDeployFolder } \" ";
411+ cmd += $ ";cd \" { _launch . RemoteDeployProjectFolder } \" ";
403412 cmd += $ ";tar -zxf \" { _tarGzFileName } \" ";
404413 ////cmd += $";tar -zxf \"{pathBuildTarGz}\"";
405414
406415 if ( removeTarGz )
407416 cmd += $ ";rm \" { pathBuildTarGz } \" ";
408417
409- var output = Bash ( cmd ) ;
410- LogOutput ( output ) ;
418+ await Task . Run ( ( ) =>
419+ {
420+ decompressOutput = Bash ( cmd ) ;
421+ } ) ;
422+
423+ Logger . Output ( $ "Payload Decompress results: '{ decompressOutput } ' (blank=OK)") ;
411424
412425 return true ;
413426 }
0 commit comments