/// <summary>
 /// Escape a URI so that it can be passed to Gradle.
 /// </summary>
 /// <param name="uri">URI to escape.</param>
 /// <returns>Escaped URI.</returns>
 public static string EscapeUri(string uri)
 {
     // Escape the URI to handle special characters like spaces and percent escape
     // all characters that are interpreted by gradle.
     return(GradleWrapper.EscapeGradlePropertyValue(
                Uri.EscapeUriString(uri), escapeFunc: Uri.EscapeDataString,
                charactersToExclude: GradleUriExcludeEscapeCharacters));
 }
        /// <summary>
        /// Prepare Gradle for execution and call a closure with the command line parameters to
        /// execute the wrapper.
        /// </summary>
        /// <param name="useGradleDaemon">Whether to use the Gradle daemon.</param>
        /// <param name="buildScript">Path to the Gradle build script to use.</param>
        /// <param name="projectProperties">Project properties to use when running the script.
        /// </param>
        /// <param name="arguments>Other arguments to pass to Gradle.</param>
        /// <param name="logger">Logger to report errors to.</param>
        /// <param name="executeCommand">Closure which takes the tool path to execute
        /// (gradle wrapper) and a string of arguments returning true if successful,
        /// false otherwise.</param>
        /// <returns>true if successful, false otherwise.</returns>
        public bool Run(bool useGradleDaemon, string buildScript,
                        Dictionary <string, string> projectProperties,
                        string arguments, Logger logger,
                        Func <string, string, bool> executeCommand)
        {
            var allArguments = new List <string>()
            {
                useGradleDaemon ? "--daemon" : "--no-daemon",
                String.Format("-b \"{0}\"", Path.GetFullPath(buildScript)),
            };

            if (!String.IsNullOrEmpty(arguments))
            {
                allArguments.Add(arguments);
            }
            foreach (var kv in projectProperties)
            {
                allArguments.Add(String.Format("\"-P{0}={1}\"", kv.Key, kv.Value));
            }
            var argumentsString = String.Join(" ", allArguments.ToArray());

            // Generate gradle.properties to set properties in the script rather than using
            // the command line.
            // Some users of Windows 10 systems have had issues running the Gradle resolver
            // which is suspected to be caused by command line argument parsing or truncation.
            // Using both gradle.properties and properties specified via command line arguments
            // works fine.
            try {
                File.WriteAllText(Path.Combine(BuildDirectory, "gradle.properties"),
                                  GradleWrapper.GenerateGradleProperties(projectProperties));
            } catch (IOException error) {
                logger.Log(String.Format("Unable to configure Gradle for execution " +
                                         "({0} {1})\n\n{2}",
                                         Executable, argumentsString, error),
                           level: LogLevel.Error);
                return(false);
            }
            logger.Log(String.Format("Running Gradle...\n\n{0} {1}", Executable, argumentsString),
                       level: LogLevel.Verbose);
            return(executeCommand(Executable, argumentsString));
        }