Example #1
0
        public static async Task <int> Execute(
            IServiceProvider services,
            Project project,
            string command,
            string[] args)
        {
            var environment     = (IApplicationEnvironment)services.GetService(typeof(IApplicationEnvironment));
            var commandText     = project.Commands[command];
            var replacementArgs = CommandGrammar.Process(
                commandText,
                (key) => GetVariable(environment, key),
                preserveSurroundingQuotes: false)
                                  .ToArray();

            var entryPoint = replacementArgs[0];

            args = replacementArgs.Skip(1).Concat(args).ToArray();

            if (string.IsNullOrEmpty(entryPoint) ||
                string.Equals(entryPoint, "run", StringComparison.Ordinal))
            {
                entryPoint = project.Name;
            }

            CallContextServiceLocator.Locator.ServiceProvider = services;
            return(await ExecuteMain(services, entryPoint, args));
        }
Example #2
0
        internal string AddScriptExtensionPropertyToCommandLine(string scriptCommandline,
                                                                string scriptExtensionPropertyName)
        {
            var scriptArguments = CommandGrammar.Process(
                scriptCommandline,
                (s) => null,
                preserveSurroundingQuotes: true);

            scriptArguments = scriptArguments.Where(argument => !string.IsNullOrEmpty(argument)).ToArray();

            var scriptCommand  = scriptArguments.First();
            var trimmedCommand = scriptCommand.Trim('\"').Trim('\'');

            // Path.IsPathRooted only looks at paths conforming to the current os,
            // we need to account for all things
            if (!IsPathRootedForAnyOS(trimmedCommand))
            {
                scriptCommand = @".\" + scriptCommand;
            }

            if (scriptCommand.EndsWith("\"") || scriptCommand.EndsWith("'"))
            {
                var endChar = scriptCommand.Last();
                scriptCommand = $"{scriptCommand.TrimEnd(endChar)}$({scriptExtensionPropertyName}){endChar}";
            }
            else
            {
                scriptCommand += $"$({scriptExtensionPropertyName})";
            }

            var command = string.Join(" ", new[] { scriptCommand }.Concat(scriptArguments.Skip(1)));

            return(command);
        }
Example #3
0
        internal string ReplaceScriptVariables(string scriptCommandline)
        {
            Func <string, string> scriptVariableReplacementDelegate = key =>
            {
                if (ScriptVariableToMSBuildMap.ContainsKey(key))
                {
                    if (ScriptVariableToMSBuildMap[key] == null)
                    {
                        MigrationErrorCodes.MIGRATE1016(
                            $"{key} is currently an unsupported script variable for project migration")
                        .Throw();
                    }

                    return(ScriptVariableToMSBuildMap[key]);
                }
                return($"$({key})");
            };

            var scriptArguments = CommandGrammar.Process(
                scriptCommandline,
                scriptVariableReplacementDelegate,
                preserveSurroundingQuotes: true);

            scriptArguments = scriptArguments.Where(argument => !string.IsNullOrEmpty(argument)).ToArray();

            return(string.Join(" ", scriptArguments));
        }
Example #4
0
        private static IEnumerable <string> ParseScriptArguments(Project project, string scriptCommandLine, Func <string, string> getVariable)
        {
            var scriptArguments = CommandGrammar.Process(
                scriptCommandLine,
                GetScriptVariable(project, getVariable),
                preserveSurroundingQuotes: false);

            scriptArguments = scriptArguments.Where(argument => !string.IsNullOrEmpty(argument)).ToArray();
            if (scriptArguments.Length == 0)
            {
                return(null);
            }

            return(scriptArguments);
        }
Example #5
0
        public void Execute(Runtime.Project project, string scriptName, Func <string, string> getVariable)
        {
            IEnumerable <string> scriptCommandLines;

            if (!project.Scripts.TryGetValue(scriptName, out scriptCommandLines))
            {
                return;
            }

            foreach (var scriptCommandLine in scriptCommandLines)
            {
                var scriptArguments = CommandGrammar.Process(
                    scriptCommandLine,
                    GetScriptVariable(project, getVariable));

                // Command-lines on Windows are executed via "cmd /C" in order
                // to support batch files, &&, built-in commands like echo, etc.
                // ComSpec is Windows-specific, and contains the full path to cmd.exe
                var comSpec = Environment.GetEnvironmentVariable("ComSpec");
                if (!string.IsNullOrEmpty(comSpec))
                {
                    scriptArguments =
                        new[] { comSpec, "/C", "\"" }
                    .Concat(scriptArguments)
                    .Concat(new[] { "\"" })
                    .ToArray();
                }

                var startInfo = new ProcessStartInfo
                {
                    FileName         = scriptArguments.FirstOrDefault(),
                    Arguments        = String.Join(" ", scriptArguments.Skip(1)),
                    WorkingDirectory = project.ProjectDirectory,
    #if NET45
                    UseShellExecute = false,
    #endif
                };
                var process = Process.Start(startInfo);

                process.WaitForExit();
            }
        }
Example #6
0
        private string AddScriptExtension(ProjectPropertyGroupElement propertyGroup, string scriptCommandline, string scriptId)
        {
            var scriptArguments = CommandGrammar.Process(
                scriptCommandline,
                (s) => null,
                preserveSurroundingQuotes: false);

            scriptArguments = scriptArguments.Where(argument => !string.IsNullOrEmpty(argument)).ToArray();
            var scriptCommand = scriptArguments.First();
            var propertyName  = $"MigratedScriptExtension_{scriptId}";

            var windowsScriptExtensionProperty = propertyGroup.AddProperty(propertyName,
                                                                           s_windowsScriptExtension);
            var unixScriptExtensionProperty = propertyGroup.AddProperty(propertyName,
                                                                        s_unixScriptExtension);

            windowsScriptExtensionProperty.Condition =
                $" '$(OS)' == 'Windows_NT' and Exists('{scriptCommand}{s_windowsScriptExtension}') ";
            unixScriptExtensionProperty.Condition =
                $" '$(OS)' != 'Windows_NT' and Exists('{scriptCommand}{s_unixScriptExtension}') ";

            return(propertyName);
        }
Example #7
0
        public bool Execute(Runtime.Project project, string scriptName, Func <string, string> getVariable)
        {
            IEnumerable <string> scriptCommandLines;

            if (!project.Scripts.TryGetValue(scriptName, out scriptCommandLines))
            {
                return(true);
            }

            Report?.WriteLine($"Executing script '{scriptName}' in {Runtime.Project.ProjectFileName}");

            foreach (var scriptCommandLine in scriptCommandLines)
            {
                // Preserve quotation marks around arguments since command is about to be passed to a shell. May need
                // the quotes to ensure the shell groups arguments correctly.
                var scriptArguments = CommandGrammar.Process(
                    scriptCommandLine,
                    GetScriptVariable(project, getVariable),
                    preserveSurroundingQuotes: true);

                // Ensure the array won't be empty and the elements won't be null or empty strings.
                scriptArguments = scriptArguments.Where(argument => !string.IsNullOrEmpty(argument)).ToArray();
                if (scriptArguments.Length == 0)
                {
                    continue;
                }

                if (RuntimeEnvironmentHelper.IsWindows)
                {
                    // Only forward slashes are used in script blocks. Replace with backslashes to correctly
                    // locate the script. The directory separator is platform-specific.
                    scriptArguments[0] = scriptArguments[0].Replace(
                        Path.AltDirectorySeparatorChar,
                        Path.DirectorySeparatorChar);

                    // Command-lines on Windows are executed via "cmd /S /C" in order to support batch files, &&,
                    // built-in commands like echo, et cetera. /S allows quoting the command as well as the arguments.
                    // ComSpec is Windows-specific, and contains the full path to cmd.exe
                    var comSpec = Environment.GetEnvironmentVariable("ComSpec");
                    if (!string.IsNullOrEmpty(comSpec))
                    {
                        scriptArguments =
                            new[] { comSpec, "/S", "/C", "\"" }
                        .Concat(scriptArguments)
                        .Concat(new[] { "\"" })
                        .ToArray();
                    }
                }
                else
                {
                    // Special-case a script name that, perhaps with added .sh, matches an existing file.
                    var surroundWithQuotes = false;
                    var scriptCandidate    = scriptArguments[0];
                    if (scriptCandidate.StartsWith("\"", StringComparison.Ordinal) &&
                        scriptCandidate.EndsWith("\"", StringComparison.Ordinal))
                    {
                        // Strip surrounding quotes; they were required in project.json to keep the script name
                        // together but confuse File.Exists() e.g. "My Script", lacking ./ prefix and .sh suffix.
                        surroundWithQuotes = true;
                        scriptCandidate    = scriptCandidate.Substring(1, scriptCandidate.Length - 2);
                    }

                    if (!scriptCandidate.EndsWith(".sh", StringComparison.Ordinal))
                    {
                        scriptCandidate = scriptCandidate + ".sh";
                    }

                    if (File.Exists(Path.Combine(project.ProjectDirectory, scriptCandidate)))
                    {
                        // scriptCandidate may be a path relative to the project root. If so, likely will not be found
                        // in the $PATH; add ./ to let bash know where to look.
                        var prefix = Path.IsPathRooted(scriptCandidate) ? string.Empty : "./";
                        var quote  = surroundWithQuotes ? "\"" : string.Empty;
                        scriptArguments[0] = $"{ quote }{ prefix }{ scriptCandidate }{ quote }";
                    }

                    // Always use /usr/bin/env bash -c in order to support redirection and so on; similar to Windows case.
                    // Unlike Windows, must escape quotation marks within the newly-quoted string.
                    scriptArguments = new[] { "/usr/bin/env", "bash", "-c", "\"" }
                    .Concat(scriptArguments.Select(argument => argument.Replace("\"", "\\\"")))
                    .Concat(new[] { "\"" })
                    .ToArray();
                }

                var startInfo = new ProcessStartInfo
                {
                    FileName         = scriptArguments.FirstOrDefault(),
                    Arguments        = string.Join(" ", scriptArguments.Skip(1)),
                    WorkingDirectory = project.ProjectDirectory,
#if DNX451
                    UseShellExecute = false
#endif
                };

                var process = Process.Start(startInfo);
                process.WaitForExit();

                if (process.ExitCode != 0)
                {
                    ErrorMessage = string.Format(ErrorMessageTemplate, scriptName, process.ExitCode);
                    ExitCode     = process.ExitCode;
                    return(false);
                }
            }

            return(true);
        }
Example #8
0
        public bool Execute(Runtime.Project project, string scriptName, Func <string, string> getVariable)
        {
            IEnumerable <string> scriptCommandLines;

            if (!project.Scripts.TryGetValue(scriptName, out scriptCommandLines))
            {
                return(true);
            }

            foreach (var scriptCommandLine in scriptCommandLines)
            {
                var scriptArguments = CommandGrammar.Process(
                    scriptCommandLine,
                    GetScriptVariable(project, getVariable));

                // Ensure the array won't be empty and the first element won't be null or empty string.
                scriptArguments = scriptArguments.Where(argument => !string.IsNullOrEmpty(argument)).ToArray();

                if (scriptArguments.Length == 0)
                {
                    continue;
                }

                if (!PlatformHelper.IsMono)
                {
                    // Forward-slash is used in script blocked only. Replace them with back-slash to correctly
                    // locate the script. The directory separator is platform-specific.
                    scriptArguments[0] = scriptArguments[0].Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);

                    // Command-lines on Windows are executed via "cmd /C" in order
                    // to support batch files, &&, built-in commands like echo, etc.
                    // ComSpec is Windows-specific, and contains the full path to cmd.exe
                    var comSpec = Environment.GetEnvironmentVariable("ComSpec");
                    if (!string.IsNullOrEmpty(comSpec))
                    {
                        scriptArguments =
                            new[] { comSpec, "/C", "\"" }
                        .Concat(scriptArguments)
                        .Concat(new[] { "\"" })
                        .ToArray();
                    }
                }
                else
                {
                    var scriptCandiate = scriptArguments[0] + ".sh";
                    if (File.Exists(scriptCandiate))
                    {
                        scriptArguments[0] = scriptCandiate;
                        scriptArguments    = new[] { "/bin/bash" }.Concat(scriptArguments).ToArray();
                    }
                }

                var startInfo = new ProcessStartInfo
                {
                    FileName         = scriptArguments.FirstOrDefault(),
                    Arguments        = String.Join(" ", scriptArguments.Skip(1)),
                    WorkingDirectory = project.ProjectDirectory,
#if ASPNET50
                    UseShellExecute = false
#endif
                };

                var process = Process.Start(startInfo);
                process.WaitForExit();

                if (process.ExitCode != 0)
                {
                    ErrorMessage = string.Format(ErrorMessageTemplate, scriptName, process.ExitCode);
                    ExitCode     = process.ExitCode;
                    return(false);
                }
            }

            return(true);
        }
Example #9
0
        public Task <int> Main(string[] args)
        {
            RuntimeOptions options;

            string[] programArgs;
            int      exitCode;

            bool shouldExit = ParseArgs(args, out options, out programArgs, out exitCode);

            if (shouldExit)
            {
                return(Task.FromResult(exitCode));
            }

            IFileWatcher watcher;

            if (options.WatchFiles)
            {
                watcher = new FileWatcher(ProjectResolver.ResolveRootDirectory(Path.GetFullPath(options.ApplicationBaseDirectory)));
            }
            else
            {
                watcher = NoopWatcher.Instance;
            }

            var host = new DefaultHost(options, _serviceProvider, _loadContextAccessor, watcher);

            if (host.Project == null)
            {
                return(Task.FromResult(-1));
            }

            var    lookupCommand = string.IsNullOrEmpty(options.ApplicationName) ? "run" : options.ApplicationName;
            string replacementCommand;

            if (host.Project.Commands.TryGetValue(lookupCommand, out replacementCommand))
            {
                // preserveSurroundingQuotes: false to imitate a shell. Shells remove quotation marks before calling
                // Main methods. Here however we are invoking Main() without involving a shell.
                var replacementArgs = CommandGrammar
                                      .Process(replacementCommand, GetVariable, preserveSurroundingQuotes: false)
                                      .ToArray();
                options.ApplicationName = replacementArgs.First();
                programArgs             = replacementArgs.Skip(1).Concat(programArgs).ToArray();
            }

            if (string.IsNullOrEmpty(options.ApplicationName) ||
                string.Equals(options.ApplicationName, "run", StringComparison.Ordinal))
            {
                options.ApplicationName = host.Project.EntryPoint ?? host.Project.Name;
            }

            IDisposable disposable = null;

            try
            {
                disposable = host.AddLoaders(_container);

                return(ExecuteMain(host, options.ApplicationName, programArgs)
                       .ContinueWith(async(t, state) =>
                {
                    ((IDisposable)state).Dispose();
                    return await t;
                },
                                     disposable).Unwrap());
            }
            catch
            {
                // If there's an error, dispose the host and throw
                if (disposable != null)
                {
                    disposable.Dispose();
                }

                throw;
            }
        }
Example #10
0
        public Task <int> Main(string[] args)
        {
            DefaultHostOptions options;

            string[] programArgs;

            var isShowingInformation = ParseArgs(args, out options, out programArgs);

            if (isShowingInformation)
            {
                return(Task.FromResult(0));
            }

            var host = new DefaultHost(options, _serviceProvider);

            if (host.Project == null)
            {
                return(Task.FromResult(-1));
            }

            var    lookupCommand = string.IsNullOrEmpty(options.ApplicationName) ? "run" : options.ApplicationName;
            string replacementCommand;

            if (host.Project.Commands.TryGetValue(lookupCommand, out replacementCommand))
            {
                var replacementArgs = CommandGrammar.Process(
                    replacementCommand,
                    GetVariable).ToArray();
                options.ApplicationName = replacementArgs.First();
                programArgs             = replacementArgs.Skip(1).Concat(programArgs).ToArray();
            }

            if (string.IsNullOrEmpty(options.ApplicationName) ||
                string.Equals(options.ApplicationName, "run", StringComparison.Ordinal))
            {
                if (string.IsNullOrEmpty(host.Project.Name))
                {
                    options.ApplicationName = Path.GetFileName(options.ApplicationBaseDirectory);
                }
                else
                {
                    options.ApplicationName = host.Project.Name;
                }
            }

            IDisposable disposable = null;

            try
            {
                disposable = host.AddLoaders(_container);

                return(ExecuteMain(host, options.ApplicationName, programArgs)
                       .ContinueWith(async(t, state) =>
                {
                    ((IDisposable)state).Dispose();
                    return await t;
                },
                                     disposable).Unwrap());
            }
            catch
            {
                // If there's an error, dispose the host and throw
                if (disposable != null)
                {
                    disposable.Dispose();
                }

                throw;
            }
        }
Example #11
0
        public static int Main(string[] args)
        {
            DefaultHostOptions options;

            string[]    programArgs;
            int         exitCode;
            DefaultHost host;

            try
            {
                bool shouldExit = ParseArgs(args, out options, out programArgs, out exitCode);
                if (shouldExit)
                {
                    return(exitCode);
                }

                host = new DefaultHost(options, PlatformServices.Default.AssemblyLoadContextAccessor);

                if (host.Project == null)
                {
                    return(1);
                }

                var    lookupCommand = string.IsNullOrEmpty(options.ApplicationName) ? "run" : options.ApplicationName;
                string replacementCommand;
                if (host.Project.Commands.TryGetValue(lookupCommand, out replacementCommand))
                {
                    // preserveSurroundingQuotes: false to imitate a shell. Shells remove quotation marks before calling
                    // Main methods. Here however we are invoking Main() without involving a shell.
                    var replacementArgs = CommandGrammar
                                          .Process(replacementCommand, GetVariable, preserveSurroundingQuotes: false)
                                          .ToArray();
                    options.ApplicationName = replacementArgs.First();
                    programArgs             = replacementArgs.Skip(1).Concat(programArgs).ToArray();
                }

                if (string.IsNullOrEmpty(options.ApplicationName) ||
                    string.Equals(options.ApplicationName, "run", StringComparison.Ordinal))
                {
                    options.ApplicationName = host.Project.EntryPoint ?? host.Project.Name;
                }
            }
            catch (Exception ex)
            {
                throw SuppressStackTrace(ex);
            }

            IDisposable disposable = null;

            try
            {
                disposable = host.AddLoaders(PlatformServices.Default.AssemblyLoaderContainer);

                return(ExecuteMain(host, options.ApplicationName, programArgs)
                       .ContinueWith((t, state) =>
                {
                    ((IDisposable)state).Dispose();
                    return t.GetAwaiter().GetResult();
                },
                                     disposable).GetAwaiter().GetResult());
            }
            catch
            {
                // If there's an error, dispose the host and throw
                if (disposable != null)
                {
                    disposable.Dispose();
                }

                throw;
            }
        }
Example #12
0
        public Task<int> Main(string[] args)
        {
            ILogger log = null;
            try
            {
                ApplicationHostOptions options;
                string[] programArgs;
                int exitCode;

                bool shouldExit = ParseArgs(args, out options, out programArgs, out exitCode);
                if (shouldExit)
                {
                    return Task.FromResult(exitCode);
                }
                string traceConfig =
                    string.IsNullOrEmpty(options.Trace) ?
                        Environment.GetEnvironmentVariable(EnvironmentNames.Trace) :
                        options.Trace;
                // Initialize logging
                RuntimeLogging.Initialize(traceConfig, ConfigureLogging);

                // "Program" is a terrible name for a logger and this is the only logger in
                // this namespace :).
                log = RuntimeLogging.Logger("Microsoft.Framework.ApplicationHost");

                log.LogInformation("Application Host Starting");

                // Construct the necessary context for hosting the application
                var builder = RuntimeHostBuilder.ForProjectDirectory(
                    options.ApplicationBaseDirectory,
                    NuGetFramework.Parse(_environment.RuntimeFramework.FullName),
                    _serviceProvider);

                // Configure assembly loading
                builder.Loaders.Add(new ProjectAssemblyLoaderFactory(
                    new LibraryExporter(
                        builder.TargetFramework,
                        builder.PackagePathResolver)));
                builder.Loaders.Add(new PackageAssemblyLoaderFactory(builder.PackagePathResolver));

                if (builder.Project == null)
                {
                    // Failed to load the project
                    Console.Error.WriteLine("Unable to find a project.json file.");
                    return Task.FromResult(3);
                }

                // Boot the runtime
                var host = builder.Build();

                // Get the project and print some information from it
                log.LogInformation($"Project: {host.Project.Name} ({host.Project.BaseDirectory})");

                // Determine the command to be executed
                var command = string.IsNullOrEmpty(options.ApplicationName) ? "run" : options.ApplicationName;
                string replacementCommand;
                if (host.Project.Commands.TryGetValue(command, out replacementCommand))
                {
                    var replacementArgs = CommandGrammar.Process(
                        replacementCommand,
                        GetVariable).ToArray();
                    options.ApplicationName = replacementArgs.First();
                    programArgs = replacementArgs.Skip(1).Concat(programArgs).ToArray();
                }

                if (string.IsNullOrEmpty(options.ApplicationName) ||
                    string.Equals(options.ApplicationName, "run", StringComparison.Ordinal))
                {
                    options.ApplicationName = host.Project.EntryPoint ?? host.Project.Name;
                }

                log.LogInformation($"Executing '{options.ApplicationName}' '{string.Join(" ", programArgs)}'");
                return host.ExecuteApplication(
                    _loaderContainer,
                    _loadContextAccessor,
                    options.ApplicationName,
                    programArgs);
            }
            catch (Exception ex)
            {
                if (log != null)
                {
                    log.LogError($"{ex.GetType().FullName} {ex.Message}", ex);
                }
                Console.Error.WriteLine($"Error loading project: {ex.Message}");
                return Task.FromResult(1);
            }
        }