public async override Task <bool> UninstallPackageAsync(PackageIdentity packageIdentity, INuGetProjectContext nuGetProjectContext, CancellationToken token)
        {
            if (packageIdentity == null)
            {
                throw new ArgumentNullException("packageIdentity");
            }

            if (nuGetProjectContext == null)
            {
                throw new ArgumentNullException("nuGetProjectContext");
            }

            // Step-1: Check if the package already exists after setting the nuGetProjectContext
            MSBuildNuGetProjectSystem.SetNuGetProjectContext(nuGetProjectContext);

            var packageReference = (await GetInstalledPackagesAsync(token)).Where(
                p => p.PackageIdentity.Equals(packageIdentity)).FirstOrDefault();

            if (packageReference == null)
            {
                nuGetProjectContext.Log(MessageLevel.Warning, Strings.PackageDoesNotExistInProject,
                                        packageIdentity, MSBuildNuGetProjectSystem.ProjectName);
                return(false);
            }

            var packageTargetFramework = packageReference.TargetFramework ?? NuGetFramework.UnsupportedFramework;
            var packageEventArgs       = new PackageEventArgs(FolderNuGetProject, packageIdentity, FolderNuGetProject.GetInstalledPath(packageIdentity));

            using (var packageStream = File.OpenRead(FolderNuGetProject.GetInstalledPackageFilePath(packageIdentity)))
            {
                // Step-2: Create PackageReader using the PackageStream and obtain the various item groups
                // Get the package target framework instead of using project targetframework
                var zipArchive    = new ZipArchive(packageStream);
                var packageReader = new PackageReader(zipArchive);

                IEnumerable <FrameworkSpecificGroup> referenceItemGroups      = packageReader.GetReferenceItems();
                IEnumerable <FrameworkSpecificGroup> frameworkReferenceGroups = packageReader.GetFrameworkItems();
                IEnumerable <FrameworkSpecificGroup> contentFileGroups        = packageReader.GetContentItems();
                IEnumerable <FrameworkSpecificGroup> buildFileGroups          = packageReader.GetBuildItems();

                // Step-3: Get the most compatible items groups for all items groups
                FrameworkSpecificGroup compatibleReferenceItemsGroup =
                    MSBuildNuGetProjectSystemUtility.GetMostCompatibleGroup(packageTargetFramework, referenceItemGroups);
                FrameworkSpecificGroup compatibleFrameworkReferencesGroup =
                    MSBuildNuGetProjectSystemUtility.GetMostCompatibleGroup(packageTargetFramework, frameworkReferenceGroups);
                FrameworkSpecificGroup compatibleContentFilesGroup =
                    MSBuildNuGetProjectSystemUtility.GetMostCompatibleGroup(packageTargetFramework, contentFileGroups);
                FrameworkSpecificGroup compatibleBuildFilesGroup =
                    MSBuildNuGetProjectSystemUtility.GetMostCompatibleGroup(packageTargetFramework, buildFileGroups);

                // TODO: Need to handle References element??

                // Step-4: Raise PackageUninstalling event
                if (PackageUninstalling != null)
                {
                    PackageUninstalling(this, packageEventArgs);
                }
                PackageEventsProvider.Instance.NotifyUninstalling(packageEventArgs);

                // Step-5: Uninstall package from packages.config
                await PackagesConfigNuGetProject.UninstallPackageAsync(packageIdentity, nuGetProjectContext, token);

                // Step-6: Remove packages.config from MSBuildNuGetProject if there are no packages
                //         OR Add it again (to ensure that Source Control works), when there are some packages
                if (!(await PackagesConfigNuGetProject.GetInstalledPackagesAsync(token)).Any())
                {
                    MSBuildNuGetProjectSystem.RemoveFile(Path.GetFileName(PackagesConfigNuGetProject.FullPath));
                }
                else
                {
                    MSBuildNuGetProjectSystem.AddExistingFile(Path.GetFileName(PackagesConfigNuGetProject.FullPath));
                }

                // Step-7: Uninstall package from the msbuild project
                // Step-7.1: Remove references
                if (MSBuildNuGetProjectSystemUtility.IsValid(compatibleReferenceItemsGroup))
                {
                    foreach (var item in compatibleReferenceItemsGroup.Items)
                    {
                        if (IsAssemblyReference(item))
                        {
                            MSBuildNuGetProjectSystem.RemoveReference(Path.GetFileName(item));
                        }
                    }
                }

                // Step-7.2: Framework references are never removed. This is a no-op

                // Step-7.3: Remove content files
                if (MSBuildNuGetProjectSystemUtility.IsValid(compatibleContentFilesGroup))
                {
                    MSBuildNuGetProjectSystemUtility.DeleteFiles(MSBuildNuGetProjectSystem,
                                                                 zipArchive,
                                                                 (await GetInstalledPackagesAsync(token)).Select(pr => FolderNuGetProject.GetInstalledPackageFilePath(pr.PackageIdentity)),
                                                                 compatibleContentFilesGroup,
                                                                 FileTransformers);
                }

                // Step-7.4: Remove build imports
                if (MSBuildNuGetProjectSystemUtility.IsValid(compatibleBuildFilesGroup))
                {
                    foreach (var buildImportFile in compatibleBuildFilesGroup.Items)
                    {
                        string fullImportFilePath = Path.Combine(FolderNuGetProject.GetInstalledPath(packageIdentity), buildImportFile);
                        MSBuildNuGetProjectSystem.RemoveImport(fullImportFilePath);
                    }
                }

                // Step-7.5: Remove binding redirects. This is a no-op

                // Step-8: Raise PackageReferenceRemoved event
                if (PackageReferenceRemoved != null)
                {
                    PackageReferenceRemoved(this, packageEventArgs);
                }
                PackageEventsProvider.Instance.NotifyReferenceRemoved(packageEventArgs);

                // Step-9: Execute powershell script - uninstall.ps1
                IEnumerable <FrameworkSpecificGroup> toolItemGroups = packageReader.GetToolItems();
                FrameworkSpecificGroup compatibleToolItemsGroup     = MSBuildNuGetProjectSystemUtility.GetMostCompatibleGroup(MSBuildNuGetProjectSystem.TargetFramework,
                                                                                                                              toolItemGroups);
                if (MSBuildNuGetProjectSystemUtility.IsValid(compatibleToolItemsGroup))
                {
                    string uninstallPS1RelativePath = compatibleToolItemsGroup.Items.Where(p =>
                                                                                           p.EndsWith(Path.DirectorySeparatorChar + PowerShellScripts.Uninstall)).FirstOrDefault();
                    if (!String.IsNullOrEmpty(uninstallPS1RelativePath))
                    {
                        string packageInstallPath = FolderNuGetProject.GetInstalledPath(packageIdentity);
                        await MSBuildNuGetProjectSystem.ExecuteScriptAsync(packageInstallPath, uninstallPS1RelativePath, zipArchive, this);
                    }
                }
            }

            // Step-10: Uninstall package from the folderNuGetProject
            await FolderNuGetProject.UninstallPackageAsync(packageIdentity, nuGetProjectContext, token);

            // Step-11: Raise PackageUninstalled event
            if (PackageUninstalled != null)
            {
                PackageUninstalled(this, packageEventArgs);
            }
            PackageEventsProvider.Instance.NotifyUninstalled(packageEventArgs);

            return(true);
        }
예제 #2
0
        private LockFileTargetLibrary CreateLockFileTargetLibrary(LocalPackageInfo package, RestoreTargetGraph targetGraph, DefaultPackagePathResolver defaultPackagePathResolver, string correctedPackageName)
        {
            var lockFileLib = new LockFileTargetLibrary();

            var framework         = targetGraph.Framework;
            var runtimeIdentifier = targetGraph.RuntimeIdentifier;

            // package.Id is read from nuspec and it might be in wrong casing.
            // correctedPackageName should be the package name used by dependency graph and
            // it has the correct casing that runtime needs during dependency resolution.
            lockFileLib.Name    = correctedPackageName ?? package.Id;
            lockFileLib.Version = package.Version;

            IList <string>   files;
            var              contentItems    = new ContentItemCollection();
            HashSet <string> referenceFilter = null;

            using (var nupkgStream = File.OpenRead(package.ZipPath))
            {
                var packageReader = new PackageReader(nupkgStream);
                files = packageReader.GetFiles().Select(p => p.Replace(Path.DirectorySeparatorChar, '/')).ToList();

                contentItems.Load(files);

                var dependencySet = packageReader.GetPackageDependencies().GetNearest(framework);
                if (dependencySet != null)
                {
                    var set = dependencySet.Packages;

                    if (set != null)
                    {
                        lockFileLib.Dependencies = set.ToList();
                    }
                }

                var referenceSet = packageReader.GetReferenceItems().GetNearest(framework);
                if (referenceSet != null)
                {
                    referenceFilter = new HashSet <string>(referenceSet.Items, StringComparer.OrdinalIgnoreCase);
                }

                // TODO: Remove this when we do #596
                // ASP.NET Core isn't compatible with generic PCL profiles
                if (!string.Equals(framework.Framework, FrameworkConstants.FrameworkIdentifiers.AspNetCore, StringComparison.OrdinalIgnoreCase) &&
                    !string.Equals(framework.Framework, FrameworkConstants.FrameworkIdentifiers.DnxCore, StringComparison.OrdinalIgnoreCase))
                {
                    var frameworkAssemblies = packageReader.GetFrameworkItems().GetNearest(framework);
                    if (frameworkAssemblies != null)
                    {
                        foreach (var assemblyReference in frameworkAssemblies.Items)
                        {
                            lockFileLib.FrameworkAssemblies.Add(assemblyReference);
                        }
                    }
                }
            }

            var nativeCriteria  = targetGraph.Conventions.Criteria.ForRuntime(targetGraph.RuntimeIdentifier);
            var managedCriteria = targetGraph.Conventions.Criteria.ForFrameworkAndRuntime(framework, targetGraph.RuntimeIdentifier);

            var compileGroup = contentItems.FindBestItemGroup(managedCriteria, targetGraph.Conventions.Patterns.CompileAssemblies, targetGraph.Conventions.Patterns.RuntimeAssemblies);

            if (compileGroup != null)
            {
                lockFileLib.CompileTimeAssemblies = compileGroup.Items.Select(t => t.Path).ToList();
            }

            var runtimeGroup = contentItems.FindBestItemGroup(managedCriteria, targetGraph.Conventions.Patterns.RuntimeAssemblies);

            if (runtimeGroup != null)
            {
                lockFileLib.RuntimeAssemblies = runtimeGroup.Items.Select(p => p.Path).ToList();
            }

            var nativeGroup = contentItems.FindBestItemGroup(nativeCriteria, targetGraph.Conventions.Patterns.NativeLibraries);

            if (nativeGroup != null)
            {
                lockFileLib.NativeLibraries = nativeGroup.Items.Select(p => p.Path).ToList();
            }

            // COMPAT: Support lib/contract so older packages can be consumed
            string contractPath = "lib/contract/" + package.Id + ".dll";
            var    hasContract  = files.Any(path => path == contractPath);
            var    hasLib       = lockFileLib.RuntimeAssemblies.Any();

            if (hasContract && hasLib && !framework.IsDesktop())
            {
                lockFileLib.CompileTimeAssemblies.Clear();
                lockFileLib.CompileTimeAssemblies.Add(contractPath);
            }

            // Apply filters from the <references> node in the nuspec
            if (referenceFilter != null)
            {
                // Remove anything that starts with "lib/" and is NOT specified in the reference filter.
                // runtimes/* is unaffected (it doesn't start with lib/)
                lockFileLib.RuntimeAssemblies     = lockFileLib.RuntimeAssemblies.Where(p => !p.StartsWith("lib/") || referenceFilter.Contains(p)).ToList();
                lockFileLib.CompileTimeAssemblies = lockFileLib.CompileTimeAssemblies.Where(p => !p.StartsWith("lib/") || referenceFilter.Contains(p)).ToList();
            }

            return(lockFileLib);
        }
        public async override Task <bool> InstallPackageAsync(PackageIdentity packageIdentity, Stream packageStream,
                                                              INuGetProjectContext nuGetProjectContext, CancellationToken token)
        {
            if (packageIdentity == null)
            {
                throw new ArgumentNullException("packageIdentity");
            }

            if (packageStream == null)
            {
                throw new ArgumentNullException("packageStream");
            }

            if (nuGetProjectContext == null)
            {
                throw new ArgumentNullException("nuGetProjectContext");
            }

            if (!packageStream.CanSeek)
            {
                throw new ArgumentException(Strings.PackageStreamShouldBeSeekable);
            }

            // Step-1: Check if the package already exists after setting the nuGetProjectContext
            MSBuildNuGetProjectSystem.SetNuGetProjectContext(nuGetProjectContext);

            var packageReference = (await GetInstalledPackagesAsync(token)).Where(
                p => p.PackageIdentity.Equals(packageIdentity)).FirstOrDefault();

            if (packageReference != null)
            {
                nuGetProjectContext.Log(MessageLevel.Warning, Strings.PackageAlreadyExistsInProject,
                                        packageIdentity, MSBuildNuGetProjectSystem.ProjectName);
                return(false);
            }

            // Step-2: Create PackageReader using the PackageStream and obtain the various item groups
            packageStream.Seek(0, SeekOrigin.Begin);
            var           zipArchive    = new ZipArchive(packageStream);
            PackageReader packageReader = new PackageReader(zipArchive);
            IEnumerable <FrameworkSpecificGroup> referenceItemGroups      = packageReader.GetReferenceItems();
            IEnumerable <FrameworkSpecificGroup> frameworkReferenceGroups = packageReader.GetFrameworkItems();
            IEnumerable <FrameworkSpecificGroup> contentFileGroups        = packageReader.GetContentItems();
            IEnumerable <FrameworkSpecificGroup> buildFileGroups          = packageReader.GetBuildItems();
            IEnumerable <FrameworkSpecificGroup> toolItemGroups           = packageReader.GetToolItems();

            // Step-3: Get the most compatible items groups for all items groups
            bool hasCompatibleProjectLevelContent = false;

            FrameworkSpecificGroup compatibleReferenceItemsGroup =
                MSBuildNuGetProjectSystemUtility.GetMostCompatibleGroup(MSBuildNuGetProjectSystem.TargetFramework, referenceItemGroups);
            FrameworkSpecificGroup compatibleFrameworkReferencesGroup =
                MSBuildNuGetProjectSystemUtility.GetMostCompatibleGroup(MSBuildNuGetProjectSystem.TargetFramework, frameworkReferenceGroups);
            FrameworkSpecificGroup compatibleContentFilesGroup =
                MSBuildNuGetProjectSystemUtility.GetMostCompatibleGroup(MSBuildNuGetProjectSystem.TargetFramework, contentFileGroups);
            FrameworkSpecificGroup compatibleBuildFilesGroup =
                MSBuildNuGetProjectSystemUtility.GetMostCompatibleGroup(MSBuildNuGetProjectSystem.TargetFramework, buildFileGroups);
            FrameworkSpecificGroup compatibleToolItemsGroup =
                MSBuildNuGetProjectSystemUtility.GetMostCompatibleGroup(MSBuildNuGetProjectSystem.TargetFramework, toolItemGroups);

            hasCompatibleProjectLevelContent = MSBuildNuGetProjectSystemUtility.IsValid(compatibleReferenceItemsGroup) ||
                                               MSBuildNuGetProjectSystemUtility.IsValid(compatibleFrameworkReferencesGroup) ||
                                               MSBuildNuGetProjectSystemUtility.IsValid(compatibleContentFilesGroup) ||
                                               MSBuildNuGetProjectSystemUtility.IsValid(compatibleBuildFilesGroup);

            // Check if package has any content for project
            bool hasProjectLevelContent = referenceItemGroups.Any() || frameworkReferenceGroups.Any() ||
                                          contentFileGroups.Any() || buildFileGroups.Any();
            bool onlyHasCompatibleTools = false;
            bool onlyHasDependencies    = false;

            if (!hasProjectLevelContent)
            {
                // Since it does not have project-level content, check if it has dependencies or compatible tools
                // Note that we are not checking if it has compatible project level content, but, just that it has project level content
                // If the package has project-level content, but nothing compatible, we still need to throw
                // If a package does not have any project-level content, it can be a
                // Legacy solution level packages which only has compatible tools group
                onlyHasCompatibleTools = MSBuildNuGetProjectSystemUtility.IsValid(compatibleToolItemsGroup) && compatibleToolItemsGroup.Items.Any();
                if (!onlyHasCompatibleTools)
                {
                    // If it does not have compatible tool items either, check if it at least has dependencies
                    onlyHasDependencies = packageReader.GetPackageDependencies().Any();
                }
            }
            else
            {
                string shortFramework = MSBuildNuGetProjectSystem.TargetFramework.GetShortFolderName();
                nuGetProjectContext.Log(MessageLevel.Debug, Strings.Debug_TargetFrameworkInfoPrefix, packageIdentity,
                                        this.GetMetadata <string>(NuGetProjectMetadataKeys.Name), shortFramework);
            }

            // Step-4: Check if there are any compatible items in the package or that this is not a package with only tools group. If not, throw
            if (!hasCompatibleProjectLevelContent && !onlyHasCompatibleTools && !onlyHasDependencies)
            {
                throw new InvalidOperationException(
                          String.Format(CultureInfo.CurrentCulture,
                                        Strings.UnableToFindCompatibleItems, packageIdentity, MSBuildNuGetProjectSystem.TargetFramework));
            }

            if (hasCompatibleProjectLevelContent)
            {
                string shortFramework = MSBuildNuGetProjectSystem.TargetFramework.GetShortFolderName();
                nuGetProjectContext.Log(MessageLevel.Debug, Strings.Debug_TargetFrameworkInfoPrefix, packageIdentity,
                                        this.GetMetadata <string>(NuGetProjectMetadataKeys.Name), shortFramework);
            }
            else if (onlyHasCompatibleTools)
            {
                nuGetProjectContext.Log(MessageLevel.Info, Strings.AddingPackageWithOnlyToolsGroup, packageIdentity,
                                        this.GetMetadata <string>(NuGetProjectMetadataKeys.Name));
            }
            else if (onlyHasDependencies)
            {
                nuGetProjectContext.Log(MessageLevel.Info, Strings.AddingPackageWithOnlyDependencies, packageIdentity,
                                        this.GetMetadata <string>(NuGetProjectMetadataKeys.Name));
            }

            // Step-5: Raise PackageInstalling event
            // At this point, GetInstalledPath is pointless since the package is, likely, not already installed. It will be empty
            // Using PackagePathResolver.GetInstallPath would be wrong, since, package version from the nuspec is always used
            var packageEventArgs = new PackageEventArgs(FolderNuGetProject, packageIdentity, FolderNuGetProject.GetInstalledPath(packageIdentity));

            if (PackageInstalling != null)
            {
                PackageInstalling(this, packageEventArgs);
            }
            PackageEventsProvider.Instance.NotifyInstalling(packageEventArgs);

            // Step-6: Install package to FolderNuGetProject
            await FolderNuGetProject.InstallPackageAsync(packageIdentity, packageStream, nuGetProjectContext, token);

            // Step-7: Raise PackageInstalled event
            // Call GetInstalledPath again, to get the package installed path
            packageEventArgs = new PackageEventArgs(FolderNuGetProject, packageIdentity, FolderNuGetProject.GetInstalledPath(packageIdentity));
            if (PackageInstalled != null)
            {
                PackageInstalled(this, packageEventArgs);
            }
            PackageEventsProvider.Instance.NotifyInstalled(packageEventArgs);

            // Step-8: MSBuildNuGetProjectSystem operations
            // Step-8.1: Add references to project
            if (MSBuildNuGetProjectSystemUtility.IsValid(compatibleReferenceItemsGroup) && !IsSkipAssemblyReferences(nuGetProjectContext))
            {
                foreach (var referenceItem in compatibleReferenceItemsGroup.Items)
                {
                    if (IsAssemblyReference(referenceItem))
                    {
                        var referenceItemFullPath = Path.Combine(FolderNuGetProject.GetInstalledPath(packageIdentity), referenceItem);
                        var referenceName         = Path.GetFileName(referenceItem);
                        if (MSBuildNuGetProjectSystem.ReferenceExists(referenceName))
                        {
                            MSBuildNuGetProjectSystem.RemoveReference(referenceName);
                        }
                        MSBuildNuGetProjectSystem.AddReference(referenceItemFullPath);
                    }
                }
            }

            // Step-8.2: Add Frameworkreferences to project
            if (MSBuildNuGetProjectSystemUtility.IsValid(compatibleFrameworkReferencesGroup))
            {
                foreach (var frameworkReference in compatibleFrameworkReferencesGroup.Items)
                {
                    var frameworkReferenceName = Path.GetFileName(frameworkReference);
                    if (!MSBuildNuGetProjectSystem.ReferenceExists(frameworkReference))
                    {
                        MSBuildNuGetProjectSystem.AddFrameworkReference(frameworkReference);
                    }
                }
            }

            // Step-8.3: Add Content Files
            if (MSBuildNuGetProjectSystemUtility.IsValid(compatibleContentFilesGroup))
            {
                MSBuildNuGetProjectSystemUtility.AddFiles(MSBuildNuGetProjectSystem,
                                                          zipArchive, compatibleContentFilesGroup, FileTransformers);
            }

            // Step-8.4: Add Build imports
            if (MSBuildNuGetProjectSystemUtility.IsValid(compatibleBuildFilesGroup))
            {
                foreach (var buildImportFile in compatibleBuildFilesGroup.Items)
                {
                    string fullImportFilePath = Path.Combine(FolderNuGetProject.GetInstalledPath(packageIdentity), buildImportFile);
                    MSBuildNuGetProjectSystem.AddImport(fullImportFilePath,
                                                        fullImportFilePath.EndsWith(".props", StringComparison.OrdinalIgnoreCase) ? ImportLocation.Top : ImportLocation.Bottom);
                }
            }

            // Step-9: Install package to PackagesConfigNuGetProject
            await PackagesConfigNuGetProject.InstallPackageAsync(packageIdentity, packageStream, nuGetProjectContext, token);

            // Step-10: Add packages.config to MSBuildNuGetProject
            MSBuildNuGetProjectSystem.AddExistingFile(Path.GetFileName(PackagesConfigNuGetProject.FullPath));

            // Step 11: Raise PackageReferenceAdded event
            if (PackageReferenceAdded != null)
            {
                PackageReferenceAdded(this, packageEventArgs);
            }
            PackageEventsProvider.Instance.NotifyReferenceAdded(packageEventArgs);

            // Step-12: Execute powershell script - install.ps1
            string packageInstallPath = FolderNuGetProject.GetInstalledPath(packageIdentity);
            FrameworkSpecificGroup anyFrameworkToolsGroup = toolItemGroups.Where(g => g.TargetFramework.Equals(NuGetFramework.AnyFramework)).FirstOrDefault();

            if (anyFrameworkToolsGroup != null)
            {
                string initPS1RelativePath = anyFrameworkToolsGroup.Items.Where(p =>
                                                                                p.StartsWith(PowerShellScripts.InitPS1RelativePath)).FirstOrDefault();
                if (!String.IsNullOrEmpty(initPS1RelativePath))
                {
                    initPS1RelativePath = PathUtility.ReplaceAltDirSeparatorWithDirSeparator(initPS1RelativePath);
                    await MSBuildNuGetProjectSystem.ExecuteScriptAsync(packageInstallPath, initPS1RelativePath, zipArchive, this);
                }
            }

            if (MSBuildNuGetProjectSystemUtility.IsValid(compatibleToolItemsGroup))
            {
                string installPS1RelativePath = compatibleToolItemsGroup.Items.Where(p =>
                                                                                     p.EndsWith(Path.DirectorySeparatorChar + PowerShellScripts.Install)).FirstOrDefault();
                if (!String.IsNullOrEmpty(installPS1RelativePath))
                {
                    await MSBuildNuGetProjectSystem.ExecuteScriptAsync(packageInstallPath, installPS1RelativePath, zipArchive, this);
                }
            }
            return(true);
        }