Beispiel #1
0
        /// <summary>
        /// Create a <see cref="RuntimeHostBuilder"/> for the project in the specified
        /// <paramref name="projectDirectory"/>, using the default configuration.
        /// </summary>
        /// <remarks>
        /// This method will throw if the project.json file cannot be found in the
        /// specified folder. If a project.lock.json file is present in the directory
        /// it will be loaded.
        /// </remarks>
        /// <param name="projectDirectory">The directory of the project to host</param>
        public static RuntimeHostBuilder ForProjectDirectory(string projectDirectory, NuGetFramework runtimeFramework, IServiceProvider services)
        {
            if (string.IsNullOrEmpty(projectDirectory))
            {
                throw new ArgumentNullException(nameof(projectDirectory));
            }
            if (runtimeFramework == null)
            {
                throw new ArgumentNullException(nameof(runtimeFramework));
            }

            var log         = RuntimeLogging.Logger <RuntimeHostBuilder>();
            var hostBuilder = new RuntimeHostBuilder();

            // Load the Project
            var         projectResolver = new PackageSpecResolver(projectDirectory);
            PackageSpec packageSpec;

            if (projectResolver.TryResolvePackageSpec(GetProjectName(projectDirectory), out packageSpec))
            {
                log.LogVerbose($"Loaded project {packageSpec.Name}");
                hostBuilder.Project = new Project(packageSpec);
            }
            hostBuilder.GlobalSettings = projectResolver.GlobalSettings;

            // Load the Lock File if present
            LockFile lockFile;

            if (TryReadLockFile(projectDirectory, out lockFile))
            {
                log.LogVerbose($"Loaded lock file");
                hostBuilder.LockFile = lockFile;
            }

            // Set the framework and other components
            hostBuilder.TargetFramework     = runtimeFramework;
            hostBuilder.Services            = services;
            hostBuilder.PackagePathResolver = new PackagePathResolver(
                ResolveRepositoryPath(hostBuilder.GlobalSettings),
                GetCachePaths());

            log.LogVerbose("Registering PackageSpecReferenceDependencyProvider");
            hostBuilder.DependencyProviders.Add(new PackageSpecReferenceDependencyProvider(projectResolver));

            if (hostBuilder.LockFile != null)
            {
                log.LogVerbose("Registering LockFileDependencyProvider");
                hostBuilder.DependencyProviders.Add(new LockFileDependencyProvider(hostBuilder.LockFile));
            }

            log.LogVerbose("Registering ReferenceAssemblyDependencyProvider");
            var referenceResolver = new FrameworkReferenceResolver();

            hostBuilder.DependencyProviders.Add(new ReferenceAssemblyDependencyProvider(referenceResolver));

            // GAC resolver goes here! :)

            return(hostBuilder);
        }
        private async Task <IEnumerable <RestoreTargetGraph> > ExecuteRestoreAsync(NuGetv3LocalRepository localRepository,
                                                                                   RemoteWalkContext context,
                                                                                   CancellationToken token)
        {
            if (_request.Project.TargetFrameworks.Count == 0)
            {
                _logger.LogError(string.Format(CultureInfo.CurrentCulture, Strings.Log_ProjectDoesNotSpecifyTargetFrameworks, _request.Project.Name, _request.Project.FilePath));
                _success = false;
                return(Enumerable.Empty <RestoreTargetGraph>());
            }

            _logger.LogMinimal(string.Format(CultureInfo.CurrentCulture, Strings.Log_RestoringPackages, _request.Project.FilePath));

            // External references
            var updatedExternalProjects = new List <ExternalProjectReference>(_request.ExternalProjects);

            if (_request.ExternalProjects.Count > 0)
            {
                // There should be at most one match in the external projects.
                var rootProjectMatches = _request.ExternalProjects.Where(proj =>
                                                                         string.Equals(
                                                                             _request.Project.Name,
                                                                             proj.PackageSpecProjectName,
                                                                             StringComparison.OrdinalIgnoreCase))
                                         .ToList();

                if (rootProjectMatches.Count > 1)
                {
                    throw new InvalidOperationException($"Ambiguous project name '{_request.Project.Name}'.");
                }

                var rootProject = rootProjectMatches.SingleOrDefault();

                if (rootProject != null)
                {
                    // Replace the project spec with the passed in package spec,
                    // for installs which are done in memory first this will be
                    // different from the one on disk
                    updatedExternalProjects.RemoveAll(project =>
                                                      project.UniqueName.Equals(rootProject.UniqueName, StringComparison.Ordinal));

                    var updatedReference = new ExternalProjectReference(
                        rootProject.UniqueName,
                        _request.Project,
                        rootProject.MSBuildProjectPath,
                        rootProject.ExternalProjectReferences);

                    updatedExternalProjects.Add(updatedReference);

                    // Determine if the targets and props files should be written out.
                    context.IsMsBuildBased = XProjUtility.IsMSBuildBasedProject(rootProject.MSBuildProjectPath);
                }
                else
                {
                    Debug.Fail("RestoreRequest.ExternaProjects contains references, but does not contain the top level references. Add the project we are restoring for.");
                    throw new InvalidOperationException($"Missing external reference metadata for {_request.Project.Name}");
                }
            }

            // Load repositories

            // the external project provider is specific to the current restore project
            var projectResolver = new PackageSpecResolver(_request.Project);

            context.ProjectLibraryProviders.Add(
                new PackageSpecReferenceDependencyProvider(projectResolver, updatedExternalProjects, _logger));

            var remoteWalker = new RemoteDependencyWalker(context);

            var projectRange = new LibraryRange()
            {
                Name           = _request.Project.Name,
                VersionRange   = new VersionRange(_request.Project.Version),
                TypeConstraint = LibraryDependencyTarget.Project | LibraryDependencyTarget.ExternalProject
            };

            // Resolve dependency graphs
            var allInstalledPackages         = new HashSet <LibraryIdentity>();
            var allGraphs                    = new List <RestoreTargetGraph>();
            var runtimeIds                   = RequestRuntimeUtility.GetRestoreRuntimes(_request);
            var projectFrameworkRuntimePairs = CreateFrameworkRuntimePairs(_request.Project, runtimeIds);

            var projectRestoreRequest = new ProjectRestoreRequest(
                _request,
                _request.Project,
                _request.ExistingLockFile,
                _runtimeGraphCache,
                _runtimeGraphCacheByPackage);
            var projectRestoreCommand = new ProjectRestoreCommand(_logger, projectRestoreRequest);
            var result = await projectRestoreCommand.TryRestore(
                projectRange,
                projectFrameworkRuntimePairs,
                allInstalledPackages,
                localRepository,
                remoteWalker,
                context,
                writeToLockFile : true,
                token : token);

            var success  = result.Item1;
            var runtimes = result.Item3;

            allGraphs.AddRange(result.Item2);

            _success = success;

            // Calculate compatibility profiles to check by merging those defined in the project with any from the command line
            foreach (var profile in _request.Project.RuntimeGraph.Supports)
            {
                CompatibilityProfile compatProfile;
                if (profile.Value.RestoreContexts.Any())
                {
                    // Just use the contexts from the project definition
                    compatProfile = profile.Value;
                }
                else if (!runtimes.Supports.TryGetValue(profile.Value.Name, out compatProfile))
                {
                    // No definition of this profile found, so just continue to the next one
                    _logger.LogWarning(string.Format(CultureInfo.CurrentCulture, Strings.Log_UnknownCompatibilityProfile, profile.Key));
                    continue;
                }

                foreach (var pair in compatProfile.RestoreContexts)
                {
                    _logger.LogDebug($" {profile.Value.Name} -> +{pair}");
                    _request.CompatibilityProfiles.Add(pair);
                }
            }

            // Walk additional runtime graphs for supports checks
            if (_success && _request.CompatibilityProfiles.Any())
            {
                var compatibilityResult = await projectRestoreCommand.TryRestore(projectRange,
                                                                                 _request.CompatibilityProfiles,
                                                                                 allInstalledPackages,
                                                                                 localRepository,
                                                                                 remoteWalker,
                                                                                 context,
                                                                                 writeToLockFile : false,
                                                                                 token : token);

                _success = compatibilityResult.Item1;

                // TryRestore may contain graphs that are already in allGraphs if the
                // supports section contains the same TxM as the project framework.
                var currentGraphs = new HashSet <KeyValuePair <NuGetFramework, string> >(
                    allGraphs.Select(graph => new KeyValuePair <NuGetFramework, string>(
                                         graph.Framework,
                                         graph.RuntimeIdentifier))
                    );

                foreach (var graph in compatibilityResult.Item2)
                {
                    var key = new KeyValuePair <NuGetFramework, string>(
                        graph.Framework,
                        graph.RuntimeIdentifier);

                    if (currentGraphs.Add(key))
                    {
                        allGraphs.Add(graph);
                    }
                }
            }

            return(allGraphs);
        }
Beispiel #3
0
        public int Main(string[] args)
        {
#if DEBUG
            if (args.Contains("--debug"))
            {
                args = args.Skip(1).ToArray();
                System.Diagnostics.Debugger.Launch();
            }
#endif

            // Set up logging
            _log = new CommandOutputLogger();

            var app = new CommandLineApplication();
            app.Name     = "nuget3";
            app.FullName = ".NET Package Manager";
            app.HelpOption("-h|--help");
            app.VersionOption("--version", GetType().GetTypeInfo().Assembly.GetName().Version.ToString());

            app.Command("restore", restore =>
            {
                restore.Description = "Restores packages for a project and writes a lock file";

                var sources           = restore.Option("-s|--source <source>", "Specifies a NuGet package source to use during the restore", CommandOptionType.MultipleValue);
                var packagesDirectory = restore.Option("--packages <packagesDirectory>", "Directory to install packages in", CommandOptionType.SingleValue);
                var parallel          = restore.Option("-p|--parallel <noneOrNumberOfParallelTasks>", $"The number of concurrent tasks to use when restoring. Defaults to {RestoreRequest.DefaultDegreeOfConcurrency}; pass 'none' to run without concurrency.", CommandOptionType.SingleValue);
                var projectFile       = restore.Argument("[project file]", "The path to the project to restore for, either a project.json or the directory containing it. Defaults to the current directory");

                restore.OnExecute(async() =>
                {
                    // Figure out the project directory
                    IEnumerable <string> externalProjects = null;

                    PackageSpec project;
                    var projectPath = Path.GetFullPath(projectFile.Value ?? ".");
                    if (string.Equals(PackageSpec.PackageSpecFileName, Path.GetFileName(projectPath), StringComparison.OrdinalIgnoreCase))
                    {
                        _log.LogVerbose($"Reading project file {projectFile.Value}");
                        projectPath = Path.GetDirectoryName(projectPath);
                        project     = JsonPackageSpecReader.GetPackageSpec(File.ReadAllText(projectFile.Value), Path.GetFileName(projectPath), projectFile.Value);
                    }
                    else if (MsBuildUtility.IsMsBuildBasedProject(projectPath))
                    {
#if DNXCORE50
                        throw new NotSupportedException();
#else
                        externalProjects = MsBuildUtility.GetProjectReferences(projectPath);

                        projectPath         = Path.GetDirectoryName(Path.GetFullPath(projectPath));
                        var packageSpecFile = Path.Combine(projectPath, PackageSpec.PackageSpecFileName);
                        project             = JsonPackageSpecReader.GetPackageSpec(File.ReadAllText(packageSpecFile), Path.GetFileName(projectPath), projectFile.Value);
                        _log.LogVerbose($"Reading project file {projectFile.Value}");
#endif
                    }
                    else
                    {
                        var file = Path.Combine(projectPath, PackageSpec.PackageSpecFileName);

                        _log.LogVerbose($"Reading project file {file}");
                        project = JsonPackageSpecReader.GetPackageSpec(File.ReadAllText(file), Path.GetFileName(projectPath), file);
                    }
                    _log.LogVerbose($"Loaded project {project.Name} from {project.FilePath}");

                    // Resolve the root directory
                    var rootDirectory = PackageSpecResolver.ResolveRootDirectory(projectPath);
                    _log.LogVerbose($"Found project root directory: {rootDirectory}");

                    // Resolve the packages directory
                    var packagesDir = packagesDirectory.HasValue() ?
                                      packagesDirectory.Value() :
                                      Path.Combine(Environment.GetEnvironmentVariable("USERPROFILE"), ".nuget", "packages");
                    _log.LogVerbose($"Using packages directory: {packagesDir}");

                    var packageSources = sources.Values.Select(s => new PackageSource(s));
                    if (!packageSources.Any())
                    {
                        var settings = Settings.LoadDefaultSettings(projectPath,
                                                                    configFileName: null,
                                                                    machineWideSettings: null);
                        var packageSourceProvider = new PackageSourceProvider(settings);
                        packageSources            = packageSourceProvider.LoadPackageSources();
                    }

                    var request = new RestoreRequest(
                        project,
                        packageSources,
                        packagesDir);

                    if (externalProjects != null)
                    {
                        foreach (var externalReference in externalProjects)
                        {
                            request.ExternalProjects.Add(
                                new ExternalProjectReference(
                                    externalReference,
                                    Path.Combine(Path.GetDirectoryName(externalReference), PackageSpec.PackageSpecFileName),
                                    projectReferences: Enumerable.Empty <string>()));
                        }
                    }


                    // Run the restore
                    if (parallel.HasValue())
                    {
                        int parallelDegree;
                        if (string.Equals(parallel.Value(), "none", StringComparison.OrdinalIgnoreCase))
                        {
                            request.MaxDegreeOfConcurrency = 1;
                        }
                        else if (int.TryParse(parallel.Value(), out parallelDegree))
                        {
                            request.MaxDegreeOfConcurrency = parallelDegree;
                        }
                    }
                    if (request.MaxDegreeOfConcurrency <= 1)
                    {
                        _log.LogInformation("Running non-parallel restore");
                    }
                    else
                    {
                        _log.LogInformation($"Running restore with {request.MaxDegreeOfConcurrency} concurrent jobs");
                    }
                    var command = new RestoreCommand(_log);
                    var sw      = Stopwatch.StartNew();
                    var result  = await command.ExecuteAsync(request);
                    sw.Stop();

                    _log.LogInformation($"Restore completed in {sw.ElapsedMilliseconds:0.00}ms!");

                    return(0);
                });
            });

            app.Command("diag", diag =>
            {
                diag.Description = "Diagnostic commands for debugging package dependency graphs";
                diag.Command("lockfile", lockfile =>
                {
                    lockfile.Description = "Dumps data from the project lock file";

                    var project = lockfile.Option("--project <project>", "Path containing the project lockfile, or the patht to the lockfile itself", CommandOptionType.SingleValue);
                    var target  = lockfile.Option("--target <target>", "View information about a specific project target", CommandOptionType.SingleValue);
                    var library = lockfile.Argument("<library>", "Optionally, get detailed information about a specific library");

                    lockfile.OnExecute(() =>
                    {
                        var diagnostics = new DiagnosticCommands(_log);
                        var projectFile = project.HasValue() ? project.Value() : Path.GetFullPath(".");
                        return(diagnostics.Lockfile(projectFile, target.Value(), library.Value));
                    });
                });
                diag.OnExecute(() =>
                {
                    diag.ShowHelp();
                    return(0);
                });
            });

            app.OnExecute(() =>
            {
                app.ShowHelp();
                return(0);
            });

            return(app.Execute(args));
        }
Beispiel #4
0
        public async Task <RestoreResult> ExecuteAsync(RestoreRequest request)
        {
            if (request.Project.TargetFrameworks.Count == 0)
            {
                _log.LogError("The project does not specify any target frameworks!");
                return(new RestoreResult(success: false, restoreGraphs: Enumerable.Empty <RestoreTargetGraph>()));
            }

            var projectLockFilePath = string.IsNullOrEmpty(request.LockFilePath) ?
                                      Path.Combine(request.Project.BaseDirectory, LockFileFormat.LockFileName) :
                                      request.LockFilePath;

            _log.LogInformation($"Restoring packages for '{request.Project.FilePath}'");

            _log.LogWarning("TODO: Read and use lock file");

            // Load repositories
            var projectResolver = new PackageSpecResolver(request.Project.BaseDirectory);
            var nugetRepository = Repository.Factory.GetCoreV3(request.PackagesDirectory);

            var context = new RemoteWalkContext();

            context.ProjectLibraryProviders.Add(
                new LocalDependencyProvider(
                    new PackageSpecReferenceDependencyProvider(projectResolver)));

            if (request.ExternalProjects != null)
            {
                context.ProjectLibraryProviders.Add(
                    new LocalDependencyProvider(
                        new ExternalProjectReferenceDependencyProvider(request.ExternalProjects)));
            }

            context.LocalLibraryProviders.Add(
                new SourceRepositoryDependencyProvider(nugetRepository, _log));

            foreach (var provider in request.Sources.Select(s => CreateProviderFromSource(s, request.NoCache)))
            {
                context.RemoteLibraryProviders.Add(provider);
            }

            var remoteWalker = new RemoteDependencyWalker(context);

            var projectRange = new LibraryRange()
            {
                Name           = request.Project.Name,
                VersionRange   = new VersionRange(request.Project.Version),
                TypeConstraint = LibraryTypes.Project
            };

            // Resolve dependency graphs
            var frameworks = request.Project.TargetFrameworks.Select(f => f.FrameworkName).ToList();
            var graphs     = new List <RestoreTargetGraph>();

            foreach (var framework in frameworks)
            {
                graphs.Add(await WalkDependencies(projectRange, framework, remoteWalker, context));
            }

            if (graphs.Any(g => g.InConflict))
            {
                _log.LogError("Failed to resolve conflicts");
                return(new RestoreResult(success: false, restoreGraphs: graphs));
            }

            // Install the runtime-agnostic packages
            var allInstalledPackages = new HashSet <LibraryIdentity>();
            var localRepository      = new NuGetv3LocalRepository(request.PackagesDirectory, checkPackageIdCase: false);

            await InstallPackages(graphs, request.PackagesDirectory, allInstalledPackages, request.MaxDegreeOfConcurrency);

            // Resolve runtime dependencies
            var runtimeGraphs = new List <RestoreTargetGraph>();

            if (request.Project.RuntimeGraph.Runtimes.Count > 0)
            {
                foreach (var graph in graphs)
                {
                    var runtimeSpecificGraphs = await WalkRuntimeDependencies(projectRange, graph, request.Project.RuntimeGraph, remoteWalker, context, localRepository);

                    runtimeGraphs.AddRange(runtimeSpecificGraphs);
                }

                graphs.AddRange(runtimeGraphs);

                if (runtimeGraphs.Any(g => g.InConflict))
                {
                    _log.LogError("Failed to resolve conflicts");
                    return(new RestoreResult(success: false, restoreGraphs: graphs));
                }

                // Install runtime-specific packages
                await InstallPackages(runtimeGraphs, request.PackagesDirectory, allInstalledPackages, request.MaxDegreeOfConcurrency);
            }
            else
            {
                _log.LogVerbose("Skipping runtime dependency walk, no runtimes defined in project.json");
            }

            // Build the lock file
            var repository     = new NuGetv3LocalRepository(request.PackagesDirectory, checkPackageIdCase: false);
            var lockFile       = CreateLockFile(request.Project, graphs, repository);
            var lockFileFormat = new LockFileFormat();

            lockFileFormat.Write(projectLockFilePath, lockFile);

            return(new RestoreResult(true, graphs, lockFile));
        }
Beispiel #5
0
        public int Main(string[] args)
        {
#if DEBUG
            if (args.Contains("--debug"))
            {
                args = args.Skip(1).ToArray();
                System.Diagnostics.Debugger.Launch();
            }
#endif

            // Set up logging
            var loggerFactory = new LoggerFactory();
            loggerFactory.AddProvider(new CommandOutputLoggerProvider()
            {
                LogLevel = LogLevel.Debug
            });
            _log = loggerFactory.CreateLogger <Program>();


            var app = new CommandLineApplication();
            app.Name     = "nuget3";
            app.FullName = ".NET Package Manager";
            app.HelpOption("-h|--help");
            app.VersionOption("--version", _applicationEnvironment.Version);

            app.Command("restore", restore =>
            {
                restore.Description = "Restores packages for a project and writes a lock file";

                var sources           = restore.Option("-s|--source <source>", "Specifies a NuGet package source to use during the restore", CommandOptionType.MultipleValue);
                var packagesDirectory = restore.Option("--packages <packagesDirectory>", "Directory to install packages in", CommandOptionType.SingleValue);
                var parallel          = restore.Option("-p|--parallel <noneOrNumberOfParallelTasks>", $"The number of concurrent tasks to use when restoring. Defaults to {RestoreRequest.DefaultDegreeOfConcurrency}; pass 'none' to run without concurrency.", CommandOptionType.SingleValue);
                var projectFile       = restore.Argument("[project file]", "The path to the project to restore for, either a project.json or the directory containing it. Defaults to the current directory");

                restore.OnExecute(async() =>
                {
                    // Figure out the project directory
                    PackageSpec project;
                    string projectDirectory = projectFile.Value ?? Path.GetFullPath(".");
                    if (string.Equals(PackageSpec.PackageSpecFileName, Path.GetFileName(projectDirectory), StringComparison.OrdinalIgnoreCase))
                    {
                        _log.LogVerbose($"Reading project file {projectFile.Value}");
                        projectDirectory = Path.GetDirectoryName(Path.GetFullPath(projectDirectory));
                        project          = JsonPackageSpecReader.GetPackageSpec(File.ReadAllText(projectFile.Value), Path.GetFileName(projectDirectory), projectFile.Value);
                    }
                    else
                    {
                        string file = Path.Combine(projectDirectory, PackageSpec.PackageSpecFileName);

                        _log.LogVerbose($"Reading project file {file}");
                        project = JsonPackageSpecReader.GetPackageSpec(File.ReadAllText(file), Path.GetFileName(projectDirectory), file);
                    }
                    _log.LogVerbose($"Loaded project {project.Name} from {project.FilePath}");

                    // Resolve the root directory
                    var rootDirectory = PackageSpecResolver.ResolveRootDirectory(projectDirectory);
                    _log.LogVerbose($"Found project root directory: {rootDirectory}");

                    // Resolve the packages directory
                    // TODO: Do this for real :)
                    var packagesDir = packagesDirectory.HasValue() ?
                                      packagesDirectory.Value() :
                                      Path.Combine(Environment.GetEnvironmentVariable("USERPROFILE"), ".dnx", "packages");
                    _log.LogVerbose($"Using packages directory: {packagesDirectory}");

                    // Run the restore
                    var request = new RestoreRequest(
                        project,
                        sources.Values.Select(s => new PackageSource(s)),
                        packagesDir);
                    if (parallel.HasValue())
                    {
                        int parallelDegree;
                        if (string.Equals(parallel.Value(), "none", StringComparison.OrdinalIgnoreCase))
                        {
                            request.MaxDegreeOfConcurrency = 1;
                        }
                        else if (int.TryParse(parallel.Value(), out parallelDegree))
                        {
                            request.MaxDegreeOfConcurrency = parallelDegree;
                        }
                    }
                    if (request.MaxDegreeOfConcurrency <= 1)
                    {
                        _log.LogInformation("Running non-parallel restore");
                    }
                    else
                    {
                        _log.LogInformation($"Running restore with {request.MaxDegreeOfConcurrency} concurrent jobs");
                    }
                    var command = new RestoreCommand(loggerFactory);
                    var sw      = Stopwatch.StartNew();
                    var result  = await command.ExecuteAsync(request);
                    sw.Stop();

                    _log.LogInformation($"Restore completed in {sw.ElapsedMilliseconds:0.00}ms!");

                    return(0);
                });
            });

            app.Command("diag", diag =>
            {
                diag.Description = "Diagnostic commands for debugging package dependency graphs";
                diag.Command("lockfile", lockfile =>
                {
                    lockfile.Description = "Dumps data from the project lock file";

                    var project = lockfile.Option("--project <project>", "Path containing the project lockfile, or the patht to the lockfile itself", CommandOptionType.SingleValue);
                    var target  = lockfile.Option("--target <target>", "View information about a specific project target", CommandOptionType.SingleValue);
                    var library = lockfile.Argument("<library>", "Optionally, get detailed information about a specific library");

                    lockfile.OnExecute(() =>
                    {
                        var diagnostics = new DiagnosticCommands(loggerFactory);
                        var projectFile = project.HasValue() ? project.Value() : Path.GetFullPath(".");
                        return(diagnostics.Lockfile(projectFile, target.Value(), library.Value));
                    });
                });
                diag.OnExecute(() => { diag.ShowHelp(); return(0); });
            });

            app.OnExecute(() => { app.ShowHelp(); return(0); });

            return(app.Execute(args));
        }