3
3
using System . Collections . Generic ;
4
4
using System . IO ;
5
5
using System . Threading . Tasks ;
6
- using Microsoft . VisualStudio ;
7
6
using Microsoft . VisualStudio . Shell ;
8
- using Microsoft . VisualStudio . Shell . Interop ;
9
7
using Renci . SshNet ;
10
8
using SharpCompress . Common ;
11
9
using SharpCompress . Writers ;
@@ -55,12 +53,19 @@ public string Bash(string command)
55
53
/// <param name="fullScrub">Clear entire base deployment folder (TRUE) or just our project.</param>
56
54
public void CleanDeploymentFolder ( bool fullScrub = false )
57
55
{
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
+
60
61
if ( fullScrub )
61
- Bash ( $ "rm -rf { _opts . RemoteDeployBasePath } /*") ;
62
+ {
63
+ Bash ( $ "rm -rf \" { _opts . RemoteDeployBasePath } /{ filesAndFolders } \" ") ;
64
+ }
62
65
else
63
- Bash ( $ "rm -rf \" { _launch . RemoteDeployAppPath } /*\" ") ;
66
+ {
67
+ Bash ( $ "rm -rf { _launch . RemoteDeployProjectFolder } /{ filesAndFolders } ") ;
68
+ }
64
69
}
65
70
66
71
public bool Connect ( )
@@ -76,7 +81,6 @@ public bool Connect()
76
81
else
77
82
keyFile = new PrivateKeyFile ( _opts . UserPrivateKeyPath , _opts . UserPrivateKeyPassword ) ;
78
83
}
79
-
80
84
}
81
85
catch ( Exception ex )
82
86
{
@@ -177,30 +181,28 @@ public async Task<string> UploadFilesAsync()
177
181
{
178
182
try
179
183
{
180
- Bash ( $@ "mkdir -p { _launch . RemoteDeployFolder } ") ;
184
+ // Clean output folder just incase
185
+ //// Bash($@"rm -rf {_launch.RemoteDeployFolder}");
181
186
182
187
// TODO: Rev1 - Iterate through each file and upload it via SCP client or SFTP.
183
188
// TODO: Rev2 - Compress _localHost.OutputDirFullName, upload ZIP, and unzip it.
184
189
// 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")}");
186
191
187
- Bash ( $@ "mkdir -p { _launch . RemoteDeployFolder } ") ;
192
+ Bash ( $@ "mkdir -p { _launch . RemoteDeployProjectFolder } ") ;
188
193
189
194
var srcDirInfo = new DirectoryInfo ( _launch . OutputDirFullPath ) ;
190
195
if ( ! srcDirInfo . Exists )
191
196
throw new DirectoryNotFoundException ( $ "Directory '{ _launch . OutputDirFullPath } ' not found!") ;
192
197
193
198
// 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 ) ;
198
200
Logger . Output ( $ "Destination Tar.GZ: '{ destTarGz } '") ;
199
201
200
- var success = PayloadCompressAndUpload ( _sftp , srcDirInfo , destTarGz ) ;
202
+ var success = await PayloadCompressAndUploadAsync ( _sftp , srcDirInfo , destTarGz ) ;
201
203
202
204
// Decompress file
203
- PayloadDecompress ( destTarGz , false ) ;
205
+ await PayloadDecompressAsync ( destTarGz , false ) ;
204
206
205
207
return string . Empty ;
206
208
}
@@ -295,93 +297,98 @@ private ConcurrentDictionary<string, FileInfo> GetLocalFiles(DirectoryInfo srcDi
295
297
return localFileCache ;
296
298
}
297
299
298
- private void LogOutput ( string message )
299
- {
300
- Console . WriteLine ( $ ">> { message } ") ;
301
- Logger . Output ( message ) ;
302
- }
303
-
304
300
/// <summary>Compress build contents and upload to remote host.</summary>
305
301
/// <param name="sftp">SFTP connection.</param>
306
302
/// <param name="srcDirInfo">Build (source) contents directory info.</param>
307
303
/// <param name="pathBuildTarGz">Upload path and filename of build's tar.gz file.</param>
308
304
/// <returns></returns>
309
- private bool PayloadCompressAndUpload ( SftpClient sftp , DirectoryInfo srcDirInfo , string pathBuildTarGz )
305
+ private async Task < bool > PayloadCompressAndUploadAsync ( SftpClient sftp , DirectoryInfo srcDirInfo , string pathBuildTarGz )
310
306
{
311
307
var success = false ;
312
308
var localFiles = GetLocalFiles ( srcDirInfo ) ;
313
309
314
310
// TODO: Delta remote files against local files for changes.
315
311
using ( Stream tarGzStream = new MemoryStream ( ) )
316
312
{
317
- try
313
+ var outputMsg = string . Empty ;
314
+
315
+ await Task . Run ( ( ) =>
318
316
{
319
- using ( var tarGzWriter = WriterFactory . Open ( tarGzStream , ArchiveType . Tar , CompressionType . GZip ) )
317
+ try
320
318
{
321
- using ( MemoryStream fileStream = new MemoryStream ( ) )
319
+ using ( var tarGzWriter = WriterFactory . Open ( tarGzStream , ArchiveType . Tar , CompressionType . GZip ) )
322
320
{
323
- using ( BinaryWriter fileWriter = new BinaryWriter ( fileStream ) )
321
+ using ( MemoryStream fileStream = new MemoryStream ( ) )
324
322
{
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 ) )
333
324
{
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 ) ;
339
326
340
- updateFileCount ++ ;
341
- updateFileSize += file . Value . Length ;
327
+ var updateFileCount = 0 ;
328
+ long updateFileSize = 0 ;
329
+ var allFileCount = 0 ;
330
+ long allFileSize = 0 ;
342
331
343
- try
344
- {
345
- tarGzWriter . Write ( file . Key , file . Value ) ;
346
- }
347
- catch ( IOException ioEx )
332
+ foreach ( var file in localFiles )
348
333
{
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
+ }
350
355
}
351
- catch ( Exception ex )
352
- {
353
- LogOutput ( $ "Exception: { ex . Message } \n { ex . StackTrace } ") ;
354
- }
355
- }
356
356
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
+ }
358
359
}
359
360
}
361
+
362
+ success = true ;
363
+ }
364
+ catch ( Exception ex )
365
+ {
366
+ outputMsg += $ "Error while compressing file contents. { ex . Message } \n { ex . StackTrace } ";
360
367
}
368
+ } ) ;
361
369
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 ) ;
368
371
369
372
// Upload the file
370
373
if ( success )
371
374
{
372
375
try
373
376
{
374
377
var tarGzSize = tarGzStream . Length ;
375
- tarGzStream . Seek ( 0 , SeekOrigin . Begin ) ;
376
378
377
- sftp . UploadFile ( tarGzStream , pathBuildTarGz ) ;
379
+ await Task . Run ( ( ) =>
380
+ {
381
+ tarGzStream . Seek ( 0 , SeekOrigin . Begin ) ;
378
382
379
- LogOutput ( $ "Uploaded '{ _tarGzFileName } ' [{ tarGzSize , 13 : n0} bytes].") ;
383
+ sftp . UploadFile ( tarGzStream , pathBuildTarGz ) ;
384
+ } ) ;
385
+
386
+ Logger . Output ( $ "Uploaded '{ _tarGzFileName } ' [{ tarGzSize , 13 : n0} bytes].") ;
380
387
success = true ;
381
388
}
382
389
catch ( Exception ex )
383
390
{
384
- LogOutput ( $ "Error while uploading file. { ex . Message } \n { ex . StackTrace } ") ;
391
+ Logger . Output ( $ "Error while uploading file. { ex . Message } \n { ex . StackTrace } ") ;
385
392
success = false ;
386
393
}
387
394
}
@@ -394,20 +401,26 @@ private bool PayloadCompressAndUpload(SftpClient sftp, DirectoryInfo srcDirInfo,
394
401
/// <param name="pathBuildTarGz">Path to upload to.</param>
395
402
/// <param name="removeTarGz">Remove our build's tar.gz file. Set to FALSE for debugging. (default=true)</param>
396
403
/// <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 )
398
405
{
399
406
try
400
407
{
408
+ var decompressOutput = string . Empty ;
409
+
401
410
var cmd = "set -e" ;
402
- cmd += $ ";cd \" { _launch . RemoteDeployFolder } \" ";
411
+ cmd += $ ";cd \" { _launch . RemoteDeployProjectFolder } \" ";
403
412
cmd += $ ";tar -zxf \" { _tarGzFileName } \" ";
404
413
////cmd += $";tar -zxf \"{pathBuildTarGz}\"";
405
414
406
415
if ( removeTarGz )
407
416
cmd += $ ";rm \" { pathBuildTarGz } \" ";
408
417
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)") ;
411
424
412
425
return true ;
413
426
}
0 commit comments