@@ -26,6 +26,12 @@ enum class BinaryFileMode {
26
26
Skip,
27
27
};
28
28
29
+ enum class ExitStatus {
30
+ SomethingMatched = 0 ,
31
+ NoLinesMatched = 1 ,
32
+ ErrorOccurred = 2 , // NOTE: `-q` flag also silences errors.
33
+ };
34
+
29
35
template <typename ... Ts>
30
36
void fail (StringView format, Ts... args)
31
37
{
@@ -172,7 +178,7 @@ ErrorOr<int> serenity_main(Main::Arguments args)
172
178
for (auto & re : regular_expressions) {
173
179
if (re.parser_result .error != regex::Error::NoError) {
174
180
warnln (" regex parse error: {}" , regex::get_error_string (re.parser_result .error ));
175
- return 1 ;
181
+ return ExitStatus::ErrorOccurred ;
176
182
}
177
183
}
178
184
@@ -219,10 +225,10 @@ ErrorOr<int> serenity_main(Main::Arguments args)
219
225
return false ;
220
226
};
221
227
222
- bool did_match_something = false ;
228
+ auto exit_status = ExitStatus::NoLinesMatched ;
223
229
224
230
auto handle_file = [&matches, binary_mode, count_lines, quiet_mode,
225
- user_specified_multiple_files, &matched_line_count, &did_match_something ](StringView filename, bool print_filename) -> ErrorOr<void > {
231
+ user_specified_multiple_files, &matched_line_count, &exit_status ](StringView filename, bool print_filename) -> ErrorOr<void > {
226
232
auto file = TRY (Core::File::open_file_or_standard_stream (filename, Core::File::OpenMode::Read));
227
233
auto buffered_file = TRY (Core::InputBufferedFile::create (move (file)));
228
234
if (filename == ' -' )
@@ -235,9 +241,12 @@ ErrorOr<int> serenity_main(Main::Arguments args)
235
241
auto is_binary = line.contains (' \0 ' );
236
242
237
243
auto matched = matches (line, filename, line_number, print_filename, is_binary);
238
- did_match_something = did_match_something || matched;
239
- if (matched && is_binary && binary_mode == BinaryFileMode::Binary)
240
- break ;
244
+ if (matched) {
245
+ if (exit_status == ExitStatus::NoLinesMatched)
246
+ exit_status = ExitStatus::SomethingMatched;
247
+ if (is_binary && binary_mode == BinaryFileMode::Binary)
248
+ break ;
249
+ }
241
250
}
242
251
243
252
if (count_lines && !quiet_mode) {
@@ -251,15 +260,17 @@ ErrorOr<int> serenity_main(Main::Arguments args)
251
260
return {};
252
261
};
253
262
254
- auto add_directory = [&handle_file, user_has_specified_files, suppress_errors](DeprecatedString base, Optional<DeprecatedString> recursive, auto handle_directory) -> void {
263
+ auto add_directory = [&handle_file, &exit_status, user_has_specified_files, suppress_errors](DeprecatedString base, Optional<DeprecatedString> recursive, auto handle_directory) -> void {
255
264
Core::DirIterator it (recursive.value_or (base), Core::DirIterator::Flags::SkipDots);
256
265
while (it.has_next ()) {
257
266
auto path = it.next_full_path ();
258
267
if (!FileSystem::is_directory (path)) {
259
268
// Remove leading './' when `grep -r` was run without any specified paths.
260
269
auto key = user_has_specified_files ? path.view () : path.substring_view (base.length () + 1 );
261
- if (auto result = handle_file (key, true ); result.is_error () && !suppress_errors)
270
+ if (auto result = handle_file (key, true ); result.is_error () && !suppress_errors) {
262
271
warnln (" Failed with file {}: {}" , key, result.release_error ());
272
+ exit_status = ExitStatus::ErrorOccurred;
273
+ }
263
274
264
275
} else {
265
276
handle_directory (base, path, handle_directory);
@@ -283,11 +294,12 @@ ErrorOr<int> serenity_main(Main::Arguments args)
283
294
auto result = handle_file (filename, print_filename);
284
295
if (result.is_error () && !suppress_errors) {
285
296
warnln (" Failed with file {}: {}" , filename, result.release_error ());
297
+ exit_status = ExitStatus::ErrorOccurred;
286
298
}
287
299
}
288
300
}
289
301
290
- return did_match_something ? 0 : 1 ;
302
+ return exit_status ;
291
303
};
292
304
293
305
if (use_ere) {
@@ -296,13 +308,13 @@ ErrorOr<int> serenity_main(Main::Arguments args)
296
308
auto escaped_pattern = (fixed_strings) ? escape_characters (pattern, ere_special_characters) : pattern;
297
309
regular_expressions.append (Regex<PosixExtended>(escaped_pattern, options));
298
310
}
299
- return grep_logic (regular_expressions);
311
+ return to_underlying ( grep_logic (regular_expressions) );
300
312
}
301
313
302
314
Vector<Regex<PosixBasic>> regular_expressions;
303
315
for (auto pattern : patterns) {
304
316
auto escaped_pattern = (fixed_strings) ? escape_characters (pattern, basic_special_characters) : pattern;
305
317
regular_expressions.append (Regex<PosixBasic>(escaped_pattern, options));
306
318
}
307
- return grep_logic (regular_expressions);
319
+ return to_underlying ( grep_logic (regular_expressions) );
308
320
}
0 commit comments