@@ -74,60 +74,71 @@ public async Task<int> InvokeAsync(InvocationContext context)
74
74
{
75
75
CancellationToken cancellationToken = context . GetCancellationToken ( ) ;
76
76
77
- var configuredOptions = _configuration . Get < DataTransferOptions > ( ) ?? new DataTransferOptions ( ) ;
78
- var combinedConfig = BuildSettingsConfiguration ( _configuration ,
79
- Settings ? . FullName ?? configuredOptions . SettingsPath ,
80
- string . IsNullOrEmpty ( Source ?? configuredOptions . Source ) && string . IsNullOrEmpty ( Sink ?? configuredOptions . Sink ) ,
81
- cancellationToken ) ;
77
+ try
78
+ {
79
+ var configuredOptions = _configuration . Get < DataTransferOptions > ( ) ?? new DataTransferOptions ( ) ;
80
+ var combinedConfig = await BuildSettingsConfiguration ( _configuration ,
81
+ Settings ? . FullName ?? configuredOptions . SettingsPath ,
82
+ string . IsNullOrEmpty ( Source ?? configuredOptions . Source ) && string . IsNullOrEmpty ( Sink ?? configuredOptions . Sink ) ,
83
+ cancellationToken ) ;
82
84
83
- var options = combinedConfig . Get < DataTransferOptions > ( ) ;
85
+ var options = combinedConfig . Get < DataTransferOptions > ( ) ;
84
86
85
- string extensionsPath = _extensionLoader . GetExtensionFolderPath ( ) ;
86
- CompositionContainer container = _extensionLoader . BuildExtensionCatalog ( extensionsPath ) ;
87
+ string extensionsPath = _extensionLoader . GetExtensionFolderPath ( ) ;
88
+ CompositionContainer container = _extensionLoader . BuildExtensionCatalog ( extensionsPath ) ;
87
89
88
- var sources = _extensionLoader . LoadExtensions < IDataSourceExtension > ( container ) ;
89
- var sinks = _extensionLoader . LoadExtensions < IDataSinkExtension > ( container ) ;
90
+ var sources = _extensionLoader . LoadExtensions < IDataSourceExtension > ( container ) ;
91
+ var sinks = _extensionLoader . LoadExtensions < IDataSinkExtension > ( container ) ;
90
92
91
- cancellationToken . ThrowIfCancellationRequested ( ) ;
93
+ cancellationToken . ThrowIfCancellationRequested ( ) ;
92
94
93
- var source = GetExtensionSelection ( Source ?? options . Source , sources , "Source" , cancellationToken ) ;
94
- cancellationToken . ThrowIfCancellationRequested ( ) ;
95
- var sink = GetExtensionSelection ( Sink ?? options . Sink , sinks , "Sink" , cancellationToken ) ;
96
- cancellationToken . ThrowIfCancellationRequested ( ) ;
95
+ var source = await GetExtensionSelection ( Source ?? options . Source , sources , "Source" , cancellationToken ) ;
96
+ cancellationToken . ThrowIfCancellationRequested ( ) ;
97
+ var sink = await GetExtensionSelection ( Sink ?? options . Sink , sinks , "Sink" , cancellationToken ) ;
98
+ cancellationToken . ThrowIfCancellationRequested ( ) ;
97
99
98
- var sourceConfig = combinedConfig . GetSection ( "SourceSettings" ) ;
99
- var sinkConfig = GetSinkConfig ( combinedConfig ) ;
100
- var operationConfigs = combinedConfig . GetSection ( "Operations" ) ;
101
- var operations = operationConfigs ? . GetChildren ( ) . ToList ( ) ;
102
- if ( operations ? . Any ( ) == true )
103
- {
104
- foreach ( var operationConfig in operations )
100
+ var sourceConfig = combinedConfig . GetSection ( "SourceSettings" ) ;
101
+ var sinkConfig = GetSinkConfig ( combinedConfig ) ;
102
+ var operationConfigs = combinedConfig . GetSection ( "Operations" ) ;
103
+ var operations = operationConfigs ? . GetChildren ( ) . ToList ( ) ;
104
+ bool succeeded = true ;
105
+ if ( operations ? . Any ( ) == true )
105
106
{
106
- var operationSource = operationConfig . GetSection ( "SourceSettings" ) ;
107
- var sourceBuilder = new ConfigurationBuilder ( ) . AddConfiguration ( sourceConfig ) ;
108
- if ( operationSource . Exists ( ) )
109
- {
110
- sourceBuilder . AddConfiguration ( operationSource ) ;
111
- }
112
- var operationSink = GetSinkConfig ( operationConfig ) ;
113
- var sinkBuilder = new ConfigurationBuilder ( ) . AddConfiguration ( sinkConfig ) ;
114
- if ( operationSink . Exists ( ) )
107
+ foreach ( var operationConfig in operations )
115
108
{
116
- sinkBuilder . AddConfiguration ( operationSink ) ;
109
+ var operationSource = operationConfig . GetSection ( "SourceSettings" ) ;
110
+ var sourceBuilder = new ConfigurationBuilder ( ) . AddConfiguration ( sourceConfig ) ;
111
+ if ( operationSource . Exists ( ) )
112
+ {
113
+ sourceBuilder . AddConfiguration ( operationSource ) ;
114
+ }
115
+ var operationSink = GetSinkConfig ( operationConfig ) ;
116
+ var sinkBuilder = new ConfigurationBuilder ( ) . AddConfiguration ( sinkConfig ) ;
117
+ if ( operationSink . Exists ( ) )
118
+ {
119
+ sinkBuilder . AddConfiguration ( operationSink ) ;
120
+ }
121
+ succeeded &= await ExecuteDataTransferOperation ( source ,
122
+ sourceBuilder . Build ( ) ,
123
+ sink ,
124
+ sinkBuilder . Build ( ) ,
125
+ cancellationToken ) ;
117
126
}
118
- await ExecuteDataTransferOperation ( source ,
119
- sourceBuilder . Build ( ) ,
120
- sink ,
121
- sinkBuilder . Build ( ) ,
122
- cancellationToken ) ;
123
127
}
128
+ else
129
+ {
130
+ succeeded = await ExecuteDataTransferOperation ( source , sourceConfig , sink , sinkConfig , cancellationToken ) ;
131
+ }
132
+
133
+ return succeeded ? 0 : 1 ;
124
134
}
125
- else
135
+ catch ( OperationCanceledException ex )
126
136
{
127
- await ExecuteDataTransferOperation ( source , sourceConfig , sink , sinkConfig , cancellationToken ) ;
137
+ _logger . LogDebug ( ex , "Operation canceled." ) ;
138
+ Console . WriteLine ( ) ;
139
+ Console . WriteLine ( "Operation canceled. Exiting." ) ;
140
+ return 1 ;
128
141
}
129
-
130
- return 0 ;
131
142
}
132
143
133
144
private static IConfigurationSection GetSinkConfig ( IConfiguration combinedConfig )
@@ -148,7 +159,7 @@ private static IConfigurationSection GetSinkConfig(IConfiguration combinedConfig
148
159
return config ;
149
160
}
150
161
151
- private async Task ExecuteDataTransferOperation ( IDataSourceExtension source , IConfiguration sourceConfig , IDataSinkExtension sink , IConfiguration sinkConfig , CancellationToken cancellationToken )
162
+ private async Task < bool > ExecuteDataTransferOperation ( IDataSourceExtension source , IConfiguration sourceConfig , IDataSinkExtension sink , IConfiguration sinkConfig , CancellationToken cancellationToken )
152
163
{
153
164
_logger . LogDebug ( "Loaded {SettingCount} settings for source {SourceName}:\n \t \t {SettingList}" ,
154
165
sourceConfig . AsEnumerable ( ) . Count ( ) ,
@@ -168,19 +179,21 @@ private async Task ExecuteDataTransferOperation(IDataSourceExtension source, ICo
168
179
await sink . WriteAsync ( data , sinkConfig , source , _loggerFactory . CreateLogger ( sink . GetType ( ) . Name ) , cancellationToken ) ;
169
180
170
181
_logger . LogInformation ( "Data transfer complete" ) ;
182
+ return true ;
171
183
}
172
184
catch ( Exception ex )
173
185
{
174
186
_logger . LogError ( ex , "Data transfer failed" ) ;
187
+ return false ;
175
188
}
176
189
}
177
190
178
- private static T GetExtensionSelection < T > ( string ? selectionName , List < T > extensions , string inputPrompt , CancellationToken cancellationToken )
191
+ private static async Task < T > GetExtensionSelection < T > ( string ? selectionName , List < T > extensions , string inputPrompt , CancellationToken cancellationToken )
179
192
where T : class , IDataTransferExtension
180
193
{
181
194
if ( ! string . IsNullOrWhiteSpace ( selectionName ) )
182
195
{
183
- var extension = extensions . FirstOrDefault ( s => selectionName . Equals ( s . DisplayName , StringComparison . OrdinalIgnoreCase ) ) ;
196
+ var extension = extensions . FirstOrDefault ( s => s . MatchesExtensionSelection ( selectionName ) ) ;
184
197
if ( extension != null )
185
198
{
186
199
Console . WriteLine ( $ "Using { extension . DisplayName } { inputPrompt } ") ;
@@ -197,18 +210,18 @@ private static T GetExtensionSelection<T>(string? selectionName, List<T> extensi
197
210
198
211
string ? selection = "" ;
199
212
int input ;
200
- while ( ! int . TryParse ( selection , out input ) || input > extensions . Count )
213
+ while ( ! int . TryParse ( selection , out input ) || input > extensions . Count || input <= 0 )
201
214
{
202
215
cancellationToken . ThrowIfCancellationRequested ( ) ;
203
- selection = Console . ReadLine ( ) ;
216
+ selection = await Console . In . ReadLineAsync ( cancellationToken ) ;
204
217
}
205
218
206
219
T selected = extensions [ input - 1 ] ;
207
220
Console . WriteLine ( $ "Using { selected . DisplayName } { inputPrompt } ") ;
208
221
return selected ;
209
222
}
210
223
211
- private IConfiguration BuildSettingsConfiguration ( IConfiguration configuration , string ? settingsPath , bool promptForFile , CancellationToken cancellationToken )
224
+ private async Task < IConfiguration > BuildSettingsConfiguration ( IConfiguration configuration , string ? settingsPath , bool promptForFile , CancellationToken cancellationToken )
212
225
{
213
226
IConfigurationBuilder configurationBuilder = new ConfigurationBuilder ( ) ;
214
227
if ( ! string . IsNullOrEmpty ( settingsPath ) && File . Exists ( settingsPath ) )
@@ -220,7 +233,7 @@ private IConfiguration BuildSettingsConfiguration(IConfiguration configuration,
220
233
else if ( promptForFile )
221
234
{
222
235
Console . Write ( "Path to settings file? (leave empty to skip): " ) ;
223
- var path = Console . ReadLine ( ) ;
236
+ var path = await Console . In . ReadLineAsync ( cancellationToken ) ;
224
237
cancellationToken . ThrowIfCancellationRequested ( ) ;
225
238
if ( ! string . IsNullOrWhiteSpace ( path ) )
226
239
{
@@ -234,16 +247,6 @@ private IConfiguration BuildSettingsConfiguration(IConfiguration configuration,
234
247
. AddConfiguration ( configuration )
235
248
. Build ( ) ;
236
249
}
237
-
238
- private static bool IsYesResponse ( string ? response )
239
- {
240
- if ( response ? . Equals ( "y" , StringComparison . CurrentCultureIgnoreCase ) == true )
241
- return true ;
242
- if ( response ? . Equals ( "yes" , StringComparison . CurrentCultureIgnoreCase ) == true )
243
- return true ;
244
-
245
- return false ;
246
- }
247
250
}
248
251
}
249
252
}
0 commit comments