/ src / modules / imageresizer / ui / Cli / ImageResizerCliExecutor.cs
ImageResizerCliExecutor.cs
  1  // Copyright (c) Microsoft Corporation
  2  // The Microsoft Corporation licenses this file to you under the MIT license.
  3  // See the LICENSE file in the project root for more information.
  4  
  5  using System;
  6  using System.Globalization;
  7  using System.Linq;
  8  using System.Threading;
  9  
 10  using ImageResizer.Models;
 11  using ImageResizer.Properties;
 12  
 13  namespace ImageResizer.Cli
 14  {
 15      /// <summary>
 16      /// Executes Image Resizer CLI operations.
 17      /// Instance-based design for better testability and Single Responsibility Principle.
 18      /// </summary>
 19      public class ImageResizerCliExecutor
 20      {
 21          /// <summary>
 22          /// Runs the CLI executor with the provided command-line arguments.
 23          /// </summary>
 24          /// <param name="args">Command-line arguments.</param>
 25          /// <returns>Exit code.</returns>
 26          public int Run(string[] args)
 27          {
 28              var cliOptions = CliOptions.Parse(args);
 29  
 30              if (cliOptions.ParseErrors.Count > 0)
 31              {
 32                  foreach (var error in cliOptions.ParseErrors)
 33                  {
 34                      Console.Error.WriteLine(error);
 35                      CliLogger.Error($"Parse error: {error}");
 36                  }
 37  
 38                  CliOptions.PrintUsage();
 39                  return 1;
 40              }
 41  
 42              if (cliOptions.ShowHelp)
 43              {
 44                  CliOptions.PrintUsage();
 45                  return 0;
 46              }
 47  
 48              if (cliOptions.ShowConfig)
 49              {
 50                  CliOptions.PrintConfig(Settings.Default);
 51                  return 0;
 52              }
 53  
 54              if (cliOptions.Files.Count == 0 && string.IsNullOrEmpty(cliOptions.PipeName))
 55              {
 56                  Console.WriteLine(Resources.CLI_NoInputFiles);
 57                  CliOptions.PrintUsage();
 58                  return 1;
 59              }
 60  
 61              return RunSilentMode(cliOptions);
 62          }
 63  
 64          private int RunSilentMode(CliOptions cliOptions)
 65          {
 66              var batch = ResizeBatch.FromCliOptions(Console.In, cliOptions);
 67              var settings = Settings.Default;
 68              CliSettingsApplier.Apply(cliOptions, settings);
 69  
 70              CliLogger.Info($"CLI mode: processing {batch.Files.Count} files");
 71  
 72              // Use accessible line-based progress if requested or detected
 73              bool useLineBasedProgress = cliOptions.ProgressLines ?? false;
 74              int lastReportedMilestone = -1;
 75  
 76              var errors = batch.Process(
 77                  (completed, total) =>
 78                  {
 79                      var progress = (int)((completed / total) * 100);
 80  
 81                      if (useLineBasedProgress)
 82                      {
 83                          // Milestone-based progress (0%, 25%, 50%, 75%, 100%)
 84                          int milestone = (progress / 25) * 25;
 85                          if (milestone > lastReportedMilestone || completed == (int)total)
 86                          {
 87                              lastReportedMilestone = milestone;
 88                              Console.WriteLine(string.Format(CultureInfo.InvariantCulture, Resources.CLI_ProgressFormat, progress, completed, (int)total));
 89                          }
 90                      }
 91                      else
 92                      {
 93                          // Traditional carriage return mode
 94                          Console.Write(string.Format(CultureInfo.InvariantCulture, "\r{0}", string.Format(CultureInfo.InvariantCulture, Resources.CLI_ProgressFormat, progress, completed, (int)total)));
 95                      }
 96                  },
 97                  settings,
 98                  CancellationToken.None);
 99  
100              if (!useLineBasedProgress)
101              {
102                  Console.WriteLine();
103              }
104  
105              var errorList = errors.ToList();
106              if (errorList.Count > 0)
107              {
108                  Console.Error.WriteLine(string.Format(CultureInfo.InvariantCulture, Resources.CLI_CompletedWithErrors, errorList.Count));
109                  CliLogger.Error($"Processing completed with {errorList.Count} error(s)");
110                  foreach (var error in errorList)
111                  {
112                      Console.Error.WriteLine(string.Format(CultureInfo.InvariantCulture, "  {0}: {1}", error.File, error.Error));
113                      CliLogger.Error($"  {error.File}: {error.Error}");
114                  }
115  
116                  return 1;
117              }
118  
119              CliLogger.Info("CLI batch completed successfully");
120              Console.WriteLine(Resources.CLI_AllFilesProcessed);
121              return 0;
122          }
123      }
124  }