예제 #1
0
        /// <summary>
        /// This is a helper method for looking up directories that directly contains assemblies that would be loaded
        /// given the published runtime framework. We should run crossgen on these folders
        /// </summary>
        private IEnumerable <string> ResolveOutputAssemblies(PublishRoot root)
        {
            var resolver = new DefaultPackagePathResolver(root.TargetPackagesPath);

            if (root.LockFile == null)
            {
                return(Enumerable.Empty <string>());
            }

            var directories = new HashSet <string>();

            foreach (var target in root.LockFile.Targets)
            {
                foreach (var library in target.Libraries)
                {
                    var packagesDir = resolver.GetInstallPath(library.Name, library.Version);

                    foreach (var path in library.RuntimeAssemblies)
                    {
                        var assemblyPath = CombinePath(packagesDir, path);
                        directories.Add(Path.GetDirectoryName(assemblyPath));
                    }
                }
            }

            return(directories);
        }
예제 #2
0
        public bool BuildNativeImages(PublishRoot root)
        {
            var success = true;

            // REVIEW: Does does doing this for multiple runtimes make sense?
            foreach (var runtime in root.Runtimes)
            {
                var runtimeBin = Path.Combine(runtime.TargetPath, "bin");

                var options = new CrossgenOptions()
                {
                    CrossgenPath = Path.Combine(runtimeBin, "crossgen.exe"),
                    InputPaths   = ResolveOutputAssemblies(root),
                    RuntimePath  = runtimeBin,
                    Symbols      = false
                };

                var crossgenManager = new CrossgenManager(options);
                success &= crossgenManager.GenerateNativeImages();

                if (!success)
                {
                    return(false);
                }
            }
            return(success);
        }
예제 #3
0
        private async Task <bool> Restore(PublishRoot root, PublishProject publishProject, string restoreDirectory)
        {
            var appEnv = (IApplicationEnvironment)root.HostServices.GetService(typeof(IApplicationEnvironment));

            var feedOptions = new FeedOptions();

            feedOptions.IgnoreFailedSources = true;
            feedOptions.Sources.Add(root.TargetPackagesPath);
            feedOptions.TargetPackagesFolder = root.TargetPackagesPath;

            var restoreCommand = new RestoreCommand(appEnv);

            foreach (var runtime in root.Runtimes)
            {
                restoreCommand.TargetFrameworks.Add(publishProject.SelectFrameworkForRuntime(runtime));
            }

            restoreCommand.SkipRestoreEvents = true;
            restoreCommand.SkipInstall       = true;
            // This is a workaround for #1322. Since we use restore to generate the lock file
            // after publish, it's possible to fail restore after copying the closure
            // if framework assemblies and packages have the same name. This is more likely now
            // since dependencies may exist in the top level
            restoreCommand.IgnoreMissingDependencies = true;
            restoreCommand.CheckHashFile             = false;
            restoreCommand.RestoreDirectories.Add(restoreDirectory);
            restoreCommand.FeedOptions = feedOptions;

            // Mute "dnu restore" subcommand
            restoreCommand.Reports = Reports.Constants.NullReports;

            var success = await restoreCommand.Execute();

            return(success);
        }
예제 #4
0
        public bool BuildNativeImages(PublishRoot root)
        {
            var success = true;

            foreach (var runtime in root.Runtimes)
            {
                NuGetDependencyResolver resolver;
                if (!_resolverLookup.TryGetValue(runtime.Framework, out resolver))
                {
                    throw new InvalidOperationException("No matching framework is found for " + runtime.Framework);
                }

                var runtimeBin = Path.Combine(runtime.TargetPath, "bin");

                var options = new CrossgenOptions()
                {
                    CrossgenPath = Path.Combine(runtimeBin, "crossgen.exe"),
                    InputPaths   = ResolveOutputAssemblies(root, resolver),
                    RuntimePath  = runtimeBin,
                    Symbols      = false
                };

                var crossgenManager = new CrossgenManager(options);
                success &= crossgenManager.GenerateNativeImages();

                if (!success)
                {
                    return(false);
                }
            }
            return(success);
        }
예제 #5
0
        /// <summary>
        /// This is a helper method for looking up directories that directly contains assemblies that would be loaded
        /// given the published runtime framework. We should run crossgen on these folders
        /// </summary>
        private IEnumerable<string> ResolveOutputAssemblies(PublishRoot root)
        {
            var resolver = new DefaultPackagePathResolver(root.TargetPackagesPath);

            if (root.PublishedLockFile == null)
            {
                return Enumerable.Empty<string>();
            }

            var directories = new HashSet<string>();

            foreach (var target in root.PublishedLockFile.Targets)
            {
                foreach (var library in target.Libraries)
                {
                    var packagesDir = resolver.GetInstallPath(library.Name, library.Version);

                    foreach (var path in library.RuntimeAssemblies)
                    {
                        var assemblyPath = CombinePath(packagesDir, path);
                        directories.Add(Path.GetDirectoryName(assemblyPath));
                    }
                }
            }

            return directories;
        }
예제 #6
0
        private void CopyProject(PublishRoot root, Runtime.Project project, string targetPath, bool includeSource)
        {
            var additionalExcluding = new List <string>();

            // If a public folder is specified with 'webroot' or '--wwwroot', we ignore it when copying project files
            var wwwRootPath = string.Empty;

            if (!string.IsNullOrEmpty(WwwRoot))
            {
                wwwRootPath = Path.GetFullPath(Path.Combine(project.ProjectDirectory, WwwRoot));
                wwwRootPath = PathUtility.EnsureTrailingSlash(wwwRootPath);
            }

            // If project root is used as value of '--wwwroot', we shouldn't exclude it when copying
            if (string.Equals(wwwRootPath, PathUtility.EnsureTrailingSlash(project.ProjectDirectory)))
            {
                wwwRootPath = string.Empty;
            }

            if (!string.IsNullOrEmpty(wwwRootPath))
            {
                additionalExcluding.Add(wwwRootPath.Substring(PathUtility.EnsureTrailingSlash(project.ProjectDirectory).Length));
            }

            var sourceFiles = project.Files.GetFilesForBundling(includeSource, additionalExcluding);

            root.Operations.Copy(sourceFiles, project.ProjectDirectory, targetPath);
        }
예제 #7
0
        public bool BuildNativeImages(PublishRoot root)
        {
            var success = true;
            foreach (var runtime in root.Runtimes)
            {
                NuGetDependencyResolver resolver;
                if (!_resolverLookup.TryGetValue(runtime.Framework, out resolver))
                {
                    throw new InvalidOperationException("No matching framework is found for " + runtime.Framework);
                }

                var runtimeBin = Path.Combine(runtime.TargetPath, "bin");

                var options = new CrossgenOptions()
                {
                    CrossgenPath = Path.Combine(runtimeBin, "crossgen.exe"),
                    InputPaths = ResolveOutputAssemblies(root, resolver),
                    RuntimePath = runtimeBin,
                    Symbols = false
                };

                var crossgenManager = new CrossgenManager(options);
                success &= crossgenManager.GenerateNativeImages();

                if (!success)
                {
                    return false;
                }
            }
            return success;
        }
예제 #8
0
        private void EmitSource(PublishRoot root)
        {
            root.Reports.Quiet.WriteLine("  Copying source code from {0} dependency {1}",
                                         _projectDescription.Type, _projectDescription.Identity.Name);

            var project    = GetCurrentProject();
            var targetName = project.Name;

            TargetPath = Path.Combine(
                root.OutputPath,
                PublishRoot.AppRootName,
                PublishRoot.SourceFolderName,
                targetName);

            // If root.OutputPath is specified by --out option, it might not be a full path
            TargetPath = Path.GetFullPath(TargetPath);

            root.Reports.Quiet.WriteLine("    Source {0}", _projectDescription.Path.Bold());
            root.Reports.Quiet.WriteLine("    Target {0}", TargetPath);

            root.Operations.Delete(TargetPath);

            CopyProject(root, project, TargetPath, includeSource: true);

            CopyRelativeSources(project);

            UpdateWebRoot(root, TargetPath);

            var appBase = Path.Combine(PublishRoot.AppRootName, "src", project.Name);

            _relativeAppBase    = Path.Combine("..", appBase);
            ApplicationBasePath = Path.Combine(root.OutputPath, appBase);
        }
예제 #9
0
        private void EmitSource(PublishRoot root)
        {
            root.Reports.Quiet.WriteLine("  Copying source code from {0} dependency {1}",
                _projectDescription.Type, _projectDescription.Identity.Name);

            var project = GetCurrentProject();
            var targetName = project.Name;
            TargetPath = Path.Combine(
                root.OutputPath,
                PublishRoot.AppRootName,
                PublishRoot.SourceFolderName,
                targetName);

            // If root.OutputPath is specified by --out option, it might not be a full path
            TargetPath = Path.GetFullPath(TargetPath);

            root.Reports.Quiet.WriteLine("    Source {0}", _projectDescription.Path.Bold());
            root.Reports.Quiet.WriteLine("    Target {0}", TargetPath);

            root.Operations.Delete(TargetPath);

            CopyProject(root, project, TargetPath, includeSource: true);

            CopyRelativeSources(project);

            UpdateWebRoot(root, TargetPath);

            var appBase = Path.Combine(PublishRoot.AppRootName, "src", project.Name);

            _relativeAppBase = Path.Combine("..", appBase);
            ApplicationBasePath = Path.Combine(root.OutputPath, appBase);
        }
예제 #10
0
        private async Task <bool> Restore(PublishRoot root, PublishProject publishProject, string restoreDirectory, IEnumerable <FrameworkName> targetFrameworks)
        {
            var appEnv = PlatformServices.Default.Application;

            var feedOptions = new FeedOptions();

            feedOptions.IgnoreFailedSources = true;
            feedOptions.Sources.Add(root.TargetPackagesPath);
            feedOptions.TargetPackagesFolder = root.TargetPackagesPath;

            var restoreCommand = new RestoreCommand(appEnv);

            restoreCommand.TargetFrameworks.AddRange(targetFrameworks);
            restoreCommand.RequestedRuntimes = root.RuntimeIdentifiers;
            restoreCommand.SkipRestoreEvents = true;
            restoreCommand.SkipInstall       = true;
            // This is a workaround for #1322. Since we use restore to generate the lock file
            // after publish, it's possible to fail restore after copying the closure
            // if framework assemblies and packages have the same name. This is more likely now
            // since dependencies may exist in the top level
            restoreCommand.IgnoreMissingDependencies = true;
            restoreCommand.CheckHashFile             = false;
            restoreCommand.RestoreDirectories.Add(restoreDirectory);
            restoreCommand.FeedOptions = feedOptions;

            // Mute "dnu restore" subcommand
            restoreCommand.Reports = Reports.Constants.NullReports;

            var success = await restoreCommand.Execute();

            return(success);
        }
예제 #11
0
        public bool Emit(PublishRoot root)
        {
            root.Reports.Quiet.WriteLine("Bundling runtime {0}", Name);

            if (Directory.Exists(TargetPath))
            {
                root.Reports.Quiet.WriteLine("  {0} already exists.", TargetPath);

                // REVIEW: IS this correct?
                return(true);
            }

            if (!Directory.Exists(TargetPath))
            {
                Directory.CreateDirectory(TargetPath);
            }

            new PublishOperations().Copy(_runtimePath, TargetPath);

            if (!RuntimeEnvironmentHelper.IsWindows)
            {
                // Executable permissions on dnx lost on copy.
                var dnxPath = Path.Combine(TargetPath, "bin", "dnx");
                if (!FileOperationUtils.MarkExecutable(dnxPath))
                {
                    root.Reports.Information.WriteLine("Failed to mark {0} as executable".Yellow(), dnxPath);
                }
            }

            return(true);
        }
예제 #12
0
        public bool PostProcess(PublishRoot root)
        {
            // At this point, all nupkgs generated from dependency projects are available in packages folder
            // So we can add them to lockfile now
            if (!UpdateLockFile(root))
            {
                return(false);
            }

            // Prune the packages folder only leaving things that are required
            PrunePackages(root);

            // If --wwwroot-out doesn't have a non-empty value, we don't need a public app folder in output
            if (string.IsNullOrEmpty(WwwRootOut))
            {
                return(true);
            }

            var project = GetCurrentProject();

            // Construct path to public app folder, which contains content files and tool dlls
            // The name of public app folder is specified with "--appfolder" option
            // Default name of public app folder is the same as main project
            var wwwRootOutPath = Path.Combine(root.OutputPath, WwwRootOut);

            // Delete old public app folder because we don't want leftovers from previous operations
            root.Operations.Delete(wwwRootOutPath);
            Directory.CreateDirectory(wwwRootOutPath);

            // Copy content files (e.g. html, js and images) of main project into public app folder
            CopyContentFiles(root, project, wwwRootOutPath);

            return(GenerateWebConfigFileForWwwRootOut(root, project, wwwRootOutPath));
        }
예제 #13
0
 public PublishRuntime(PublishRoot root, FrameworkName frameworkName, string runtimePath)
 {
     _frameworkName = frameworkName;
     _runtimePath   = runtimePath;
     Name           = new DirectoryInfo(_runtimePath).Name;
     TargetPath     = Path.Combine(root.TargetRuntimesPath, Name);
 }
예제 #14
0
        public bool Emit(PublishRoot root)
        {
            root.Reports.Quiet.WriteLine("Bundling runtime {0}", Name);

            if (Directory.Exists(TargetPath))
            {
                root.Reports.Quiet.WriteLine("  {0} already exists.", TargetPath);

                // REVIEW: IS this correct?
                return true;
            }

            if (!Directory.Exists(TargetPath))
            {
                Directory.CreateDirectory(TargetPath);
            }

            new PublishOperations().Copy(_runtimePath, TargetPath);

            if (!RuntimeEnvironmentHelper.IsWindows)
            {
                // Executable permissions on dnx lost on copy. 
                var dnxPath = Path.Combine(TargetPath, "bin", "dnx");
                if (!FileOperationUtils.MarkExecutable(dnxPath))
                {
                    root.Reports.Information.WriteLine("Failed to mark {0} as executable".Yellow(), dnxPath);
                }
            }

            return true;
        }
예제 #15
0
 public PublishRuntime(PublishRoot root, FrameworkName frameworkName, string runtimePath)
 {
     _frameworkName = frameworkName;
     _runtimePath = runtimePath;
     Name = new DirectoryInfo(_runtimePath).Name;
     TargetPath = Path.Combine(root.TargetRuntimesPath, Name);
 }
예제 #16
0
        public bool BuildNativeImages(PublishRoot root)
        {
            var success = true;

            // REVIEW: Does does doing this for multiple runtimes make sense?
            foreach (var runtime in root.Runtimes)
            {
                var runtimeBin = Path.Combine(runtime.TargetPath, "bin");

                var options = new CrossgenOptions()
                {
                    CrossgenPath = Path.Combine(runtimeBin, "crossgen.exe"),
                    InputPaths = ResolveOutputAssemblies(root),
                    RuntimePath = runtimeBin,
                    Symbols = false
                };

                var crossgenManager = new CrossgenManager(options);
                success &= crossgenManager.GenerateNativeImages();

                if (!success)
                {
                    return false;
                }
            }
            return success;
        }
예제 #17
0
        private static string GetBootstrapperVersion(PublishRoot root)
        {
            // Use version of Microsoft.AspNet.Loader.IIS.Interop as version of bootstrapper
            var package = root.Packages.SingleOrDefault(
                x => string.Equals(x.Library.Name, "Microsoft.AspNet.Loader.IIS.Interop"));

            return(package == null ? string.Empty : package.Library.Version.ToString());
        }
예제 #18
0
        bool TryAddRuntime(PublishRoot root, FrameworkName frameworkName, string runtimePath)
        {
            if (!Directory.Exists(runtimePath))
            {
                return(false);
            }

            root.Runtimes.Add(new PublishRuntime(root, frameworkName, runtimePath));
            return(true);
        }
예제 #19
0
        private void UpdateWebRoot(PublishRoot root, string targetPath)
        {
            // Update the 'webroot' property, which was specified with '--wwwroot-out' option
            if (!string.IsNullOrEmpty(WwwRootOut))
            {
                var targetProjectJson = Path.Combine(targetPath, Runtime.Project.ProjectFileName);

                UpdateJson(targetProjectJson, jsonObj =>
                {
                    var targetWebRootPath = Path.Combine(root.OutputPath, WwwRootOut);
                    jsonObj["webroot"]    = PathUtility.GetRelativePath(targetProjectJson, targetWebRootPath, separator: '/');
                });
            }
        }
예제 #20
0
        private bool UpdateLockFile(PublishRoot root)
        {
            var tasks = new Task <bool> [root.Projects.Count];

            for (int i = 0; i < root.Projects.Count; i++)
            {
                var project          = root.Projects[i];
                var restoreDirectory = project.IsPackage ? Path.Combine(project.TargetPath, "root") : project.TargetPath;
                tasks[i] = Restore(root, project, restoreDirectory);
            }

            Task.WaitAll(tasks);

            return(tasks.All(t => t.Result));
        }
예제 #21
0
        private void CopyContentFiles(PublishRoot root, Runtime.Project project, string targetFolderPath)
        {
            root.Reports.Quiet.WriteLine("Copying contents of {0} dependency {1} to {2}",
                                         _projectDescription.Type, _projectDescription.Identity.Name, targetFolderPath);

            var contentSourcePath = GetWwwRootSourcePath(project.ProjectDirectory, WwwRoot);

            root.Reports.Quiet.WriteLine("  Source {0}", contentSourcePath);
            root.Reports.Quiet.WriteLine("  Target {0}", targetFolderPath);

            if (Directory.Exists(contentSourcePath))
            {
                root.Operations.Copy(contentSourcePath, targetFolderPath);
            }
        }
예제 #22
0
        /// <summary>
        /// This is a helper method for looking up directories that directly contains assemblies that would be loaded
        /// given the published runtime framework. We should run crossgen on these folders
        /// </summary>
        private IEnumerable <string> ResolveOutputAssemblies(PublishRoot root, NuGetDependencyResolver resolver)
        {
            var outputPathsMap = root.Packages
                                 .ToDictionary(
                pkg => pkg.Library,
                pkg => pkg.TargetPath
                );

            var result              = new HashSet <string>();
            var libraryNotInOutput  = new List <LibraryIdentity>();
            var missingOutputFolder = new List <string>();

            foreach (var dependency in resolver.PackageAssemblyLookup.Values)
            {
                var    libId             = dependency.Library.Identity;
                var    libPath           = dependency.Library.Path;
                var    assemblyDir       = Path.GetDirectoryName(dependency.Path);
                var    assemblySelection = assemblyDir.Substring(libPath.Length);
                string outputLibLocation;
                if (!outputPathsMap.TryGetValue(libId, out outputLibLocation))
                {
                    libraryNotInOutput.Add(libId);
                    continue;
                }
                var output = outputLibLocation + assemblySelection;

                if (!Directory.Exists(output))
                {
                    missingOutputFolder.Add(output);
                }
                else
                {
                    result.Add(output);
                }
            }

            if (libraryNotInOutput.Any())
            {
                throw new InvalidOperationException(string.Format("Library {0} cannot be found in the published output.", string.Join(", ", libraryNotInOutput)));
            }

            if (missingOutputFolder.Any())
            {
                throw new InvalidOperationException("Published output does not contain directory:\n" + string.Join("\n", missingOutputFolder));
            }

            return(result);
        }
예제 #23
0
        private IEnumerable <FrameworkName> SelectCompatibleFrameworks(PublishRoot root, Runtime.Project project, IEnumerable <FrameworkName> requestedFrameworks)
        {
            var selectedFrameworks = new List <FrameworkName>();

            foreach (var framework in requestedFrameworks)
            {
                var selectedFramework = project.GetCompatibleTargetFramework(framework);
                if (selectedFramework == null)
                {
                    root.Reports.WriteError($"Unable to build {project.Name}. It is not compatible with the requested target framework: {framework}");
                    return(null);
                }
                selectedFrameworks.Add(selectedFramework.FrameworkName);
            }
            return(selectedFrameworks);
        }
예제 #24
0
        public void Emit(PublishRoot root)
        {
            root.Reports.Quiet.WriteLine("Using {0} dependency {1}", _package.Type, Library);

            var srcPackagePathResolver    = new DefaultPackagePathResolver(root.SourcePackagesPath);
            var targetPackagePathResolver = new DefaultPackagePathResolver(root.TargetPackagesPath);
            var srcPackageDir             = srcPackagePathResolver.GetInstallPath(
                _package.Identity.Name,
                _package.Identity.Version);
            var targetPackageDir = targetPackagePathResolver.GetInstallPath(
                _package.Identity.Name,
                _package.Identity.Version);

            root.Reports.Quiet.WriteLine("    Source {0}", srcPackageDir.Bold());
            root.Reports.Quiet.WriteLine("    Target {0}", targetPackageDir);

            root.Operations.Copy(srcPackageDir, targetPackageDir);
        }
예제 #25
0
        public void Emit(PublishRoot root)
        {
            root.Reports.Quiet.WriteLine("Using {0} dependency {1}", _package.Type, Library);

            var srcPackagePathResolver = new DefaultPackagePathResolver(root.SourcePackagesPath);
            var targetPackagePathResolver = new DefaultPackagePathResolver(root.TargetPackagesPath);
            var srcPackageDir = srcPackagePathResolver.GetInstallPath(
                _package.Identity.Name,
                _package.Identity.Version);
            var targetPackageDir = targetPackagePathResolver.GetInstallPath(
                _package.Identity.Name,
                _package.Identity.Version);

            root.Reports.Quiet.WriteLine("    Source {0}", srcPackageDir.Bold());
            root.Reports.Quiet.WriteLine("    Target {0}", targetPackageDir);

            root.Operations.Copy(srcPackageDir, targetPackageDir);
        }
예제 #26
0
        private bool UpdateLockFile(PublishRoot root)
        {
            var appEnv = (IApplicationEnvironment)root.HostServices.GetService(typeof(IApplicationEnvironment));

            var feedOptions = new FeedOptions();

            feedOptions.IgnoreFailedSources = true;
            feedOptions.Sources.Add(root.TargetPackagesPath);
            feedOptions.TargetPackagesFolder = root.TargetPackagesPath;

            var tasks = new Task <bool> [root.Projects.Count];

            for (int i = 0; i < root.Projects.Count; i++)
            {
                var project        = root.Projects[i];
                var restoreCommand = new RestoreCommand(appEnv);

                foreach (var runtime in root.Runtimes)
                {
                    restoreCommand.TargetFrameworks.Add(project.SelectFrameworkForRuntime(runtime));
                }

                var restoreDirectory = project.IsPackage ? Path.Combine(project.TargetPath, "root") : project.TargetPath;
                restoreCommand.SkipRestoreEvents = true;
                restoreCommand.SkipInstall       = true;
                // This is a workaround for #1322. Since we use restore to generate the lock file
                // after publish, it's possible to fail restore after copying the closure
                // if framework assemblies and packages have the same name. This is more likely now
                // since dependencies may exist in the top level
                restoreCommand.IgnoreMissingDependencies = true;
                restoreCommand.CheckHashFile             = false;
                restoreCommand.RestoreDirectories.Add(restoreDirectory);
                restoreCommand.FeedOptions = feedOptions;

                // Mute "dnu restore" subcommand
                restoreCommand.Reports = Reports.Constants.NullReports;

                tasks[i] = restoreCommand.Execute();
            }

            Task.WaitAll(tasks);

            return(tasks.All(t => t.Result));
        }
예제 #27
0
        private static void CopyAspNetLoaderDll(PublishRoot root, string wwwRootOutPath)
        {
            // Tool dlls including AspNet.Loader.dll go to bin folder under public app folder
            var wwwRootOutBinPath = Path.Combine(wwwRootOutPath, "bin");

            // Check for an environment variable which can be used (generally in tests)
            // to override where AspNet.Loader.dll is located.
            var loaderPath = Environment.GetEnvironmentVariable(EnvironmentNames.AspNetLoaderPath);

            if (string.IsNullOrEmpty(loaderPath))
            {
                // Copy Microsoft.AspNet.Loader.IIS.Interop/tools/*.dll into bin to support AspNet.Loader.dll
                var package = root.Packages.SingleOrDefault(
                    x => string.Equals(x.Library.Name, "Microsoft.AspNet.Loader.IIS.Interop"));
                if (package == null)
                {
                    return;
                }

                var resolver    = new DefaultPackagePathResolver(root.SourcePackagesPath);
                var packagePath = resolver.GetInstallPath(package.Library.Name, package.Library.Version);
                loaderPath = Path.Combine(packagePath, "tools");
            }

            if (!string.IsNullOrEmpty(loaderPath) && Directory.Exists(loaderPath))
            {
                foreach (var packageToolFile in Directory.EnumerateFiles(loaderPath, "*.dll").Select(Path.GetFileName))
                {
                    // Create the bin folder only when we need to put something inside it
                    if (!Directory.Exists(wwwRootOutBinPath))
                    {
                        Directory.CreateDirectory(wwwRootOutBinPath);
                    }

                    // Copy to bin folder under public app folder
                    File.Copy(
                        Path.Combine(loaderPath, packageToolFile),
                        Path.Combine(wwwRootOutBinPath, packageToolFile),
                        overwrite: true);
                }
            }
        }
예제 #28
0
        public async Task Emit(PublishRoot root)
        {
            root.Reports.Quiet.WriteLine("Using {0} dependency {1}", _libraryDescription.Type, Library);

            var packagePathResolver = new DefaultPackagePathResolver(root.SourcePackagesPath);
            var srcNupkgPath        = packagePathResolver.GetPackageFilePath(_libraryDescription.Identity.Name, _libraryDescription.Identity.Version);

            var options = new Packages.AddOptions
            {
                NuGetPackage        = srcNupkgPath,
                PackageHashFilePath = Path.ChangeExtension(srcNupkgPath, NuGet.Constants.HashFileExtension),
                SourcePackages      = root.TargetPackagesPath,
            };

            // Mute "packages add" subcommand
            options.Reports = Reports.Constants.NullReports;

            var packagesAddCommand = new Packages.AddCommand(options);
            await packagesAddCommand.Execute();
        }
예제 #29
0
        public bool Emit(PublishRoot root)
        {
            root.Reports.Quiet.WriteLine("Using {0} dependency {1} for {2}", _projectDescription.Type,
                _projectDescription.Identity, _projectDescription.Framework.ToString().Yellow().Bold());

            var success = true;

            if (root.NoSource || IsWrappingAssembly())
            {
                success = EmitNupkg(root);
            }
            else
            {
                success = EmitSource(root);
            }

            root.Reports.Quiet.WriteLine();

            return success;
        }
예제 #30
0
        public async Task Emit(PublishRoot root)
        {
            root.Reports.Quiet.WriteLine("Using {0} dependency {1}", _libraryDescription.Type, Library);

            var packagePathResolver = new DefaultPackagePathResolver(root.SourcePackagesPath);
            var srcNupkgPath = packagePathResolver.GetPackageFilePath(_libraryDescription.Identity.Name, _libraryDescription.Identity.Version);

            var options = new Packages.AddOptions
            {
                NuGetPackage = srcNupkgPath,
                PackageHashFilePath = Path.ChangeExtension(srcNupkgPath, NuGet.Constants.HashFileExtension),
                SourcePackages = root.TargetPackagesPath,
            };

            // Mute "packages add" subcommand
            options.Reports = Reports.Constants.NullReports;

            var packagesAddCommand = new Packages.AddCommand(options);
            await packagesAddCommand.Execute();
        }
예제 #31
0
        public bool Emit(PublishRoot root)
        {
            root.Reports.Quiet.WriteLine("Using {0} dependency {1} for {2}", _projectDescription.Type,
                                         _projectDescription.Identity, _projectDescription.Framework.ToString().Yellow().Bold());

            var success = true;

            if (root.NoSource || IsWrappingAssembly())
            {
                success = EmitNupkg(root);
            }
            else
            {
                EmitSource(root);
            }

            root.Reports.Quiet.WriteLine();

            return(success);
        }
예제 #32
0
        /// <summary>
        /// This is the factory method to instantiate a PackNativeManager, if parameters are in invalid state and native
        /// generation cannot be performed, it would return null
        /// </summary>
        public static NativeImageGenerator Create(PublishOptions options, PublishRoot root, IEnumerable<DependencyContext> contexts)
        {
            if (options.Runtimes.Count() == 0)
            {
                options.Reports.Information.WriteLine(
                    "Please provide target CoreCLR runtimes using --runtime flags".Yellow());
                return null;
            }

            foreach (var runtime in root.Runtimes)
            {
                var frameworkName = runtime.Framework;
                // NOTE: !IsDesktop == IsCore and only Core packages can be crossgened at least for now
                if (VersionUtility.IsDesktop(frameworkName))
                {
                    options.Reports.Information.WriteLine(
                        "Native image generation is only supported for .NET Core flavors.".Yellow());
                    return null;
                }
            }

            var duplicates = options.Runtimes
                .GroupBy(r => CrossgenManager.ResolveProcessorArchitecture(r))
                .Where(g => g.Count() > 1);

            if (duplicates.Any())
            {
                var message = "The following runtimes will result in output conflicts. Please provide distinct runtime flavor for each processor architecture:\n"
                    + string.Join("\n", duplicates.Select(
                        g => string.Format("Architecture: {0}\nRuntimes: {1}", g.Key, string.Join(", ", g))));
                options.Reports.Information.WriteLine(message.Yellow());
                return null;
            }

            var contextMap = contexts.ToDictionary(
                context => context.FrameworkName,
                context => context.NuGetDependencyResolver
            );

            return new NativeImageGenerator(contextMap);
        }
예제 #33
0
        /// <summary>
        /// This is the factory method to instantiate a PackNativeManager, if parameters are in invalid state and native
        /// generation cannot be performed, it would return null
        /// </summary>
        public static NativeImageGenerator Create(PublishOptions options, PublishRoot root, IEnumerable <DependencyContext> contexts)
        {
            if (options.Runtimes.Count() == 0)
            {
                options.Reports.Information.WriteLine(
                    "Please provide target CoreCLR runtimes using --runtime flags".Yellow());
                return(null);
            }

            foreach (var runtime in root.Runtimes)
            {
                var frameworkName = runtime.Framework;
                // NOTE: !IsDesktop == IsCore and only Core packages can be crossgened at least for now
                if (VersionUtility.IsDesktop(frameworkName))
                {
                    options.Reports.Information.WriteLine(
                        "Native image generation is only supported for .NET Core flavors.".Yellow());
                    return(null);
                }
            }

            var duplicates = options.Runtimes
                             .GroupBy(r => CrossgenManager.ResolveProcessorArchitecture(r))
                             .Where(g => g.Count() > 1);

            if (duplicates.Any())
            {
                var message = "The following runtimes will result in output conflicts. Please provide distinct runtime flavor for each processor architecture:\n"
                              + string.Join("\n", duplicates.Select(
                                                g => string.Format("Architecture: {0}\nRuntimes: {1}", g.Key, string.Join(", ", g))));
                options.Reports.Information.WriteLine(message.Yellow());
                return(null);
            }

            var contextMap = contexts.ToDictionary(
                context => context.FrameworkName,
                context => context.NuGetDependencyResolver
                );

            return(new NativeImageGenerator(contextMap));
        }
예제 #34
0
        private void UpdateWebRoot(PublishRoot root, string targetPath)
        {
            // Update the 'webroot' property, which was specified with '--wwwroot-out' option
            if (!string.IsNullOrEmpty(WwwRootOut))
            {
                var hostingConfig = Path.Combine(targetPath, "hosting.json");
                if (!File.Exists(hostingConfig))
                {
                    File.AppendAllText(hostingConfig, $@"{{
    ""webroot"": ""{PathUtility.GetRelativePath(hostingConfig, Path.Combine(root.OutputPath, WwwRootOut), separator: '/')}""
}}");
                }
                else
                {
                    UpdateJson(hostingConfig, jsonObj =>
                    {
                        var targetWebRootPath = Path.Combine(root.OutputPath, WwwRootOut);
                        PublishOperations.SetWebRootJson(jsonObj, PathUtility.GetRelativePath(hostingConfig, targetWebRootPath, separator: '/'));
                    });
                }
            }
        }
예제 #35
0
        private static void CopyAspNetLoaderDll(PublishRoot root, string wwwRootOutPath)
        {
            // Tool dlls including AspNet.Loader.dll go to bin folder under public app folder
            var wwwRootOutBinPath = Path.Combine(wwwRootOutPath, "bin");

            // Check for an environment variable which can be used (generally in tests)
            // to override where AspNet.Loader.dll is located.
            var loaderPath = Environment.GetEnvironmentVariable(EnvironmentNames.AspNetLoaderPath);
            if (string.IsNullOrEmpty(loaderPath))
            {
                // Copy Microsoft.AspNet.Loader.IIS.Interop/tools/*.dll into bin to support AspNet.Loader.dll
                var package = root.Packages.SingleOrDefault(
                    x => string.Equals(x.Library.Name, "Microsoft.AspNet.Loader.IIS.Interop"));
                if (package == null)
                {
                    return;
                }

                var resolver = new DefaultPackagePathResolver(root.SourcePackagesPath);
                var packagePath = resolver.GetInstallPath(package.Library.Name, package.Library.Version);
                loaderPath = Path.Combine(packagePath, "tools");
            }

            if (!string.IsNullOrEmpty(loaderPath) && Directory.Exists(loaderPath))
            {
                foreach (var packageToolFile in Directory.EnumerateFiles(loaderPath, "*.dll").Select(Path.GetFileName))
                {
                    // Create the bin folder only when we need to put something inside it
                    if (!Directory.Exists(wwwRootOutBinPath))
                    {
                        Directory.CreateDirectory(wwwRootOutBinPath);
                    }

                    // Copy to bin folder under public app folder
                    File.Copy(
                        Path.Combine(loaderPath, packageToolFile),
                        Path.Combine(wwwRootOutBinPath, packageToolFile),
                        overwrite: true);
                }
            }
        }
예제 #36
0
        private void UpdateWebRoot(PublishRoot root, string targetPath)
        {
            // Update the 'webroot' property, which was specified with '--wwwroot-out' option
            if (!string.IsNullOrEmpty(WwwRootOut))
            {
                var targetProjectJson = Path.Combine(targetPath, Runtime.Project.ProjectFileName);

                UpdateJson(targetProjectJson, jsonObj =>
                {
                    var targetWebRootPath = Path.Combine(root.OutputPath, WwwRootOut);
                    jsonObj["webroot"] = PathUtility.GetRelativePath(targetProjectJson, targetWebRootPath, separator: '/');
                });
            }
        }
예제 #37
0
        private bool EmitNupkg(PublishRoot root)
        {
            root.Reports.Quiet.WriteLine("  Packing nupkg from {0} dependency {1}",
                _projectDescription.Type, _projectDescription.Identity.Name);

            IsPackage = true;

            var project = GetCurrentProject();
            if (project == null)
            {
                return false;
            }

            var resolver = new DefaultPackagePathResolver(root.TargetPackagesPath);
            var targetNupkg = resolver.GetPackageFileName(project.Name, project.Version);
            TargetPath = resolver.GetInstallPath(project.Name, project.Version);

            root.Reports.Quiet.WriteLine("    Source {0}", _projectDescription.Path.Bold());
            root.Reports.Quiet.WriteLine("    Target {0}", TargetPath);

            if (Directory.Exists(TargetPath))
            {
                root.Operations.Delete(TargetPath);
            }

            // If this is a wrapper project, we need to generate a lock file before building it
            if (IsWrappingAssembly())
            {
                var success = Restore(root, publishProject: this, restoreDirectory: project.ProjectDirectory)
                    .GetAwaiter().GetResult();
                if (!success)
                {
                    return false;
                }
            }

            // Generate nupkg from this project dependency
            var buildOptions = new BuildOptions();
            buildOptions.ProjectPatterns.Add(project.ProjectDirectory);
            buildOptions.OutputDir = Path.Combine(project.ProjectDirectory, "bin");
            buildOptions.Configurations.Add(root.Configuration);
            buildOptions.GeneratePackages = true;
            buildOptions.Reports = root.Reports.ShallowCopy();

            if (root.Frameworks.Any())
            {
                // Make sure we only emit the nupkgs for the specified frameworks
                // We need to pick actual project frameworks relevant to the publish
                // but the project may not target exactly the right framework so we need
                // to use a compatibility check.
                foreach (var framework in root.Frameworks)
                {
                    var selectedFramework = project.GetCompatibleTargetFramework(framework.Key);
                    if (selectedFramework == null)
                    {
                        root.Reports.WriteError($"Unable to build {project.Name}. It is not compatible with the requested target framework: {framework.Key}");
                        return false;
                    }
                    buildOptions.TargetFrameworks.Add(selectedFramework.FrameworkName, VersionUtility.GetShortFrameworkName(selectedFramework.FrameworkName));
                }
            }

            // Mute "dnu pack" completely if it is invoked by "dnu publish --quiet"
            buildOptions.Reports.Information = root.Reports.Quiet;

            var buildManager = new BuildManager(root.HostServices, buildOptions);
            if (!buildManager.Build())
            {
                return false;
            }

            // Extract the generated nupkg to target path
            var srcNupkgPath = Path.Combine(buildOptions.OutputDir, root.Configuration, targetNupkg);
            var srcSymbolsNupkgPath = Path.ChangeExtension(srcNupkgPath, "symbols.nupkg");

            var options = new Packages.AddOptions
            {
                NuGetPackage = root.IncludeSymbols ? srcSymbolsNupkgPath : srcNupkgPath,
                SourcePackages = root.TargetPackagesPath,
                Reports = root.Reports
            };

            var packagesAddCommand = new Packages.AddCommand(options);
            packagesAddCommand.Execute().GetAwaiter().GetResult();

            // Copy content files (e.g. html, js and images) of main project into "root" folder of the exported package
            var rootFolderPath = Path.Combine(TargetPath, "root");
            var rootProjectJson = Path.Combine(rootFolderPath, Runtime.Project.ProjectFileName);

            root.Operations.Delete(rootFolderPath);
            CopyProject(root, project, rootFolderPath, includeSource: false);

            UpdateWebRoot(root, rootFolderPath);

            UpdateJson(rootProjectJson, jsonObj =>
            {
                // Update the project entrypoint
                jsonObj["entryPoint"] = _projectDescription.Identity.Name;

                // Set mark this as non loadable
                jsonObj["loadable"] = false;

                // Update the dependencies node to reference the main project
                var deps = new JObject();
                jsonObj["dependencies"] = deps;

                deps[_projectDescription.Identity.Name] = _projectDescription.Identity.Version.ToString();
            });

            var appBase = Path.Combine(PublishRoot.AppRootName, "packages", resolver.GetPackageDirectory(_projectDescription.Identity.Name, _projectDescription.Identity.Version), "root");

            _relativeAppBase = Path.Combine("..", appBase);
            ApplicationBasePath = Path.Combine(root.OutputPath, appBase);

            root.Reports.Quiet.WriteLine("Removing {0}", srcNupkgPath);
            File.Delete(srcNupkgPath);

            root.Reports.Quiet.WriteLine("Removing {0}", srcSymbolsNupkgPath);
            File.Delete(srcSymbolsNupkgPath);

            return true;
        }
예제 #38
0
        private void PrunePackages(PublishRoot root)
        {
            if (root.MainProjectLockFile == null)
            {
                return;
            }

            var resolver = new DefaultPackagePathResolver(root.TargetPackagesPath);

            var lockFilePath = Path.GetFullPath(Path.Combine(ApplicationBasePath, LockFileFormat.LockFileName));

            root.PublishedLockFile = new LockFileFormat().Read(lockFilePath);

            var filesToKeep   = new HashSet <string>();
            var filesToRemove = new HashSet <string>();

            foreach (var target in root.PublishedLockFile.Targets)
            {
                foreach (var library in target.Libraries)
                {
                    var packageDir = resolver.GetInstallPath(library.Name, library.Version);

                    if (library.Name != root.MainProjectName && string.Equals(library.Type, Runtime.LibraryTypes.Package, StringComparison.OrdinalIgnoreCase))
                    {
                        filesToRemove.Add(resolver.GetHashPath(library.Name, library.Version));
                        filesToRemove.Add(resolver.GetPackageFilePath(library.Name, library.Version));
                        filesToRemove.AddRange(Directory.EnumerateFiles(packageDir, $"{library.Name}.xml", SearchOption.AllDirectories));
                    }

                    foreach (var path in library.RuntimeAssemblies)
                    {
                        filesToKeep.Add(Path.Combine(packageDir, path));
                    }
                    foreach (var path in library.CompileTimeAssemblies)
                    {
                        filesToKeep.Add(Path.Combine(packageDir, path));
                    }
                    foreach (var path in library.NativeLibraries)
                    {
                        filesToKeep.Add(Path.Combine(packageDir, path));
                    }
                    foreach (var path in library.ResourceAssemblies)
                    {
                        filesToKeep.Add(Path.Combine(packageDir, path));
                    }
                }
            }

            foreach (var target in root.MainProjectLockFile.Targets.Where(projectTarget =>
                                                                          string.IsNullOrEmpty(projectTarget.RuntimeIdentifier) &&
                                                                          !root.PublishedLockFile.Targets.Any(publishTarget =>
                                                                                                              projectTarget.TargetFramework == publishTarget.TargetFramework)))
            {
                foreach (var library in target.Libraries)
                {
                    var packageDir = resolver.GetInstallPath(library.Name, library.Version);

                    if (Directory.Exists(packageDir))
                    {
                        foreach (var path in library.RuntimeAssemblies)
                        {
                            filesToRemove.Add(Path.Combine(packageDir, path));
                        }
                        foreach (var path in library.CompileTimeAssemblies)
                        {
                            filesToRemove.Add(Path.Combine(packageDir, path));
                        }
                        foreach (var path in library.NativeLibraries)
                        {
                            filesToRemove.Add(Path.Combine(packageDir, path));
                        }
                        foreach (var path in library.ResourceAssemblies)
                        {
                            filesToRemove.Add(Path.Combine(packageDir, path));
                        }
                    }
                }
            }

            foreach (var file in filesToRemove.Except(filesToKeep))
            {
                File.Delete(file);
            }

            if (Directory.Exists(root.TargetPackagesPath))
            {
                root.Operations.DeleteEmptyFolders(root.TargetPackagesPath);
            }

            return;
        }
예제 #39
0
        private bool EmitNupkg(PublishRoot root)
        {
            root.Reports.Quiet.WriteLine("  Packing nupkg from {0} dependency {1}",
                _libraryDescription.Type, _libraryDescription.Identity.Name);

            IsPackage = true;

            var project = GetCurrentProject();
            var resolver = new DefaultPackagePathResolver(root.TargetPackagesPath);
            var targetNupkg = resolver.GetPackageFileName(project.Name, project.Version);
            TargetPath = resolver.GetInstallPath(project.Name, project.Version);

            root.Reports.Quiet.WriteLine("    Source {0}", _libraryDescription.Path.Bold());
            root.Reports.Quiet.WriteLine("    Target {0}", TargetPath);

            if (Directory.Exists(TargetPath))
            {
                root.Operations.Delete(TargetPath);
            }

            // Generate nupkg from this project dependency
            var buildOptions = new BuildOptions();
            buildOptions.ProjectPatterns.Add(project.ProjectDirectory);
            buildOptions.OutputDir = Path.Combine(project.ProjectDirectory, "bin");
            buildOptions.Configurations.Add(root.Configuration);
            buildOptions.GeneratePackages = true;
            buildOptions.Reports = root.Reports.ShallowCopy();

            // Mute "dnu pack" completely if it is invoked by "dnu publish --quiet"
            buildOptions.Reports.Information = root.Reports.Quiet;

            var buildManager = new BuildManager(root.HostServices, buildOptions);
            if (!buildManager.Build())
            {
                return false;
            }

            // Extract the generated nupkg to target path
            var srcNupkgPath = Path.Combine(buildOptions.OutputDir, root.Configuration, targetNupkg);
            var srcSymbolsNupkgPath = Path.ChangeExtension(srcNupkgPath, "symbols.nupkg");

            var options = new Packages.AddOptions
            {
                NuGetPackage = root.IncludeSymbols ? srcSymbolsNupkgPath : srcNupkgPath,
                SourcePackages = root.TargetPackagesPath,
                Reports = root.Reports
            };

            var packagesAddCommand = new Packages.AddCommand(options);
            packagesAddCommand.Execute().GetAwaiter().GetResult();

            // Copy content files (e.g. html, js and images) of main project into "root" folder of the exported package
            var rootFolderPath = Path.Combine(TargetPath, "root");
            var rootProjectJson = Path.Combine(rootFolderPath, Runtime.Project.ProjectFileName);

            root.Operations.Delete(rootFolderPath);
            CopyProject(root, project, rootFolderPath, includeSource: false);

            UpdateWebRoot(root, rootFolderPath);

            UpdateJson(rootProjectJson, jsonObj =>
            {
                // Update the project entrypoint
                jsonObj["entryPoint"] = _libraryDescription.Identity.Name;

                // Set mark this as non loadable
                jsonObj["loadable"] = false;

                // Update the dependencies node to reference the main project
                var deps = new JObject();
                jsonObj["dependencies"] = deps;

                deps[_libraryDescription.Identity.Name] = _libraryDescription.Identity.Version.ToString();
            });

            var appBase = Path.Combine(PublishRoot.AppRootName, "packages", resolver.GetPackageDirectory(_libraryDescription.Identity.Name, _libraryDescription.Identity.Version), "root");

            _relativeAppBase = Path.Combine("..", appBase);
            ApplicationBasePath = Path.Combine(root.OutputPath, appBase);

            root.Reports.Quiet.WriteLine("Removing {0}", srcNupkgPath);
            File.Delete(srcNupkgPath);

            root.Reports.Quiet.WriteLine("Removing {0}", srcSymbolsNupkgPath);
            File.Delete(srcSymbolsNupkgPath);

            return true;
        }
예제 #40
0
        private void GenerateWebConfigFileForWwwRootOut(PublishRoot root, Runtime.Project project, string wwwRootOutPath)
        {
            // Generate web.config for public app folder
            var wwwRootOutWebConfigFilePath = Path.Combine(wwwRootOutPath, "web.config");
            var wwwRootSourcePath           = GetWwwRootSourcePath(project.ProjectDirectory, WwwRoot);
            var webConfigFilePath           = Path.Combine(wwwRootSourcePath, "web.config");

            XDocument xDoc;

            if (File.Exists(webConfigFilePath))
            {
                xDoc = XDocument.Parse(File.ReadAllText(webConfigFilePath));
            }
            else
            {
                xDoc = new XDocument();
            }

            if (xDoc.Root == null)
            {
                xDoc.Add(new XElement("configuration"));
            }

            if (xDoc.Root.Name != "configuration")
            {
                throw new InvalidDataException("'configuration' is the only valid name for root element of web.config file");
            }

            var appSettingsElement = GetOrAddElement(parent: xDoc.Root, name: "appSettings");

            // Always generate \ since web.config is a IIS thing only
            var relativeRuntimesPath = PathUtility.GetRelativePath(wwwRootOutWebConfigFilePath, root.TargetRuntimesPath)
                                       .Replace(Path.DirectorySeparatorChar, '\\');

            var defaultRuntime = root.Runtimes.FirstOrDefault();
            var appBase        = _relativeAppBase.Replace(Path.DirectorySeparatorChar, '\\');

            var keyValuePairs = new Dictionary <string, string>()
            {
                { Runtime.Constants.WebConfigBootstrapperVersion, GetBootstrapperVersion(root) },
                { Runtime.Constants.WebConfigRuntimePath, relativeRuntimesPath },
                { Runtime.Constants.WebConfigRuntimeVersion, GetRuntimeVersion(defaultRuntime) },
                { Runtime.Constants.WebConfigRuntimeFlavor, GetRuntimeFlavor(defaultRuntime) },
                { Runtime.Constants.WebConfigRuntimeAppBase, appBase },
            };

            foreach (var pair in keyValuePairs)
            {
                var addElement = appSettingsElement.Elements()
                                 .Where(x => x.Name == "add" && x.Attribute("key").Value == pair.Key)
                                 .SingleOrDefault();
                if (addElement == null)
                {
                    addElement = new XElement("add");
                    addElement.SetAttributeValue("key", pair.Key);
                    appSettingsElement.Add(addElement);
                }

                addElement.SetAttributeValue("value", pair.Value);
            }

            // Generate target framework information
            ApplyTargetFramework(xDoc, project);

            var xmlWriterSettings = new XmlWriterSettings
            {
                Indent           = true,
                ConformanceLevel = ConformanceLevel.Auto
            };

            using (var xmlWriter = XmlWriter.Create(File.Create(wwwRootOutWebConfigFilePath), xmlWriterSettings))
            {
                xDoc.WriteTo(xmlWriter);
            }
        }
예제 #41
0
        private void GenerateWebConfigFileForWwwRootOut(PublishRoot root, Runtime.Project project, string wwwRootOutPath)
        {
            // Generate web.config for public app folder
            var wwwRootOutWebConfigFilePath = Path.Combine(wwwRootOutPath, "web.config");
            var wwwRootSourcePath = GetWwwRootSourcePath(project.ProjectDirectory, WwwRoot);
            var webConfigFilePath = Path.Combine(wwwRootSourcePath, "web.config");

            XDocument xDoc;
            if (File.Exists(webConfigFilePath))
            {
                xDoc = XDocument.Parse(File.ReadAllText(webConfigFilePath));
            }
            else
            {
                xDoc = new XDocument();
            }

            if (xDoc.Root == null)
            {
                xDoc.Add(new XElement("configuration"));
            }

            if (xDoc.Root.Name != "configuration")
            {
                throw new InvalidDataException("'configuration' is the only valid name for root element of web.config file");
            }

            var appSettingsElement = GetOrAddElement(parent: xDoc.Root, name: "appSettings");

            // Always generate \ since web.config is a IIS thing only
            var relativeRuntimesPath = PathUtility.GetRelativePath(wwwRootOutWebConfigFilePath, root.TargetRuntimesPath)
                                                  .Replace(Path.DirectorySeparatorChar, '\\');

            var defaultRuntime = root.Runtimes.FirstOrDefault();
            var appBase = _relativeAppBase.Replace(Path.DirectorySeparatorChar, '\\');

            var keyValuePairs = new Dictionary<string, string>()
            {
                { Runtime.Constants.WebConfigBootstrapperVersion, GetBootstrapperVersion(root) },
                { Runtime.Constants.WebConfigRuntimePath, relativeRuntimesPath },
                { Runtime.Constants.WebConfigRuntimeVersion, GetRuntimeVersion(defaultRuntime) },
                { Runtime.Constants.WebConfigRuntimeFlavor, GetRuntimeFlavor(defaultRuntime) },
                { Runtime.Constants.WebConfigRuntimeAppBase, appBase },
            };

            foreach (var pair in keyValuePairs)
            {
                var addElement = appSettingsElement.Elements()
                    .Where(x => x.Name == "add" && x.Attribute("key").Value == pair.Key)
                    .SingleOrDefault();
                if (addElement == null)
                {
                    addElement = new XElement("add");
                    addElement.SetAttributeValue("key", pair.Key);
                    appSettingsElement.Add(addElement);
                }

                addElement.SetAttributeValue("value", pair.Value);
            }

            // Generate target framework information
            ApplyTargetFramework(xDoc, project);

            var xmlWriterSettings = new XmlWriterSettings
            {
                Indent = true,
                ConformanceLevel = ConformanceLevel.Auto
            };

            using (var xmlWriter = XmlWriter.Create(File.Create(wwwRootOutWebConfigFilePath), xmlWriterSettings))
            {
                xDoc.WriteTo(xmlWriter);
            }
        }
예제 #42
0
        private bool PrunePackages(PublishRoot root)
        {
            var resolver = new DefaultPackagePathResolver(root.TargetPackagesPath);

            // Special cases (for backwards compat)
            var specialFolders = new List<string> {
                "native",
                "InteropAssemblies",
                "redist",
                "runtimes"
            };

            if (!root.NoSource)
            {
                // 'shared' folder is build time dependency, so we only copy it when deploying with source
                specialFolders.Add("shared");
            }

            var lockFilePath = Path.GetFullPath(Path.Combine(ApplicationBasePath, LockFileFormat.LockFileName));
            var format = new LockFileFormat();
            root.LockFile = format.Read(lockFilePath);

            var keep = new HashSet<string>();

            foreach (var target in root.LockFile.Targets)
            {
                foreach (var library in target.Libraries)
                {
                    var packagesDir = resolver.GetInstallPath(library.Name, library.Version);
                    var manifest = resolver.GetManifestFilePath(library.Name, library.Version);

                    keep.Add(manifest);

                    foreach (var path in library.RuntimeAssemblies)
                    {
                        keep.Add(CombinePath(packagesDir, path));
                    }

                    foreach (var path in library.CompileTimeAssemblies)
                    {
                        keep.Add(CombinePath(packagesDir, path));
                    }

                    foreach (var path in library.NativeLibraries)
                    {
                        keep.Add(CombinePath(packagesDir, path));
                    }

                    foreach (var path in library.ResourceAssemblies)
                    {
                        keep.Add(CombinePath(packagesDir, path));
                    }

                    foreach (var specialFolder in specialFolders)
                    {
                        var specialFolderPath = CombinePath(packagesDir, specialFolder);

                        if (!Directory.Exists(specialFolderPath))
                        {
                            continue;
                        }

                        keep.AddRange(Directory.EnumerateFiles(specialFolderPath, "*.*", SearchOption.AllDirectories));
                    }
                }
            }

            foreach (var package in root.Packages)
            {
                var packageDir = resolver.GetInstallPath(package.Library.Name, package.Library.Version);
                var packageFiles = Directory.EnumerateFiles(packageDir, "*.*", SearchOption.AllDirectories);

                foreach (var file in packageFiles)
                {
                    if (!keep.Contains(file))
                    {
                        File.Delete(file);
                    }
                }

                root.Operations.DeleteEmptyFolders(packageDir);
            }

            return true;
        }
예제 #43
0
        private async Task<bool> Restore(PublishRoot root, PublishProject publishProject, string restoreDirectory)
        {
            var appEnv = (IApplicationEnvironment)root.HostServices.GetService(typeof(IApplicationEnvironment));

            var feedOptions = new FeedOptions();
            feedOptions.IgnoreFailedSources = true;
            feedOptions.Sources.Add(root.TargetPackagesPath);
            feedOptions.TargetPackagesFolder = root.TargetPackagesPath;

            var restoreCommand = new RestoreCommand(appEnv);

            foreach (var framework in root.Frameworks)
            {
                restoreCommand.TargetFrameworks.Add(framework.Key);
            }

            restoreCommand.SkipRestoreEvents = true;
            restoreCommand.SkipInstall = true;
            // This is a workaround for #1322. Since we use restore to generate the lock file
            // after publish, it's possible to fail restore after copying the closure
            // if framework assemblies and packages have the same name. This is more likely now
            // since dependencies may exist in the top level
            restoreCommand.IgnoreMissingDependencies = true;
            restoreCommand.CheckHashFile = false;
            restoreCommand.RestoreDirectories.Add(restoreDirectory);
            restoreCommand.FeedOptions = feedOptions;

            // Mute "dnu restore" subcommand
            restoreCommand.Reports = Reports.Constants.NullReports;

            var success = await restoreCommand.Execute();
            return success;
        }
예제 #44
0
        private bool GenerateWebConfigFileForWwwRootOut(PublishRoot root, Runtime.Project project, string wwwRootOutPath)
        {
            // Generate web.config for public app folder
            var wwwRootOutWebConfigFilePath = Path.Combine(wwwRootOutPath, "web.config");
            var wwwRootSourcePath           = GetWwwRootSourcePath(project.ProjectDirectory, WwwRoot);
            var webConfigFilePath           = Path.Combine(wwwRootSourcePath, "web.config");

            XDocument xDoc;

            if (File.Exists(webConfigFilePath))
            {
                xDoc = XDocument.Parse(File.ReadAllText(webConfigFilePath));
            }
            else
            {
                xDoc = new XDocument();
            }

            if (xDoc.Root == null)
            {
                xDoc.Add(new XElement("configuration"));
            }

            if (xDoc.Root.Name != "configuration")
            {
                throw new InvalidDataException("'configuration' is the only valid name for root element of web.config file");
            }

            // <system.webServer>
            //   <handlers>
            //    <add name="httpplatformhandler" path="*" verb="*" modules="httpPlatformHandler" resourceType="Unspecified" />
            //  </handlers>
            //  <httpPlatform processPath="..\command.cmd"
            //                arguments=""
            //                stdoutLogEnabled="true"
            //                stdoutLogFile="..\logs\stdout.log">
            //  </httpPlatform>
            // </system.webServer>

            // Look for specified command

            var command = root.IISCommand;

            if (!string.IsNullOrEmpty(command) && !project.Commands.ContainsKey(command))
            {
                root.Reports.WriteError($"Specified command {command} cannot be found.");
                return(false);
            }
            else if (project.Commands.Count == 1)
            {
                command = project.Commands.First().Key;
            }
            else if (project.Commands.Count == 0)
            {
                root.Reports.WriteWarning("No commands defined. Defaulting to web.");
            }
            else
            {
                root.Reports.WriteWarning("Multiple commands defined. Defaulting to web.");
            }

            command = command ?? "web";

            root.Reports.Information.WriteLine($"Using command '{command}' as the entry point for web.config.");

            var azurePublishValue = Environment.GetEnvironmentVariable("DNU_PUBLISH_AZURE");
            var publishingToAzure = string.Equals(azurePublishValue, "true", StringComparison.Ordinal) ||
                                    string.Equals(azurePublishValue, "1", StringComparison.Ordinal) ||
                                    !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("WEBSITE_SITE_NAME"));

            var basePath    = publishingToAzure ? @"%home%\site" : "..";
            var baseLogPath = publishingToAzure ? @"\\?\%home%\LogFiles" : @"..\logs";

            var targetDocument = XDocument.Parse($@"<configuration><system.webServer>
  <handlers>
    <add name=""httpplatformhandler"" path=""*"" verb=""*"" modules=""httpPlatformHandler"" resourceType=""Unspecified"" />
  </handlers>
  <httpPlatform processPath=""{basePath}\approot\{command}.cmd""
                arguments="""" 
                stdoutLogEnabled=""true"" 
                stdoutLogFile=""{baseLogPath}\stdout.log"">
  </httpPlatform>
</system.webServer></configuration>");

            var attributesToOverwrite = new[]
            {
                "processPath",
                "arguments"
            };

            var result = xDoc.Root.MergeWith(targetDocument.Root, (name, sourceChild, targetChild) =>
            {
                if (sourceChild != null)
                {
                    // We're only going to merge the httpPlatform element attributes we don't care about
                    if (string.Equals(name.LocalName, "httpPlatform"))
                    {
                        foreach (var attr in sourceChild.Attributes())
                        {
                            if (!attributesToOverwrite.Contains(attr.Name.LocalName))
                            {
                                targetChild.SetAttributeValue(attr.Name, attr.Value);
                            }
                        }
                    }

                    targetChild.Remove();
                    sourceChild.Parent.Add(targetChild);
                    sourceChild.Remove();
                    return(true);
                }

                return(false);
            });

            var xmlWriterSettings = new XmlWriterSettings
            {
                Indent           = true,
                ConformanceLevel = ConformanceLevel.Auto
            };

            using (var xmlWriter = XmlWriter.Create(File.Create(wwwRootOutWebConfigFilePath), xmlWriterSettings))
            {
                result.WriteTo(xmlWriter);
            }

            // Create the logs directory so the httpPlatformHandler can write there
            Directory.CreateDirectory(Path.Combine(root.OutputPath, "logs"));

            return(true);
        }
예제 #45
0
        public bool Publish()
        {
            var warnings = new List <DiagnosticMessage>();

            Runtime.Project project;
            if (!Runtime.Project.TryGetProject(_options.ProjectDir, out project, warnings))
            {
                _options.Reports.Error.WriteLine("Unable to locate {0}.".Red(), Runtime.Project.ProjectFileName);
                return(false);
            }

            foreach (var warning in warnings)
            {
                _options.Reports.Information.WriteLine(warning.FormattedMessage.Yellow());
            }

            // '--wwwroot' option can override 'webroot' property in project.json
            _options.WwwRoot    = _options.WwwRoot ?? project.WebRoot;
            _options.WwwRootOut = _options.WwwRootOut ?? _options.WwwRoot;

            if (string.IsNullOrEmpty(_options.WwwRoot) && !string.IsNullOrEmpty(_options.WwwRootOut))
            {
                _options.Reports.Error.WriteLine(
                    "'--wwwroot-out' option can be used only when the '--wwwroot' option or 'webroot' in project.json is specified.".Red());
                return(false);
            }

            if (string.Equals(_options.WwwRootOut, PublishRoot.AppRootName, StringComparison.OrdinalIgnoreCase))
            {
                _options.Reports.Error.WriteLine(
                    "'{0}' is a reserved folder name. Please choose another name for the wwwroot-out folder.".Red(),
                    PublishRoot.AppRootName);
                return(false);
            }

            var sw = Stopwatch.StartNew();

            string outputPath = _options.OutputDir;

            var projectDir = project.ProjectDirectory;

            var frameworkContexts = new Dictionary <FrameworkName, DependencyContext>();

            var root = new PublishRoot(project, outputPath, _hostServices, _options.Reports)
            {
                Configuration  = _options.Configuration,
                NoSource       = _options.NoSource,
                IncludeSymbols = _options.IncludeSymbols
            };

            Func <string, string> getVariable = key =>
            {
                return(null);
            };

            if (!ScriptExecutor.Execute(project, "prepare", getVariable))
            {
                _options.Reports.Error.WriteLine(ScriptExecutor.ErrorMessage);
                return(false);
            }

            if (!ScriptExecutor.Execute(project, "prepublish", getVariable))
            {
                _options.Reports.Error.WriteLine(ScriptExecutor.ErrorMessage);
                return(false);
            }

            if (!ResolveActualRuntimeNames(_options.Runtimes))
            {
                return(false);
            }

            foreach (var runtime in _options.Runtimes)
            {
                // Calculate the runtime name by taking the last path segment (since it could be a path),
                // but first strip off any trailing '\' or '/' in case the path provided was something like
                //  "C:\Foo\Bar\dnx-clr-win-x64...\"
                var runtimeName   = new DirectoryInfo(runtime).Name;
                var frameworkName = DependencyContext.SelectFrameworkNameForRuntime(
                    project.GetTargetFrameworks().Select(x => x.FrameworkName),
                    runtimeName);

                if (frameworkName == null)
                {
                    _options.Reports.Error.WriteLine(
                        "The project being published does not support the runtime '{0}'",
                        runtime.ToString().Red().Bold());
                    return(false);
                }


                var           runtimeLocated    = TryAddRuntime(root, frameworkName, runtime);
                List <string> runtimeProbePaths = null;

                if (!runtimeLocated)
                {
                    runtimeProbePaths = new List <string>();
                    runtimeProbePaths.Add(runtime);
                    var runtimeHome = Environment.GetEnvironmentVariable(EnvironmentNames.Home);
                    if (string.IsNullOrEmpty(runtimeHome))
                    {
                        var runtimeGlobalPath  = DnuEnvironment.GetFolderPath(DnuFolderPath.DnxGlobalPath);
                        var defaultRuntimeHome = DnuEnvironment.GetFolderPath(DnuFolderPath.DefaultDnxHome);
                        runtimeHome = $"{defaultRuntimeHome};{runtimeGlobalPath}";
                    }

                    foreach (var portion in runtimeHome.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
                    {
                        var packagesPath = Path.Combine(
                            Environment.ExpandEnvironmentVariables(portion),
                            "runtimes",
                            runtime);

                        if (TryAddRuntime(root, frameworkName, packagesPath))
                        {
                            runtimeLocated = true;
                            break;
                        }

                        runtimeProbePaths.Add(packagesPath);
                    }
                }

                if (!runtimeLocated)
                {
                    _options.Reports.Error.WriteLine(string.Format("Unable to locate runtime '{0}'", runtime.Red().Bold()));
                    if (runtimeProbePaths != null)
                    {
                        _options.Reports.Error.WriteLine(string.Format("Locations probed:{0}{1}", Environment.NewLine, string.Join(Environment.NewLine, runtimeProbePaths)));
                    }
                    return(false);
                }

                if (!frameworkContexts.ContainsKey(frameworkName))
                {
                    frameworkContexts[frameworkName] = CreateDependencyContext(project, frameworkName);
                }
            }

            // If there is no target framework filter specified with '--runtime',
            // the published output targets all frameworks specified in project.json
            if (!_options.Runtimes.Any())
            {
                foreach (var frameworkInfo in project.GetTargetFrameworks())
                {
                    if (!frameworkContexts.ContainsKey(frameworkInfo.FrameworkName))
                    {
                        frameworkContexts[frameworkInfo.FrameworkName] =
                            CreateDependencyContext(project, frameworkInfo.FrameworkName);
                    }
                }
            }

            if (!frameworkContexts.Any())
            {
                // We can only get here if the project has no frameworks section, which we don't actually support any more
                _options.Reports.Error.WriteLine("The project being published has no frameworks listed in the 'frameworks' section.");
                return(false);
            }

            root.SourcePackagesPath = frameworkContexts.First().Value.PackagesDirectory;

            bool anyUnresolvedDependency = false;

            foreach (var dependencyContext in frameworkContexts.Values)
            {
                foreach (var library in dependencyContext.LibraryManager.GetLibraryDescriptions())
                {
                    if (!library.Resolved)
                    {
                        // If there's any unresolved dependencies then complain and keep working
                        _options.Reports.Quiet.WriteLine("  Unable to resolve dependency {0}", library.Identity.ToString().Red().Bold());
                        anyUnresolvedDependency = true;
                    }
                    else
                    {
                        if (library.Type == LibraryTypes.Project)
                        {
                            if (!root.Projects.Any(p => p.Library.Name == library.Identity.Name))
                            {
                                var publishProject = new PublishProject((ProjectDescription)library);

                                if (publishProject.Library.Name == project.Name)
                                {
                                    publishProject.WwwRoot    = _options.WwwRoot;
                                    publishProject.WwwRootOut = _options.WwwRootOut;
                                }

                                root.Projects.Add(publishProject);
                            }
                        }
                        else if (library.Type == LibraryTypes.Package)
                        {
                            if (!root.Packages.Any(p => p.Library.Name == library.Identity.Name))
                            {
                                root.Packages.Add(new PublishPackage((PackageDescription)library));
                            }
                        }
                    }
                }
            }

            NativeImageGenerator nativeImageGenerator = null;

            if (_options.Native)
            {
                nativeImageGenerator = NativeImageGenerator.Create(_options, root, frameworkContexts.Values);
                if (nativeImageGenerator == null)
                {
                    _options.Reports.Error.WriteLine("Fail to initiate native image generation process.".Red());
                    return(false);
                }
            }

            var success = root.Emit();

            if (!ScriptExecutor.Execute(project, "postpublish", getVariable))
            {
                _options.Reports.Error.WriteLine(ScriptExecutor.ErrorMessage);
                return(false);
            }

            if (_options.Native && !nativeImageGenerator.BuildNativeImages(root))
            {
                _options.Reports.Error.WriteLine("Native image generation failed.");
                return(false);
            }

            sw.Stop();

            _options.Reports.Information.WriteLine("Time elapsed {0}", sw.Elapsed);
            return(!anyUnresolvedDependency && success);
        }
예제 #46
0
        private bool UpdateLockFile(PublishRoot root)
        {
            var tasks = new Task<bool>[root.Projects.Count];
            for (int i = 0; i < root.Projects.Count; i++)
            {
                var project = root.Projects[i];
                var restoreDirectory = project.IsPackage ? Path.Combine(project.TargetPath, "root") : project.TargetPath;
                tasks[i] = Restore(root, project, restoreDirectory);
            }

            Task.WaitAll(tasks);

            return tasks.All(t => t.Result);
        }
예제 #47
0
        private bool GenerateWebConfigFileForWwwRootOut(PublishRoot root, Runtime.Project project, string wwwRootOutPath)
        {
            // Generate web.config for public app folder
            var wwwRootOutWebConfigFilePath = Path.Combine(wwwRootOutPath, "web.config");
            var wwwRootSourcePath = GetWwwRootSourcePath(project.ProjectDirectory, WwwRoot);
            var webConfigFilePath = Path.Combine(wwwRootSourcePath, "web.config");

            XDocument xDoc;
            if (File.Exists(webConfigFilePath))
            {
                xDoc = XDocument.Parse(File.ReadAllText(webConfigFilePath));
            }
            else
            {
                xDoc = new XDocument();
            }

            if (xDoc.Root == null)
            {
                xDoc.Add(new XElement("configuration"));
            }

            if (xDoc.Root.Name != "configuration")
            {
                throw new InvalidDataException("'configuration' is the only valid name for root element of web.config file");
            }

            // <system.webServer>
            //   <handlers>
            //    <add name="httpplatformhandler" path="*" verb="*" modules="httpPlatformHandler" resourceType="Unspecified" />
            //  </handlers>
            //  <httpPlatform processPath="..\command.cmd"
            //                arguments="" 
            //                stdoutLogEnabled="true" 
            //                stdoutLogFile="..\logs\stdout.log">
            //  </httpPlatform>
            // </system.webServer>

            // Look for specified command

            var command = root.IISCommand;

            if (!string.IsNullOrEmpty(command) && !project.Commands.ContainsKey(command))
            {
                root.Reports.WriteError($"Specified command {command} cannot be found.");
                return false;
            }
            else if (project.Commands.Count == 1)
            {
                command = project.Commands.First().Key;
            }
            else if (project.Commands.Count == 0)
            {
                root.Reports.WriteWarning("No commands defined. Defaulting to web.");
            }
            else
            {
                root.Reports.WriteWarning("Multiple commands defined. Defaulting to web.");
            }

            command = command ?? "web";

            root.Reports.Information.WriteLine($"Using command '{command}' as the entry point for web.config.");

            var azurePublishValue = Environment.GetEnvironmentVariable("DNU_PUBLISH_AZURE");
            var publishingToAzure = string.Equals(azurePublishValue, "true", StringComparison.Ordinal) ||
                                    string.Equals(azurePublishValue, "1", StringComparison.Ordinal) ||
                                    !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("WEBSITE_SITE_NAME"));

            var basePath = publishingToAzure ? @"%home%\site" : "..";
            var baseLogPath = publishingToAzure ? @"\\?\%home%\LogFiles" : @"..\logs";

            var targetDocument = XDocument.Parse($@"<configuration><system.webServer>
  <handlers>
    <add name=""httpplatformhandler"" path=""*"" verb=""*"" modules=""httpPlatformHandler"" resourceType=""Unspecified"" />
  </handlers>
  <httpPlatform processPath=""{basePath}\approot\{command}.cmd""
                arguments="""" 
                stdoutLogEnabled=""true"" 
                stdoutLogFile=""{baseLogPath}\stdout.log"">
  </httpPlatform>
</system.webServer></configuration>");

            var attributesToOverwrite = new[]
            {
                "processPath",
                "arguments"
            };

            var result = xDoc.Root.MergeWith(targetDocument.Root, (name, sourceChild, targetChild) =>
            {
                if (sourceChild != null)
                {
                    // We're only going to merge the httpPlatform element attributes we don't care about
                    if (string.Equals(name.LocalName, "httpPlatform"))
                    {
                        foreach (var attr in sourceChild.Attributes())
                        {
                            if (!attributesToOverwrite.Contains(attr.Name.LocalName))
                            {
                                targetChild.SetAttributeValue(attr.Name, attr.Value);
                            }
                        }
                    }

                    targetChild.Remove();
                    sourceChild.Parent.Add(targetChild);
                    sourceChild.Remove();
                    return true;
                }

                return false;
            });

            var xmlWriterSettings = new XmlWriterSettings
            {
                Indent = true,
                ConformanceLevel = ConformanceLevel.Auto
            };

            using (var xmlWriter = XmlWriter.Create(File.Create(wwwRootOutWebConfigFilePath), xmlWriterSettings))
            {
                result.WriteTo(xmlWriter);
            }

            // Create the logs directory so the httpPlatformHandler can write there
            Directory.CreateDirectory(Path.Combine(root.OutputPath, "logs"));

            return true;
        }
예제 #48
0
        private bool PrunePackages(PublishRoot root)
        {
            var resolver = new DefaultPackagePathResolver(root.TargetPackagesPath);

            // Special cases (for backwards compat)
            var specialFolders = new List <string> {
                "native",
                "InteropAssemblies",
                "redist"
            };

            if (!root.NoSource)
            {
                // 'shared' folder is build time dependency, so we only copy it when deploying with source
                specialFolders.Add("shared");
            }

            var lockFilePath = Path.GetFullPath(Path.Combine(ApplicationBasePath, LockFileFormat.LockFileName));
            var format       = new LockFileFormat();

            root.LockFile = format.Read(lockFilePath);

            var keep = new HashSet <string>();

            foreach (var target in root.LockFile.Targets)
            {
                foreach (var library in target.Libraries)
                {
                    var packagesDir = resolver.GetInstallPath(library.Name, library.Version);
                    var manifest    = resolver.GetManifestFilePath(library.Name, library.Version);

                    keep.Add(manifest);

                    foreach (var path in library.RuntimeAssemblies)
                    {
                        keep.Add(CombinePath(packagesDir, path));
                    }

                    foreach (var path in library.CompileTimeAssemblies)
                    {
                        keep.Add(CombinePath(packagesDir, path));
                    }

                    foreach (var path in library.NativeLibraries)
                    {
                        keep.Add(CombinePath(packagesDir, path));
                    }

                    foreach (var specialFolder in specialFolders)
                    {
                        var specialFolderPath = CombinePath(packagesDir, specialFolder);

                        if (!Directory.Exists(specialFolderPath))
                        {
                            continue;
                        }

                        keep.AddRange(Directory.EnumerateFiles(specialFolderPath, "*.*", SearchOption.AllDirectories));
                    }
                }
            }

            foreach (var package in root.Packages)
            {
                var packageDir   = resolver.GetInstallPath(package.Library.Name, package.Library.Version);
                var packageFiles = Directory.EnumerateFiles(packageDir, "*.*", SearchOption.AllDirectories);

                foreach (var file in packageFiles)
                {
                    if (!keep.Contains(file))
                    {
                        File.Delete(file);
                    }
                }

                root.Operations.DeleteEmptyFolders(packageDir);
            }

            return(true);
        }
예제 #49
0
 private static string GetBootstrapperVersion(PublishRoot root)
 {
     // Use version of Microsoft.AspNet.Loader.IIS.Interop as version of bootstrapper
     var package = root.Packages.SingleOrDefault(
         x => string.Equals(x.Library.Name, "Microsoft.AspNet.Loader.IIS.Interop"));
     return package == null ? string.Empty : package.Library.Version.ToString();
 }
예제 #50
0
        public bool PostProcess(PublishRoot root)
        {
            // At this point, all nupkgs generated from dependency projects are available in packages folder
            // So we can add them to lockfile now
            if (!UpdateLockFile(root))
            {
                return false;
            }

            // Prune the packages folder only leaving things that are required
            if (!PrunePackages(root))
            {
                return false;
            }

            // If --wwwroot-out doesn't have a non-empty value, we don't need a public app folder in output
            if (string.IsNullOrEmpty(WwwRootOut))
            {
                return true;
            }

            var project = GetCurrentProject();

            // Construct path to public app folder, which contains content files and tool dlls
            // The name of public app folder is specified with "--appfolder" option
            // Default name of public app folder is the same as main project
            var wwwRootOutPath = Path.Combine(root.OutputPath, WwwRootOut);

            // Delete old public app folder because we don't want leftovers from previous operations
            root.Operations.Delete(wwwRootOutPath);
            Directory.CreateDirectory(wwwRootOutPath);

            // Copy content files (e.g. html, js and images) of main project into public app folder
            CopyContentFiles(root, project, wwwRootOutPath);

            return GenerateWebConfigFileForWwwRootOut(root, project, wwwRootOutPath);
        }
예제 #51
0
        /// <summary>
        /// This is a helper method for looking up directories that directly contains assemblies that would be loaded
        /// given the published runtime framework. We should run crossgen on these folders
        /// </summary>
        private IEnumerable<string> ResolveOutputAssemblies(PublishRoot root, NuGetDependencyResolver resolver)
        {
            var outputPathsMap = root.Packages
                .ToDictionary(
                    pkg => pkg.Library,
                    pkg => pkg.TargetPath
                );

            var result = new HashSet<string>();
            var libraryNotInOutput = new List<LibraryIdentity>();
            var missingOutputFolder = new List<string>();

            foreach (var dependency in resolver.PackageAssemblyLookup.Values)
            {
                var libId = dependency.Library.Identity;
                var libPath = dependency.Library.Path;
                var assemblyDir = Path.GetDirectoryName(dependency.Path);
                var assemblySelection = assemblyDir.Substring(libPath.Length);
                string outputLibLocation;
                if (!outputPathsMap.TryGetValue(libId, out outputLibLocation))
                {
                    libraryNotInOutput.Add(libId);
                    continue;
                }
                var output = outputLibLocation + assemblySelection;

                if (!Directory.Exists(output))
                {
                    missingOutputFolder.Add(output);
                }
                else
                {
                    result.Add(output);
                }
            }

            if (libraryNotInOutput.Any())
            {
                throw new InvalidOperationException(string.Format("Library {0} cannot be found in the published output.", string.Join(", ", libraryNotInOutput)));
            }

            if (missingOutputFolder.Any())
            {
                throw new InvalidOperationException("Published output does not contain directory:\n" + string.Join("\n", missingOutputFolder));
            }

            return result;
        }
예제 #52
0
        private void PrunePackages(PublishRoot root)
        {
            if (root.MainProjectLockFile == null)
            {
                return;
            }

            var resolver = new DefaultPackagePathResolver(root.TargetPackagesPath);

            var lockFilePath = Path.GetFullPath(Path.Combine(ApplicationBasePath, LockFileFormat.LockFileName));
            root.PublishedLockFile = new LockFileFormat().Read(lockFilePath);

            var filesToKeep = new HashSet<string>();
            var filesToRemove = new HashSet<string>();

            foreach (var target in root.PublishedLockFile.Targets)
            {
                foreach (var library in target.Libraries)
                {
                    var packageDir = resolver.GetInstallPath(library.Name, library.Version);

                    if (library.Name != root.MainProjectName && string.Equals(library.Type, Runtime.LibraryTypes.Package, StringComparison.OrdinalIgnoreCase))
                    {
                        filesToRemove.Add(resolver.GetHashPath(library.Name, library.Version));
                        filesToRemove.Add(resolver.GetPackageFilePath(library.Name, library.Version));
                        filesToRemove.AddRange(Directory.EnumerateFiles(packageDir, $"{library.Name}.xml", SearchOption.AllDirectories));
                    }

                    foreach (var path in library.RuntimeAssemblies)
                    {
                        filesToKeep.Add(Path.Combine(packageDir, path));
                    }
                    foreach (var path in library.CompileTimeAssemblies)
                    {
                        filesToKeep.Add(Path.Combine(packageDir, path));
                    }
                    foreach (var path in library.NativeLibraries)
                    {
                        filesToKeep.Add(Path.Combine(packageDir, path));
                    }
                    foreach (var path in library.ResourceAssemblies)
                    {
                        filesToKeep.Add(Path.Combine(packageDir, path));
                    }
                }
            }

            foreach (var target in root.MainProjectLockFile.Targets.Where(projectTarget =>
                string.IsNullOrEmpty(projectTarget.RuntimeIdentifier) &&
                !root.PublishedLockFile.Targets.Any(publishTarget =>
                projectTarget.TargetFramework == publishTarget.TargetFramework)))
            {
                foreach (var library in target.Libraries)
                {
                    var packageDir = resolver.GetInstallPath(library.Name, library.Version);

                    if (Directory.Exists(packageDir))
                    {
                        foreach (var path in library.RuntimeAssemblies)
                        {
                            filesToRemove.Add(Path.Combine(packageDir, path));
                        }
                        foreach (var path in library.CompileTimeAssemblies)
                        {
                            filesToRemove.Add(Path.Combine(packageDir, path));
                        }
                        foreach (var path in library.NativeLibraries)
                        {
                            filesToRemove.Add(Path.Combine(packageDir, path));
                        }
                        foreach (var path in library.ResourceAssemblies)
                        {
                            filesToRemove.Add(Path.Combine(packageDir, path));
                        }
                    }
                }
            }

            foreach (var file in filesToRemove.Except(filesToKeep))
            {
                File.Delete(file);
            }

            if (Directory.Exists(root.TargetPackagesPath))
            {
                root.Operations.DeleteEmptyFolders(root.TargetPackagesPath);
            }

            return;
        }
예제 #53
0
        private bool UpdateLockFile(PublishRoot root)
        {
            var appEnv = (IApplicationEnvironment)root.HostServices.GetService(typeof(IApplicationEnvironment));

            var feedOptions = new FeedOptions();
            feedOptions.IgnoreFailedSources = true;
            feedOptions.Sources.Add(root.TargetPackagesPath);
            feedOptions.TargetPackagesFolder = root.TargetPackagesPath;

            var tasks = new Task<bool>[root.Projects.Count];
            for (int i = 0; i < root.Projects.Count; i++)
            {
                var project = root.Projects[i];
                var restoreCommand = new RestoreCommand(appEnv);

                foreach (var runtime in root.Runtimes)
                {
                    restoreCommand.TargetFrameworks.Add(project.SelectFrameworkForRuntime(runtime));
                }

                var restoreDirectory = project.IsPackage ? Path.Combine(project.TargetPath, "root") : project.TargetPath;
                restoreCommand.SkipRestoreEvents = true;
                restoreCommand.SkipInstall = true;
                // This is a workaround for #1322. Since we use restore to generate the lock file
                // after publish, it's possible to fail restore after copying the closure
                // if framework assemblies and packages have the same name. This is more likely now
                // since dependencies may exist in the top level
                restoreCommand.IgnoreMissingDependencies = true;
                restoreCommand.CheckHashFile = false;
                restoreCommand.RestoreDirectories.Add(restoreDirectory);
                restoreCommand.FeedOptions = feedOptions;

                // Mute "dnu restore" subcommand
                restoreCommand.Reports = Reports.Constants.NullReports;

                tasks[i] = restoreCommand.Execute();
            }

            Task.WaitAll(tasks);

            return tasks.All(t => t.Result);
        }
예제 #54
0
        private bool TryAddRuntime(PublishRoot root, FrameworkName frameworkName, string runtimePath)
        {
            if (!Directory.Exists(runtimePath))
            {
                return false;
            }

            root.Runtimes.Add(new PublishRuntime(root, frameworkName, runtimePath));
            root.Frameworks.Add(frameworkName, null);
            return true;
        }
예제 #55
0
        private async Task<bool> Restore(PublishRoot root, PublishProject publishProject, string restoreDirectory, IEnumerable<FrameworkName> targetFrameworks)
        {
            var appEnv = PlatformServices.Default.Application;

            var feedOptions = new FeedOptions();
            feedOptions.IgnoreFailedSources = true;
            feedOptions.Sources.Add(root.TargetPackagesPath);
            feedOptions.TargetPackagesFolder = root.TargetPackagesPath;

            var restoreCommand = new RestoreCommand(appEnv);

            restoreCommand.TargetFrameworks.AddRange(targetFrameworks);
            restoreCommand.RequestedRuntimes = root.RuntimeIdentifiers;
            restoreCommand.SkipRestoreEvents = true;
            restoreCommand.SkipInstall = true;
            // This is a workaround for #1322. Since we use restore to generate the lock file
            // after publish, it's possible to fail restore after copying the closure
            // if framework assemblies and packages have the same name. This is more likely now
            // since dependencies may exist in the top level
            restoreCommand.IgnoreMissingDependencies = true;
            restoreCommand.CheckHashFile = false;
            restoreCommand.RestoreDirectories.Add(restoreDirectory);
            restoreCommand.FeedOptions = feedOptions;

            // Mute "dnu restore" subcommand
            restoreCommand.Reports = Reports.Constants.NullReports;

            var success = await restoreCommand.Execute();
            return success;
        }
예제 #56
0
        private void CopyContentFiles(PublishRoot root, Runtime.Project project, string targetFolderPath)
        {
            root.Reports.Quiet.WriteLine("Copying contents of {0} dependency {1} to {2}",
                _projectDescription.Type, _projectDescription.Identity.Name, targetFolderPath);

            var contentSourcePath = GetWwwRootSourcePath(project.ProjectDirectory, WwwRoot);

            root.Reports.Quiet.WriteLine("  Source {0}", contentSourcePath);
            root.Reports.Quiet.WriteLine("  Target {0}", targetFolderPath);

            if (Directory.Exists(contentSourcePath))
            {
                root.Operations.Copy(contentSourcePath, targetFolderPath);
            }
        }
예제 #57
0
        public bool Publish()
        {
            var warnings = new List<DiagnosticMessage>();
            Runtime.Project project;
            if (!Runtime.Project.TryGetProject(_options.ProjectDir, out project, warnings))
            {
                _options.Reports.Error.WriteLine("Unable to locate {0}.".Red(), Runtime.Project.ProjectFileName);
                return false;
            }

            foreach (var warning in warnings)
            {
                _options.Reports.Information.WriteLine(warning.FormattedMessage.Yellow());
            }

            // '--wwwroot' option can override 'webroot' property in project.json
            _options.WwwRoot = _options.WwwRoot ?? project.WebRoot;
            _options.WwwRootOut = _options.WwwRootOut ?? _options.WwwRoot;

            if (string.IsNullOrEmpty(_options.WwwRoot) && !string.IsNullOrEmpty(_options.WwwRootOut))
            {
                _options.Reports.Error.WriteLine(
                    "'--wwwroot-out' option can be used only when the '--wwwroot' option or 'webroot' in project.json is specified.".Red());
                return false;
            }

            if (string.Equals(_options.WwwRootOut, PublishRoot.AppRootName, StringComparison.OrdinalIgnoreCase))
            {
                _options.Reports.Error.WriteLine(
                    "'{0}' is a reserved folder name. Please choose another name for the wwwroot-out folder.".Red(),
                    PublishRoot.AppRootName);
                return false;
            }

            var sw = Stopwatch.StartNew();

            string outputPath = _options.OutputDir;

            var projectDir = project.ProjectDirectory;

            var frameworkContexts = new Dictionary<FrameworkName, DependencyContext>();

            var root = new PublishRoot(project, outputPath, _hostServices, _options.Reports)
            {
                Configuration = _options.Configuration,
                NoSource = _options.NoSource,
                IncludeSymbols = _options.IncludeSymbols
            };

            Func<string, string> getVariable = key =>
            {
                return null;
            };

            if (!ScriptExecutor.Execute(project, "prepare", getVariable))
            {
                _options.Reports.Error.WriteLine(ScriptExecutor.ErrorMessage);
                return false;
            }

            if (!ScriptExecutor.Execute(project, "prepublish", getVariable))
            {
                _options.Reports.Error.WriteLine(ScriptExecutor.ErrorMessage);
                return false;
            }

            if (!ResolveActualRuntimeNames(_options.Runtimes))
            {
                return false;
            }

            foreach (var runtime in _options.Runtimes)
            {
                // Calculate the runtime name by taking the last path segment (since it could be a path),
                // but first strip off any trailing '\' or '/' in case the path provided was something like
                //  "C:\Foo\Bar\dnx-clr-win-x64...\"
                var runtimeName = new DirectoryInfo(runtime).Name;
                var frameworkName = DependencyContext.SelectFrameworkNameForRuntime(
                    project.GetTargetFrameworks().Select(x => x.FrameworkName),
                    runtimeName);

                if (frameworkName == null)
                {
                    _options.Reports.Error.WriteLine(
                        "The project being published does not support the runtime '{0}'",
                        runtime.ToString().Red().Bold());
                    return false;
                }

                var runtimeLocated = TryAddRuntime(root, frameworkName, runtime);
                List<string> runtimeProbePaths = null;

                if (!runtimeLocated)
                {
                    runtimeProbePaths = new List<string>();
                    runtimeProbePaths.Add(runtime);
                    var runtimeHome = Environment.GetEnvironmentVariable(EnvironmentNames.Home);
                    if (string.IsNullOrEmpty(runtimeHome))
                    {
                        var runtimeGlobalPath = DnuEnvironment.GetFolderPath(DnuFolderPath.DnxGlobalPath);
                        var defaultRuntimeHome = DnuEnvironment.GetFolderPath(DnuFolderPath.DefaultDnxHome);
                        runtimeHome = $"{defaultRuntimeHome};{runtimeGlobalPath}";
                    }

                    foreach (var portion in runtimeHome.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
                    {
                        var packagesPath = Path.Combine(
                            Environment.ExpandEnvironmentVariables(portion),
                            "runtimes",
                            runtime);

                        if (TryAddRuntime(root, frameworkName, packagesPath))
                        {
                            runtimeLocated = true;
                            break;
                        }

                        runtimeProbePaths.Add(packagesPath);
                    }
                }

                if (!runtimeLocated)
                {
                    _options.Reports.Error.WriteLine(string.Format("Unable to locate runtime '{0}'", runtime.Red().Bold()));
                    if (runtimeProbePaths != null)
                    {
                        _options.Reports.Error.WriteLine(string.Format("Locations probed:{0}{1}", Environment.NewLine, string.Join(Environment.NewLine, runtimeProbePaths)));
                    }
                    return false;
                }

                if (!frameworkContexts.ContainsKey(frameworkName))
                {
                    frameworkContexts[frameworkName] = CreateDependencyContext(project, frameworkName);
                }
            }

            // If there is no target framework filter specified with '--runtime',
            // the published output targets all frameworks specified in project.json
            if (!_options.Runtimes.Any())
            {
                foreach (var frameworkInfo in project.GetTargetFrameworks())
                {
                    if (!frameworkContexts.ContainsKey(frameworkInfo.FrameworkName))
                    {
                        frameworkContexts[frameworkInfo.FrameworkName] =
                            CreateDependencyContext(project, frameworkInfo.FrameworkName);
                    }
                }
            }

            if (!frameworkContexts.Any())
            {
                // We can only get here if the project has no frameworks section, which we don't actually support any more
                _options.Reports.Error.WriteLine("The project being published has no frameworks listed in the 'frameworks' section.");
                return false;
            }

            root.SourcePackagesPath = frameworkContexts.First().Value.PackagesDirectory;

            bool anyUnresolvedDependency = false;
            foreach (var dependencyContext in frameworkContexts.Values)
            {
                // If there's any unresolved dependencies then complain and keep working
                if (dependencyContext.DependencyWalker.Libraries.Any(l => !l.Resolved))
                {
                    anyUnresolvedDependency = true;
                    var message = "Warning: " +
                        dependencyContext.DependencyWalker.GetMissingDependenciesWarning(
                            dependencyContext.FrameworkName);
                    _options.Reports.Quiet.WriteLine(message.Yellow());
                }

                foreach (var libraryDescription in dependencyContext.NuGetDependencyResolver.Dependencies)
                {
                    IList<DependencyContext> contexts;
                    if (!root.LibraryDependencyContexts.TryGetValue(libraryDescription.Identity, out contexts))
                    {
                        root.Packages.Add(new PublishPackage(libraryDescription));
                        contexts = new List<DependencyContext>();
                        root.LibraryDependencyContexts[libraryDescription.Identity] = contexts;
                    }
                    contexts.Add(dependencyContext);
                }

                foreach (var libraryDescription in dependencyContext.ProjectReferenceDependencyProvider.Dependencies)
                {
                    if (!root.Projects.Any(p => p.Name == libraryDescription.Identity.Name))
                    {
                        var publishProject = new PublishProject(
                            dependencyContext.ProjectReferenceDependencyProvider,
                            dependencyContext.ProjectResolver,
                            libraryDescription);

                        if (publishProject.Name == project.Name)
                        {
                            publishProject.WwwRoot = _options.WwwRoot;
                            publishProject.WwwRootOut = _options.WwwRootOut;
                        }
                        root.Projects.Add(publishProject);
                    }
                }
            }

            NativeImageGenerator nativeImageGenerator = null;
            if (_options.Native)
            {
                nativeImageGenerator = NativeImageGenerator.Create(_options, root, frameworkContexts.Values);
                if (nativeImageGenerator == null)
                {
                    _options.Reports.Error.WriteLine("Fail to initiate native image generation process.".Red());
                    return false;
                }
            }

            var success = root.Emit();

            if (!ScriptExecutor.Execute(project, "postpublish", getVariable))
            {
                _options.Reports.Error.WriteLine(ScriptExecutor.ErrorMessage);
                return false;
            }

            if (_options.Native && !nativeImageGenerator.BuildNativeImages(root))
            {
                _options.Reports.Error.WriteLine("Native image generation failed.");
                return false;
            }

            sw.Stop();

            _options.Reports.Information.WriteLine("Time elapsed {0}", sw.Elapsed);
            return !anyUnresolvedDependency && success;
        }
예제 #58
0
        private void CopyProject(PublishRoot root, Runtime.Project project, string targetPath, bool includeSource)
        {
            var additionalExcluding = new List<string>();

            // If a public folder is specified with 'webroot' or '--wwwroot', we ignore it when copying project files
            var wwwRootPath = string.Empty;
            if (!string.IsNullOrEmpty(WwwRoot))
            {
                wwwRootPath = Path.GetFullPath(Path.Combine(project.ProjectDirectory, WwwRoot));
                wwwRootPath = PathUtility.EnsureTrailingSlash(wwwRootPath);
            }

            // If project root is used as value of '--wwwroot', we shouldn't exclude it when copying
            if (string.Equals(wwwRootPath, PathUtility.EnsureTrailingSlash(project.ProjectDirectory)))
            {
                wwwRootPath = string.Empty;
            }

            if (!string.IsNullOrEmpty(wwwRootPath))
            {
                additionalExcluding.Add(wwwRootPath.Substring(PathUtility.EnsureTrailingSlash(project.ProjectDirectory).Length));
            }

            var sourceFiles = project.Files.GetFilesForBundling(includeSource, additionalExcluding);
            root.Operations.Copy(sourceFiles, project.ProjectDirectory, targetPath);
        }
예제 #59
0
        public bool Publish()
        {
            var warnings = new List<DiagnosticMessage>();
            Runtime.Project project;
            if (!Runtime.Project.TryGetProject(_options.ProjectDir, out project, warnings))
            {
                _options.Reports.Error.WriteLine("Unable to locate {0}.".Red(), Runtime.Project.ProjectFileName);
                return false;
            }

            foreach (var warning in warnings)
            {
                _options.Reports.Information.WriteLine(warning.FormattedMessage.Yellow());
            }

            if (string.IsNullOrEmpty(_options.WwwRoot) && File.Exists(Path.Combine(project.ProjectDirectory, "hosting.json")))
            {
                var jsonObj = JObject.Parse(File.ReadAllText(Path.Combine(project.ProjectDirectory, "hosting.json")));
                _options.WwwRoot = PublishOperations.GetWebRootJson(jsonObj)?.ToString();
            }

            if (string.IsNullOrEmpty(_options.WwwRoot) && Directory.Exists(Path.Combine(project.ProjectDirectory, "wwwroot")))
            {
                _options.WwwRoot = "wwwroot";
            }

            _options.WwwRoot = _options.WwwRoot ?? "";
            _options.WwwRootOut = _options.WwwRootOut ?? _options.WwwRoot;

            if (string.IsNullOrEmpty(_options.WwwRoot) && !string.IsNullOrEmpty(_options.WwwRootOut))
            {
                _options.Reports.Error.WriteLine(
                    "'--wwwroot-out' option can be used only when the '--wwwroot' option or 'webroot' in project.json is specified.".Red());
                return false;
            }

            if (string.Equals(_options.WwwRootOut, PublishRoot.AppRootName, StringComparison.OrdinalIgnoreCase))
            {
                _options.Reports.Error.WriteLine(
                    "'{0}' is a reserved folder name. Please choose another name for the wwwroot-out folder.".Red(),
                    PublishRoot.AppRootName);
                return false;
            }

            var sw = Stopwatch.StartNew();

            string outputPath = _options.OutputDir;

            var projectDir = project.ProjectDirectory;

            var frameworkContexts = new Dictionary<Tuple<FrameworkName, string>, DependencyContext>();

            var root = new PublishRoot(project, outputPath, _options.Reports)
            {
                Configuration = _options.Configuration,
                NoSource = _options.NoSource,
                IncludeSymbols = _options.IncludeSymbols,
                IISCommand = _options.IISCommand
            };

            Func<string, string> getVariable = key =>
            {
                return null;
            };

            if (!ScriptExecutor.Execute(project, "prepare", getVariable))
            {
                _options.Reports.Error.WriteLine(ScriptExecutor.ErrorMessage);
                return false;
            }

            if (!ScriptExecutor.Execute(project, "prepublish", getVariable))
            {
                _options.Reports.Error.WriteLine(ScriptExecutor.ErrorMessage);
                return false;
            }

            if (!ResolveActualRuntimeNames(_options.Runtimes))
            {
                return false;
            }

            foreach (var runtime in _options.Runtimes)
            {
                // Calculate the runtime name by taking the last path segment (since it could be a path),
                // but first strip off any trailing '\' or '/' in case the path provided was something like
                //  "C:\Foo\Bar\dnx-clr-win-x64...\"
                var runtimeName = new DirectoryInfo(runtime).Name;
                var frameworkName = DependencyContext.SelectFrameworkNameForRuntime(
                    project.GetTargetFrameworks().Select(x => x.FrameworkName),
                    runtimeName);
                if (frameworkName == null)
                {
                    _options.Reports.Error.WriteLine(
                        "The project being published does not support the runtime '{0}'",
                        runtime.ToString().Red().Bold());
                    return false;
                }


                var runtimeLocated = TryAddRuntime(root, frameworkName, runtime);
                List<string> runtimeProbePaths = null;

                if (!runtimeLocated)
                {
                    runtimeProbePaths = new List<string>();
                    runtimeProbePaths.Add(runtime);
                    var runtimeHome = Environment.GetEnvironmentVariable(EnvironmentNames.Home);
                    var pathSeparator = Path.PathSeparator;
                    if (string.IsNullOrEmpty(runtimeHome))
                    {
                        var runtimeGlobalPath = DnuEnvironment.GetFolderPath(DnuFolderPath.DnxGlobalPath);
                        var defaultRuntimeHome = DnuEnvironment.GetFolderPath(DnuFolderPath.DefaultDnxHome);
                        runtimeHome = $"{defaultRuntimeHome}{pathSeparator}{runtimeGlobalPath}";
                    }

                    foreach (var portion in runtimeHome.Split(new[] { pathSeparator }, StringSplitOptions.RemoveEmptyEntries))
                    {
                        var packagesPath = Path.Combine(
                            Environment.ExpandEnvironmentVariables(portion),
                            "runtimes",
                            runtime);

                        if (TryAddRuntime(root, frameworkName, packagesPath))
                        {
                            runtimeLocated = true;
                            break;
                        }

                        runtimeProbePaths.Add(packagesPath);
                    }
                }

                if (!runtimeLocated)
                {
                    _options.Reports.Error.WriteLine(string.Format("Unable to locate runtime '{0}'", runtime.Red().Bold()));
                    if (runtimeProbePaths != null)
                    {
                        _options.Reports.Error.WriteLine(string.Format("Locations probed:{0}{1}", Environment.NewLine, string.Join(Environment.NewLine, runtimeProbePaths)));
                    }
                    return false;
                }

                if (!frameworkContexts.ContainsKey(Tuple.Create(frameworkName, string.Empty)))
                {
                    frameworkContexts[Tuple.Create(frameworkName, string.Empty)] = CreateDependencyContext(project, frameworkName, Enumerable.Empty<string>());
                }

                foreach (var rid in DependencyContext.GetRuntimeIdentifiers(runtimeName))
                {
                    root.RuntimeIdentifiers.Add(rid);
                    if (!frameworkContexts.ContainsKey(Tuple.Create(frameworkName, rid)))
                    {
                        frameworkContexts[Tuple.Create(frameworkName, rid)] = CreateDependencyContext(project, frameworkName, new[] { rid });
                    }
                }
            }

            // If there is no target framework filter specified with '--runtime',
            // the published output targets all frameworks specified in project.json
            if (!_options.Runtimes.Any())
            {
                IEnumerable<FrameworkName> frameworksToPublish;

                if (!_options.TargetFrameworks.Any())
                {
                    frameworksToPublish = project
                            .GetTargetFrameworks()
                            .Select(fx => fx.FrameworkName);
                }
                else
                {
                    string frameworkSelectionError;
                    frameworksToPublish = FrameworkSelectionHelper.SelectFrameworks(project,
                                                                       _options.TargetFrameworks,
                                                                       _applicationEnvironment.RuntimeFramework,
                                                                       out frameworkSelectionError)?.ToList();
                    if (frameworksToPublish == null)
                    {
                        _options.Reports.WriteError(frameworkSelectionError);
                        return false;
                    }

                    foreach (var framework in frameworksToPublish)
                    {
                        root.Frameworks.Add(framework, null);
                    }
                }

                // Add runtime IDs for the currently running platform
                foreach (var runtime in PlatformServices.Default.Runtime.GetDefaultRestoreRuntimes())
                {
                    root.RuntimeIdentifiers.Add(runtime);
                }

                foreach (var framework in frameworksToPublish)
                {
                    if (!frameworkContexts.ContainsKey(Tuple.Create(framework, string.Empty)))
                    {
                        frameworkContexts[Tuple.Create(framework, string.Empty)] = CreateDependencyContext(project, framework, Enumerable.Empty<string>());
                    }

                    foreach (var rid in RuntimeEnvironmentHelper.RuntimeEnvironment.GetDefaultRestoreRuntimes())
                    {
                        root.RuntimeIdentifiers.Add(rid);
                        if (!frameworkContexts.ContainsKey(Tuple.Create(framework, rid)))
                        {
                            frameworkContexts[Tuple.Create(framework, rid)] = CreateDependencyContext(project, framework, new[] { rid });
                        }
                    }
                }
            }

            if (!frameworkContexts.Any())
            {
                // We can only get here if the project has no frameworks section, which we don't actually support any more
                _options.Reports.Error.WriteLine("The project being published has no frameworks listed in the 'frameworks' section.");
                return false;
            }

            root.SourcePackagesPath = frameworkContexts.First().Value.PackagesDirectory;

            bool anyUnresolvedDependency = false;

            foreach (var dependencyContext in frameworkContexts.Values)
            {
                foreach (var library in dependencyContext.LibraryManager.GetLibraryDescriptions())
                {
                    if (!library.Resolved)
                    {
                        // If there's any unresolved dependencies then complain and keep working
                        _options.Reports.Quiet.WriteLine("  Unable to resolve dependency {0}", library.Identity.ToString().Red().Bold());
                        anyUnresolvedDependency = true;
                    }
                    else
                    {
                        if (library.Type == Runtime.LibraryTypes.Project)
                        {
                            if (!root.Projects.Any(p => p.Library.Name == library.Identity.Name))
                            {
                                var publishProject = new PublishProject((ProjectDescription)library);

                                if (publishProject.Library.Name == project.Name)
                                {
                                    publishProject.WwwRoot = _options.WwwRoot;
                                    publishProject.WwwRootOut = _options.WwwRootOut;
                                }
                                root.Projects.Add(publishProject);
                            }
                        }
                        else if (library.Type == Runtime.LibraryTypes.Package)
                        {
                            if (!root.Packages.Any(p => p.Library.Name == library.Identity.Name && p.Library.Version == library.Identity.Version))
                            {
                                root.Packages.Add(new PublishPackage((PackageDescription)library));
                            }
                        }
                    }
                }
            }

            NativeImageGenerator nativeImageGenerator = null;
            if (_options.Native)
            {
                nativeImageGenerator = NativeImageGenerator.Create(_options, root, frameworkContexts.Values);
                if (nativeImageGenerator == null)
                {
                    _options.Reports.Error.WriteLine("Fail to initiate native image generation process.".Red());
                    return false;
                }
            }

            var success = root.Emit();

            if (!ScriptExecutor.Execute(project, "postpublish", getVariable))
            {
                _options.Reports.Error.WriteLine(ScriptExecutor.ErrorMessage);
                return false;
            }

            if (_options.Native && !nativeImageGenerator.BuildNativeImages(root))
            {
                _options.Reports.Error.WriteLine("Native image generation failed.");
                return false;
            }

            sw.Stop();

            _options.Reports.Information.WriteLine("Time elapsed {0}", sw.Elapsed);
            return !anyUnresolvedDependency && success;
        }
예제 #60
0
        private bool EmitNupkg(PublishRoot root)
        {
            root.Reports.Quiet.WriteLine("  Packing nupkg from {0} dependency {1}",
                                         _projectDescription.Type, _projectDescription.Identity.Name);

            IsPackage = true;

            var project     = GetCurrentProject();
            var resolver    = new DefaultPackagePathResolver(root.TargetPackagesPath);
            var targetNupkg = resolver.GetPackageFileName(project.Name, project.Version);

            TargetPath = resolver.GetInstallPath(project.Name, project.Version);

            root.Reports.Quiet.WriteLine("    Source {0}", _projectDescription.Path.Bold());
            root.Reports.Quiet.WriteLine("    Target {0}", TargetPath);

            if (Directory.Exists(TargetPath))
            {
                root.Operations.Delete(TargetPath);
            }

            // If this is a wrapper project, we need to generate a lock file before building it
            if (IsWrappingAssembly())
            {
                var success = Restore(root, publishProject: this, restoreDirectory: project.ProjectDirectory)
                              .GetAwaiter().GetResult();
                if (!success)
                {
                    return(false);
                }
            }

            // Generate nupkg from this project dependency
            var buildOptions = new BuildOptions();

            buildOptions.ProjectPatterns.Add(project.ProjectDirectory);
            buildOptions.OutputDir = Path.Combine(project.ProjectDirectory, "bin");
            buildOptions.Configurations.Add(root.Configuration);
            buildOptions.GeneratePackages = true;
            buildOptions.Reports          = root.Reports.ShallowCopy();

            // Mute "dnu pack" completely if it is invoked by "dnu publish --quiet"
            buildOptions.Reports.Information = root.Reports.Quiet;

            var buildManager = new BuildManager(root.HostServices, buildOptions);

            if (!buildManager.Build())
            {
                return(false);
            }

            // Extract the generated nupkg to target path
            var srcNupkgPath        = Path.Combine(buildOptions.OutputDir, root.Configuration, targetNupkg);
            var srcSymbolsNupkgPath = Path.ChangeExtension(srcNupkgPath, "symbols.nupkg");

            var options = new Packages.AddOptions
            {
                NuGetPackage   = root.IncludeSymbols ? srcSymbolsNupkgPath : srcNupkgPath,
                SourcePackages = root.TargetPackagesPath,
                Reports        = root.Reports
            };

            var packagesAddCommand = new Packages.AddCommand(options);

            packagesAddCommand.Execute().GetAwaiter().GetResult();

            // Copy content files (e.g. html, js and images) of main project into "root" folder of the exported package
            var rootFolderPath  = Path.Combine(TargetPath, "root");
            var rootProjectJson = Path.Combine(rootFolderPath, Runtime.Project.ProjectFileName);

            root.Operations.Delete(rootFolderPath);
            CopyProject(root, project, rootFolderPath, includeSource: false);

            UpdateWebRoot(root, rootFolderPath);

            UpdateJson(rootProjectJson, jsonObj =>
            {
                // Update the project entrypoint
                jsonObj["entryPoint"] = _projectDescription.Identity.Name;

                // Set mark this as non loadable
                jsonObj["loadable"] = false;

                // Update the dependencies node to reference the main project
                var deps = new JObject();
                jsonObj["dependencies"] = deps;

                deps[_projectDescription.Identity.Name] = _projectDescription.Identity.Version.ToString();
            });

            var appBase = Path.Combine(PublishRoot.AppRootName, "packages", resolver.GetPackageDirectory(_projectDescription.Identity.Name, _projectDescription.Identity.Version), "root");

            _relativeAppBase    = Path.Combine("..", appBase);
            ApplicationBasePath = Path.Combine(root.OutputPath, appBase);

            root.Reports.Quiet.WriteLine("Removing {0}", srcNupkgPath);
            File.Delete(srcNupkgPath);

            root.Reports.Quiet.WriteLine("Removing {0}", srcSymbolsNupkgPath);
            File.Delete(srcSymbolsNupkgPath);

            return(true);
        }