/// <summary> /// Performs execution of the source of the script /// </summary> /// <param name="scriptSource">The source of the script to execute</param> /// <param name="directive">The execution directives to execute with</param> /// <returns>The outcome of the execution</returns> private CommandResult ExecuteScriptSource(string scriptSource, ExecutionDirective directive) { var output = new StringBuilder(); var status = CommandStatus.Success; var lines = Parser.ParseScriptLines(scriptSource, _formatter); var workingDirective = ExecutionDirective.GetDefault(); if (!directive.IsEmpty()) workingDirective.Patch(directive); _executionFaulted = false; // Execute each line foreach(var line in lines) { // Don't execute a comment line (starts with #) and don't execute if faulted if (!line.StartsWith(Constants.ScriptCommentLineIndicator) && !_executionFaulted) { // Look for directives if (line.StartsWith(Constants.ScriptDirectiveIndicator)) { // Extract directive in string var directiveString = line.Substring(1); // Parse string to get directive var currentDirective = ExecutionDirective.Parse(directiveString); if (currentDirective.IsEmpty()) _formatter.PrintLine("Unknown directive '" + directiveString + "'", output); workingDirective.Patch(currentDirective); } else { var res = Execute(line, workingDirective); if (res != null) { if (!(bool)(workingDirective.EchoOff ?? false)) { _formatter.PrintLine(res.Message, output); } if (res.Status == CommandStatus.Abort) return new CommandResult(CommandStatus.Success, res.Message); if (res.Status != CommandStatus.Success) status = CommandStatus.Failure; } else { _executionFaulted = false; return null; } } } } _executionFaulted = false; return new CommandResult(status, output.ToString()); }
/// <summary> /// Execute a script /// </summary> /// <param name="name">The name of the script to process</param> /// <param name="args">The arguments to the script</param> /// <param name="directive">Execution directives to control how execution should perform</param> /// <returns>The output from the script if the script was found, otherwise null</returns> private CommandResult ExecuteScript(string name, string[] args, ExecutionDirective directive) { try { var script = ScriptLocator.GetScript(name); if (script != null) { // Substitute script parameters for (int i = 0; i < args.Length; i++) { script = script.Replace("$" + (i + 1) + "$", args[i]); } return ExecuteScriptSource(script, directive); } } catch (MultipleScriptsFoundException ex) { var message = new StringBuilder(); foreach (var scriptName in ex.Names) { _formatter.PrintLine(scriptName, message); } message.Append("Multiple scripts found by name '"); message.Append(name); _formatter.PrintLine("'", message); message.Append("Script names must be unique"); return new CommandResult(CommandStatus.Failure, message.ToString()); } if (directive.StopOnError.HasValue && directive.StopOnError.Value) _executionFaulted = true; return null; }
/// <summary> /// Executes a command /// </summary> /// <param name="cmd">The command to execute</param> /// <param name="args">Arguments to apply to the command</param> /// <param name="directive">Directives to execute with</param> /// <returns>The outcome of the execution</returns> private CommandResult ExecuteCommand(ICommand cmd, string[] args, ExecutionDirective directive) { cmd.Initialise(_context, _formatter); CommandResult result = null; var manualParseInterface = CommandInspector.GetManualParseCommand(cmd); if (manualParseInterface != null) { var subArgs = from arg in args select Parser.PerformSubstitution(_context, arg); result = manualParseInterface.Run(subArgs.ToArray()); } else { var properties = cmd.GetType().GetProperties(); object propValue = null; var processingArgs = args; // Process multi-word named parameters first foreach (var prop in properties) { propValue = null; var namedParameterAttribute = CommandInspector.GetNamedParameter(prop); if (namedParameterAttribute != null && namedParameterAttribute.WordCount > 1) { var words = new List<string>(); for (var i = 0; i < namedParameterAttribute.WordCount; i++) { var value = string.Empty; ParameterUtil.GetParameter(args, "-" + namedParameterAttribute.Name, i, ref value); if (!string.IsNullOrEmpty(value)) words.Add(value); } if (words.Count > 0) { propValue = words.ToArray(); processingArgs = ParameterUtil.RemoveParameter(processingArgs, "-" + namedParameterAttribute.Name, namedParameterAttribute.WordCount); } } ConvertAndAssignParameter(prop, cmd, propValue); } // Find flags var flags = from prop in properties let attr = CommandInspector.GetFlagParameter(prop) where attr != null select attr.Name; // Parse remaining arguments StringDictionary named = null; string[] numbered = null; ParameterUtil.ExtractParameters(out named, out numbered, processingArgs, flags.ToArray()); // Map the parameters to properties foreach (var prop in properties) { propValue = null; var namedParameterAttribute = CommandInspector.GetNamedParameter(prop); if (namedParameterAttribute != null) { if (named.ContainsKey(namedParameterAttribute.Name)) propValue = named[namedParameterAttribute.Name]; } var numberedParameterAttribute = CommandInspector.GetNumberedParameter(prop); if (numberedParameterAttribute != null) { if (numberedParameterAttribute.Number < numbered.Length) propValue = numbered[numberedParameterAttribute.Number]; } var flagParameterAttribute = CommandInspector.GetFlagParameter(prop); if (flagParameterAttribute != null) { if (named.ContainsKey(flagParameterAttribute.Name)) { #if NET45 var origVal = (bool)prop.GetValue(cmd); #else var origVal = (bool)prop.GetValue(cmd, null); #endif propValue = !origVal; } } ConvertAndAssignParameter(prop, cmd, propValue); } AssignListParameter(cmd, properties, numbered); result = cmd.Run(); } if ((bool)(directive.StopOnError ?? false) && (result.Status == CommandStatus.Failure)) _executionFaulted = true; return result; }
/// <summary> /// Execute a command or script /// </summary> /// <param name="command">The command or script name</param> /// <param name="args">Arguments to pass to the command</param> /// <param name="directive">Execution directives to control how execution should perform</param> /// <returns>True if the command was run, otherwise returns false</returns> private CommandResult Execute(string command, string[] args, ExecutionDirective directive) { // update current date and time in environment variable Context.EnvironmentVariables["now"] = Sitecore.DateUtil.IsoNow; command = Parser.PerformSubstitution(_context, command); if (command == string.Empty) return new CommandResult(CommandStatus.Success, string.Empty); ICommand cmd = null; if (_commands.ContainsKey(command)) { cmd = (ICommand)Activator.CreateInstance(_commands[command]); } else if (_custcommands.ContainsKey(command)) { cmd = (ICommand)Activator.CreateInstance(_custcommands[command]); } else if(_commandAliases.ContainsKey(command) && _commands.ContainsKey(_commandAliases[command].CommandName)) { var alias = _commandAliases[command]; cmd = (ICommand)Activator.CreateInstance(_commands[alias.CommandName]); if(alias.Parameters != null && alias.Parameters.Length > 0) { var paramsList = new List<string>(alias.Parameters); paramsList.AddRange(args); args = paramsList.ToArray(); } } if (cmd != null) { return ExecuteCommand(cmd, args, directive); } else return ExecuteScript(command, args, directive); }
/// <summary> /// Executes a command /// </summary> /// <param name="elements">The elements forming the command and arguments</param> /// <param name="directive">Execution directives to control how execution should perform</param> private CommandResult Execute(string[] elements, ExecutionDirective directive) { EnsureValidContextItem(); // Check if we have any subcommands var ind = Array.IndexOf(elements, Constants.SubcommandSymbol); while (ind >= 0) { var innerOutput = string.Empty; if (elements.Length >= (ind + 2)) { var subelements = Parser.ParseInputLine(elements[ind + 1]); var innerResult = Execute(subelements, directive); if (innerResult.Status != CommandStatus.Success) return new CommandResult(innerResult.Status, "Subcommand failure: " + innerResult.Message); innerOutput = innerResult.Message; elements = elements.Take(ind).Concat(new[] { innerOutput }).Concat(elements.Skip(ind + 2)).ToArray(); } ind = Array.IndexOf(elements, Constants.SubcommandSymbol); } // Check if we have any forwarding sub commands ind = Array.IndexOf(elements, Constants.CommandChainSymbol); while (ind >= 0) { var subelements = elements.Take(ind); var innerResult = Execute(subelements.ToArray(), directive); if (innerResult.Status != CommandStatus.Success) return new CommandResult(innerResult.Status, "Subcommand failure: " + innerResult.Message); _context.EnvironmentVariables[Constants.CommandChainedValue] = innerResult.Message; elements = elements.Skip(ind + 1).ToArray(); ind = Array.IndexOf(elements, Constants.CommandChainSymbol); } if (elements.Length > 0) { for (var i = 0; i < elements.Length; i++) { if (elements[i].Contains(Constants.EscapedSubcommandSymbol)) elements[i] = elements[i].Replace(Constants.EscapedSubcommandSymbol, Constants.SubcommandSymbol); if (elements[i].Contains(Constants.EscapedCommandChainSymbol)) elements[i] = elements[i].Replace(Constants.EscapedCommandChainSymbol, Constants.CommandChainSymbol); } var args = elements.Skip(1).ToArray(); var result = Execute(elements[0].Trim(), args, directive); if (result != null) return result; if (directive.IgnoreUnknownCommands == null || !directive.IgnoreUnknownCommands.Value) return new CommandResult(CommandStatus.Failure, "Unknown command or script name " + elements[0].Trim()); } return new CommandResult(CommandStatus.Success, string.Empty); }
/// <summary> /// Execute a single command line /// </summary> /// <param name="commandLine">The command line to execute</param> /// <param name="directive">Execution directives to control how execution should perform</param> /// <returns>String output from the execution</returns> public CommandResult Execute(string commandLine, ExecutionDirective directive) { var elements = Parser.ParseInputLine(commandLine); // Dispatch the command to the core command handler var result = Execute(elements, directive); return new CommandResult(result.Status, result.Message); }