Example #1
0
 public override Stream CreateFile(string fullPath, INuGetProjectContext nuGetProjectContext)
 {
     PendAddedFiles.Add(fullPath);
     return(FileSystemUtility.CreateFile(fullPath));
 }
        /// <summary>
        /// Asynchronously deletes a package.
        /// </summary>
        /// <param name="packageIdentity">A package identity.</param>
        /// <param name="nuGetProjectContext">A NuGet project context.</param>
        /// <param name="token">A cancellation token.</param>
        /// <returns>A task that represents the asynchronous operation.
        /// The task result (<see cref="Task{TResult}.Result" />) returns a <see cref="bool" />
        /// indication successfulness of the operation.</returns>
        /// <exception cref="ArgumentNullException">Thrown if <paramref name="packageIdentity" />
        /// is <c>null</c>.</exception>
        /// <exception cref="ArgumentNullException">Thrown if <paramref name="nuGetProjectContext" />
        /// is <c>null</c>.</exception>
        public async Task <bool> DeletePackage(PackageIdentity packageIdentity,
                                               INuGetProjectContext nuGetProjectContext,
                                               CancellationToken token)
        {
            if (packageIdentity == null)
            {
                throw new ArgumentNullException(nameof(packageIdentity));
            }

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

            var packageFilePath = GetInstalledPackageFilePath(packageIdentity);

            if (File.Exists(packageFilePath))
            {
                var packageDirectoryPath = Path.GetDirectoryName(packageFilePath);
                using (var packageReader = new PackageArchiveReader(packageFilePath))
                {
                    var installedSatelliteFilesPair = await PackageHelper.GetInstalledSatelliteFilesAsync(
                        packageReader,
                        PackagePathResolver,
                        GetPackageSaveMode(nuGetProjectContext),
                        token);

                    var runtimePackageDirectory = installedSatelliteFilesPair.Item1;
                    var installedSatelliteFiles = installedSatelliteFilesPair.Item2;
                    if (!string.IsNullOrEmpty(runtimePackageDirectory))
                    {
                        try
                        {
                            // Delete all the package files now
                            FileSystemUtility.DeleteFiles(installedSatelliteFiles, runtimePackageDirectory, nuGetProjectContext);
                        }
                        catch (Exception ex)
                        {
                            nuGetProjectContext.Log(MessageLevel.Warning, ex.Message);
                            // Catch all exception with delete so that the package file is always deleted
                        }
                    }

                    // Get all the package files before deleting the package file
                    var installedPackageFiles = await PackageHelper.GetInstalledPackageFilesAsync(
                        packageReader,
                        packageIdentity,
                        PackagePathResolver,
                        GetPackageSaveMode(nuGetProjectContext),
                        token);

                    try
                    {
                        // Delete all the package files now
                        FileSystemUtility.DeleteFiles(installedPackageFiles, packageDirectoryPath, nuGetProjectContext);
                    }
                    catch (Exception ex)
                    {
                        nuGetProjectContext.Log(MessageLevel.Warning, ex.Message);
                        // Catch all exception with delete so that the package file is always deleted
                    }
                }

                // Delete the package file
                FileSystemUtility.DeleteFile(packageFilePath, nuGetProjectContext);

                // Delete the package directory if any
                FileSystemUtility.DeleteDirectorySafe(packageDirectoryPath, recursive: true, nuGetProjectContext: nuGetProjectContext);

                // If this is the last package delete the package directory
                // If this is the last package delete the package directory
                if (!FileSystemUtility.GetFiles(Root, string.Empty, "*.*").Any() &&
                    !FileSystemUtility.GetDirectories(Root, string.Empty).Any())
                {
                    FileSystemUtility.DeleteDirectorySafe(Root, recursive: false, nuGetProjectContext: nuGetProjectContext);
                }
            }

            return(true);
        }
        internal static void DeleteFiles(IMSBuildNuGetProjectSystem projectSystem,
                                         ZipArchive zipArchive,
                                         IEnumerable <string> otherPackagesPath,
                                         FrameworkSpecificGroup frameworkSpecificGroup,
                                         IDictionary <FileTransformExtensions, IPackageFileTransformer> fileTransformers)
        {
            var packageTargetFramework = frameworkSpecificGroup.TargetFramework;
            IPackageFileTransformer transformer;

            var directoryLookup = frameworkSpecificGroup.Items.ToLookup(
                p => Path.GetDirectoryName(ResolveTargetPath(projectSystem,
                                                             fileTransformers,
                                                             fte => fte.UninstallExtension,
                                                             GetEffectivePathForContentFile(packageTargetFramework, p),
                                                             out transformer)));

            // Get all directories that this package may have added
            var directories = from grouping in directoryLookup
                              from directory in FileSystemUtility.GetDirectories(grouping.Key, altDirectorySeparator: false)
                              orderby directory.Length descending
                              select directory;

            string projectFullPath = projectSystem.ProjectFullPath;

            // Remove files from every directory
            foreach (var directory in directories)
            {
                var directoryFiles = directoryLookup.Contains(directory)
                    ? directoryLookup[directory]
                    : Enumerable.Empty <string>();

                if (!Directory.Exists(Path.Combine(projectFullPath, directory)))
                {
                    continue;
                }

                foreach (var file in directoryFiles)
                {
                    if (IsEmptyFolder(file))
                    {
                        continue;
                    }

                    // Resolve the path
                    var path = ResolveTargetPath(projectSystem,
                                                 fileTransformers,
                                                 fte => fte.UninstallExtension,
                                                 GetEffectivePathForContentFile(packageTargetFramework, file),
                                                 out transformer);

                    if (projectSystem.IsSupportedFile(path))
                    {
                        // Register the file being uninstalled (used by web site project system).
                        projectSystem.RegisterProcessedFiles(new[] { path });

                        if (transformer != null)
                        {
                            // TODO: use the framework from packages.config instead of the current framework
                            // which may have changed during re-targeting
                            var projectFramework = projectSystem.TargetFramework;

                            var matchingFiles = new List <InternalZipFileInfo>();
                            foreach (var otherPackagePath in otherPackagesPath)
                            {
                                using (var otherPackageZipReader = new PackageArchiveReader(otherPackagePath))
                                {
                                    // use the project framework to find the group that would have been installed
                                    var mostCompatibleContentFilesGroup = GetMostCompatibleGroup(
                                        projectFramework,
                                        otherPackageZipReader.GetContentItems());

                                    if (IsValid(mostCompatibleContentFilesGroup))
                                    {
                                        // Should not normalize content files group.
                                        // It should be like a ZipFileEntry with a forward slash.
                                        foreach (var otherPackageItem in mostCompatibleContentFilesGroup.Items)
                                        {
                                            if (GetEffectivePathForContentFile(packageTargetFramework,
                                                                               otherPackageItem)
                                                .Equals(
                                                    GetEffectivePathForContentFile(packageTargetFramework, file),
                                                    StringComparison.OrdinalIgnoreCase))
                                            {
                                                matchingFiles.Add(new InternalZipFileInfo(otherPackagePath,
                                                                                          otherPackageItem));
                                            }
                                        }
                                    }
                                }
                            }

                            try
                            {
                                var zipArchiveFileEntry = PathUtility.GetEntry(zipArchive, file);
                                if (zipArchiveFileEntry != null)
                                {
                                    transformer.RevertFile(zipArchiveFileEntry.Open, path, matchingFiles,
                                                           projectSystem);
                                }
                            }
                            catch (Exception e)
                            {
                                projectSystem.NuGetProjectContext.Log(MessageLevel.Warning, e.Message);
                            }
                        }
                        else
                        {
                            try
                            {
                                var zipArchiveFileEntry = PathUtility.GetEntry(zipArchive, file);
                                if (zipArchiveFileEntry != null)
                                {
                                    DeleteFileSafe(path, zipArchiveFileEntry.Open, projectSystem);
                                }
                            }
                            catch (Exception e)
                            {
                                projectSystem.NuGetProjectContext.Log(MessageLevel.Warning, e.Message);
                            }
                        }
                    }
                }

                // If the directory is empty then delete it
                if (!GetFilesSafe(projectSystem, directory).Any() &&
                    !GetDirectoriesSafe(projectSystem, directory).Any())
                {
                    DeleteDirectorySafe(projectSystem, directory);
                }
            }
        }
        /// <summary>
        /// Asynchronously installs a package.
        /// </summary>
        /// <param name="packageIdentity">A package identity.</param>
        /// <param name="downloadResourceResult">A download resource result.</param>
        /// <param name="nuGetProjectContext">A NuGet project context.</param>
        /// <param name="token">A cancellation token.</param>
        /// <returns>A task that represents the asynchronous operation.
        /// The task result (<see cref="Task{TResult}.Result" />) returns a <see cref="bool" />
        /// indication successfulness of the operation.</returns>
        /// <exception cref="ArgumentNullException">Thrown if <paramref name="packageIdentity" />
        /// is <c>null</c>.</exception>
        /// <exception cref="ArgumentNullException">Thrown if <paramref name="downloadResourceResult" />
        /// is <c>null</c>.</exception>
        /// <exception cref="ArgumentNullException">Thrown if <paramref name="nuGetProjectContext" />
        /// is <c>null</c>.</exception>
        /// <exception cref="ArgumentException">Thrown if the package stream for
        /// <paramref name="downloadResourceResult" /> is not seekable.</exception>
        public override Task <bool> InstallPackageAsync(
            PackageIdentity packageIdentity,
            DownloadResourceResult downloadResourceResult,
            INuGetProjectContext nuGetProjectContext,
            CancellationToken token)
        {
            if (packageIdentity == null)
            {
                throw new ArgumentNullException(nameof(packageIdentity));
            }

            if (downloadResourceResult == null)
            {
                throw new ArgumentNullException(nameof(downloadResourceResult));
            }

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

            if (downloadResourceResult.Status == DownloadResourceResultStatus.Available &&
                !downloadResourceResult.PackageStream.CanSeek)
            {
                throw new ArgumentException(Strings.PackageStreamShouldBeSeekable, nameof(downloadResourceResult));
            }

            var packageDirectory = PackagePathResolver.GetInstallPath(packageIdentity);

            return(ConcurrencyUtilities.ExecuteWithFileLockedAsync(
                       packageDirectory,
                       action: async cancellationToken =>
            {
                // 1. Set a default package extraction context, if necessary.
                var packageExtractionContext = nuGetProjectContext.PackageExtractionContext;
                if (packageExtractionContext == null)
                {
                    packageExtractionContext = new PackageExtractionContext(new LoggerAdapter(nuGetProjectContext));
                }

                // 2. Check if the Package already exists at root, if so, return false
                if (PackageExists(packageIdentity, packageExtractionContext.PackageSaveMode))
                {
                    nuGetProjectContext.Log(MessageLevel.Info, Strings.PackageAlreadyExistsInFolder, packageIdentity, Root);
                    return false;
                }

                nuGetProjectContext.Log(MessageLevel.Info, Strings.AddingPackageToFolder, packageIdentity, Path.GetFullPath(Root));

                // 3. Call PackageExtractor to extract the package into the root directory of this FileSystemNuGetProject
                if (downloadResourceResult.Status == DownloadResourceResultStatus.Available)
                {
                    downloadResourceResult.PackageStream.Seek(0, SeekOrigin.Begin);
                }
                var addedPackageFilesList = new List <string>();

                if (downloadResourceResult.PackageReader != null)
                {
                    if (downloadResourceResult.Status == DownloadResourceResultStatus.AvailableWithoutStream)
                    {
                        addedPackageFilesList.AddRange(
                            await PackageExtractor.ExtractPackageAsync(
                                downloadResourceResult.PackageReader,
                                PackagePathResolver,
                                packageExtractionContext,
                                cancellationToken));
                    }
                    else
                    {
                        addedPackageFilesList.AddRange(
                            await PackageExtractor.ExtractPackageAsync(
                                downloadResourceResult.PackageReader,
                                downloadResourceResult.PackageStream,
                                PackagePathResolver,
                                packageExtractionContext,
                                cancellationToken));
                    }
                }
                else
                {
                    addedPackageFilesList.AddRange(
                        await PackageExtractor.ExtractPackageAsync(
                            downloadResourceResult.PackageStream,
                            PackagePathResolver,
                            packageExtractionContext,
                            cancellationToken));
                }

                var packageSaveMode = GetPackageSaveMode(nuGetProjectContext);
                if (packageSaveMode.HasFlag(PackageSaveMode.Nupkg))
                {
                    var packageFilePath = GetInstalledPackageFilePath(packageIdentity);
                    if (File.Exists(packageFilePath))
                    {
                        addedPackageFilesList.Add(packageFilePath);
                    }
                }

                // Pend all the package files including the nupkg file
                FileSystemUtility.PendAddFiles(addedPackageFilesList, Root, nuGetProjectContext);

                nuGetProjectContext.Log(MessageLevel.Info, Strings.AddedPackageToFolder, packageIdentity, Path.GetFullPath(Root));

                // Extra logging with source for verbosity detailed
                // Used by external tool CoreXT to track package provenance
                if (!string.IsNullOrEmpty(downloadResourceResult.PackageSource))
                {
                    nuGetProjectContext.Log(MessageLevel.Debug, Strings.AddedPackageToFolderFromSource, packageIdentity, Path.GetFullPath(Root), downloadResourceResult.PackageSource);
                }

                return true;
            },
                       token: token));
        }
Example #5
0
        public override Task <bool> InstallPackageAsync(
            PackageIdentity packageIdentity,
            DownloadResourceResult downloadResourceResult,
            INuGetProjectContext nuGetProjectContext,
            CancellationToken token)
        {
            if (packageIdentity == null)
            {
                throw new ArgumentNullException(nameof(packageIdentity));
            }

            if (downloadResourceResult == null)
            {
                throw new ArgumentNullException(nameof(downloadResourceResult));
            }

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

            if (!downloadResourceResult.PackageStream.CanSeek)
            {
                throw new ArgumentException(Strings.PackageStreamShouldBeSeekable);
            }
            var packageFile = PackagePathResolver.GetInstallPath(packageIdentity);

            return(ConcurrencyUtilities.ExecuteWithFileLockedAsync(packageFile,
                                                                   action: cancellationToken =>
            {
                // 1. Check if the Package already exists at root, if so, return false
                if (PackageExists(packageIdentity))
                {
                    nuGetProjectContext.Log(MessageLevel.Info, Strings.PackageAlreadyExistsInFolder, packageIdentity, Root);
                    return Task.FromResult(false);
                }

                nuGetProjectContext.Log(MessageLevel.Info, Strings.AddingPackageToFolder, packageIdentity, Path.GetFullPath(Root));
                // 2. Call PackageExtractor to extract the package into the root directory of this FileSystemNuGetProject
                downloadResourceResult.PackageStream.Seek(0, SeekOrigin.Begin);
                var addedPackageFilesList = new List <string>();

                PackageExtractionContext packageExtractionContext = nuGetProjectContext.PackageExtractionContext;
                if (packageExtractionContext == null)
                {
                    packageExtractionContext = new PackageExtractionContext(new LoggerAdapter(nuGetProjectContext));
                }

                if (downloadResourceResult.PackageReader != null)
                {
                    addedPackageFilesList.AddRange(
                        PackageExtractor.ExtractPackage(
                            downloadResourceResult.PackageReader,
                            downloadResourceResult.PackageStream,
                            PackagePathResolver,
                            packageExtractionContext,
                            cancellationToken));
                }
                else
                {
                    addedPackageFilesList.AddRange(
                        PackageExtractor.ExtractPackage(
                            downloadResourceResult.PackageStream,
                            PackagePathResolver,
                            packageExtractionContext,
                            cancellationToken));
                }


                var packageSaveMode = GetPackageSaveMode(nuGetProjectContext);
                if (packageSaveMode.HasFlag(PackageSaveMode.Nupkg))
                {
                    var packageFilePath = GetInstalledPackageFilePath(packageIdentity);
                    if (File.Exists(packageFilePath))
                    {
                        addedPackageFilesList.Add(packageFilePath);
                    }
                }

                // Pend all the package files including the nupkg file
                FileSystemUtility.PendAddFiles(addedPackageFilesList, Root, nuGetProjectContext);

                nuGetProjectContext.Log(MessageLevel.Info, Strings.AddedPackageToFolder, packageIdentity, Path.GetFullPath(Root));
                return Task.FromResult(true);
            },
                                                                   token: token));
        }