예제 #1
0
        public void TelemetryTest_TelemetryActivityWithIntervalMeasure()
        {
            // Arrange
            var            secondsToWait    = 5;
            var            telemetryService = new Mock <INuGetTelemetryService>();
            TelemetryEvent telemetryEvent   = null;

            telemetryService.Setup(x => x.EmitTelemetryEvent(It.IsAny <TelemetryEvent>()))
            .Callback <TelemetryEvent>(x => telemetryEvent = x);
            TelemetryActivity.NuGetTelemetryService        = telemetryService.Object;

            // Act
            using (var telemetry = TelemetryActivity.CreateTelemetryActivityWithNewOperationId())
            {
                telemetry.TelemetryEvent = new TelemetryEvent("testEvent", new Dictionary <string, object>());
                telemetry.StartIntervalMeasure();
                Thread.Sleep(secondsToWait * 1000);
                telemetry.EndIntervalMeasure("testInterval");
            }

            // Assert
            var value = telemetryEvent["testInterval"];

            value.Should().NotBeNull();
            var actualCount = Convert.ToInt32(value);

            Assert.True(actualCount >= secondsToWait, $"The telemetry duration count should atleaset be {secondsToWait}");
        }
예제 #2
0
        public void Dispose_WithOperationIdAndWithoutParentId_EmitsOperationIdAndNotParentId()
        {
            Guid operationId;

            using (var telemetry = TelemetryActivity.CreateTelemetryActivityWithNewOperationId())
            {
                telemetry.TelemetryEvent = CreateNewTelemetryEvent();
                operationId = telemetry.OperationId;
            }

            Assert.Null(_telemetryEvent["ParentId"]);
            Assert.Equal(operationId.ToString(), _telemetryEvent["OperationId"]);
        }
예제 #3
0
        public void Dispose_Always_EmitsDuration()
        {
            using (var telemetry = TelemetryActivity.CreateTelemetryActivityWithNewOperationId())
            {
                telemetry.TelemetryEvent = CreateNewTelemetryEvent();

                Thread.Sleep(10);
            }

            var duration = (double)_telemetryEvent["Duration"];

            Assert.InRange(duration, 0d, 10d);
        }
예제 #4
0
        public void Dispose_Always_EmitsEndTime()
        {
            using (var telemetry = TelemetryActivity.CreateTelemetryActivityWithNewOperationId())
            {
                telemetry.TelemetryEvent = CreateNewTelemetryEvent();
            }

            var endTime = _telemetryEvent["EndTime"] as string;

            Assert.NotNull(endTime);

            TelemetryUtility.VerifyDateTimeFormat(endTime);
        }
예제 #5
0
        public void Dispose_WithIntervalMeasure_EmitsIntervalMeasure()
        {
            const string measureName   = "testInterval";
            var          secondsToWait = 1;

            using (var telemetry = TelemetryActivity.CreateTelemetryActivityWithNewOperationId())
            {
                telemetry.TelemetryEvent = CreateNewTelemetryEvent();
                telemetry.StartIntervalMeasure();
                Thread.Sleep(secondsToWait * 1000);
                telemetry.EndIntervalMeasure(measureName);
            }

            var value = _telemetryEvent[measureName];

            value.Should().NotBeNull();
            var actualCount = Convert.ToInt32(value);

            Assert.True(actualCount >= secondsToWait, $"The telemetry duration count should at least be {secondsToWait} seconds.");
        }
예제 #6
0
        public void TelemetryTest_TelemetryActivityWithOperationId()
        {
            // Arrange
            var            telemetryService = new Mock <INuGetTelemetryService>();
            TelemetryEvent telemetryEvent   = null;
            Guid           operationId;

            telemetryService.Setup(x => x.EmitTelemetryEvent(It.IsAny <TelemetryEvent>()))
            .Callback <TelemetryEvent>(x => telemetryEvent = x);
            TelemetryActivity.NuGetTelemetryService        = telemetryService.Object;

            // Act
            using (var telemetry = TelemetryActivity.CreateTelemetryActivityWithNewOperationId())
            {
                telemetry.TelemetryEvent = new TelemetryEvent("testEvent", new Dictionary <string, object>());
                operationId = telemetry.OperationId;
            }

            // Assert
            Assert.Null(telemetryEvent["ParentId"]);
            Assert.Equal(operationId.ToString(), telemetryEvent["OperationId"]);
        }
예제 #7
0
        public void TelemetryTest_TelemetryActivityWithIntervalMeasure()
        {
            // Arrange
            var            telemetryService = new Mock <INuGetTelemetryService>();
            TelemetryEvent telemetryEvent   = null;

            telemetryService.Setup(x => x.EmitTelemetryEvent(It.IsAny <TelemetryEvent>()))
            .Callback <TelemetryEvent>(x => telemetryEvent = x);
            TelemetryActivity.NuGetTelemetryService        = telemetryService.Object;

            // Act
            using (var telemetry = TelemetryActivity.CreateTelemetryActivityWithNewOperationId())
            {
                telemetry.TelemetryEvent = new TelemetryEvent("testEvent", new Dictionary <string, object>());
                telemetry.StartIntervalMeasure();
                Thread.Sleep(5000);
                telemetry.EndIntervalMeasure("testInterval");
            }

            // Assert
            Assert.Equal(5, Convert.ToInt32(telemetryEvent["testInterval"]));
        }
예제 #8
0
        public void TelemetryTest_TelemetryActivity()
        {
            // Arrange
            var            telemetryService = new Mock <INuGetTelemetryService>();
            TelemetryEvent telemetryEvent   = null;

            telemetryService.Setup(x => x.EmitTelemetryEvent(It.IsAny <TelemetryEvent>()))
            .Callback <TelemetryEvent>(x => telemetryEvent = x);

            TelemetryActivity.NuGetTelemetryService = telemetryService.Object;

            // Act
            using (var telemetry = TelemetryActivity.CreateTelemetryActivityWithNewOperationId())
            {
                // Wait for 5 seconds
                Thread.Sleep(5000);
                telemetry.TelemetryEvent = new TelemetryEvent("testEvent", new Dictionary <string, object>());
            }

            // Assert
            Assert.NotNull(telemetryEvent["StartTime"]);
            Assert.NotNull(telemetryEvent["EndTime"]);
            Assert.Equal(5, Convert.ToInt32(telemetryEvent["Duration"]));
        }
예제 #9
0
        public static async Task <bool> InstallFromSourceAsync(
            PackageIdentity packageIdentity,
            IPackageDownloader packageDownloader,
            VersionFolderPathResolver versionFolderPathResolver,
            PackageExtractionContext packageExtractionContext,
            CancellationToken token,
            Guid parentId = default(Guid))
        {
            if (packageDownloader == null)
            {
                throw new ArgumentNullException(nameof(packageDownloader));
            }

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

            var logger = packageExtractionContext.Logger;

            using (var telemetry = TelemetryActivity.CreateTelemetryActivityWithNewOperationId(parentId))
            {
                var targetPath   = versionFolderPathResolver.GetInstallPath(packageIdentity.Id, packageIdentity.Version);
                var targetNuspec = versionFolderPathResolver.GetManifestFilePath(packageIdentity.Id, packageIdentity.Version);
                var targetNupkg  = versionFolderPathResolver.GetPackageFilePath(packageIdentity.Id, packageIdentity.Version);
                var hashPath     = versionFolderPathResolver.GetHashPath(packageIdentity.Id, packageIdentity.Version);

                logger.LogVerbose(
                    $"Acquiring lock for the installation of {packageIdentity.Id} {packageIdentity.Version}");

                // Acquire the lock on a nukpg before we extract it to prevent the race condition when multiple
                // processes are extracting to the same destination simultaneously
                return(await ConcurrencyUtilities.ExecuteWithFileLockedAsync(targetNupkg,
                                                                             action : async cancellationToken =>
                {
                    // If this is the first process trying to install the target nupkg, go ahead
                    // After this process successfully installs the package, all other processes
                    // waiting on this lock don't need to install it again.
                    if (!File.Exists(hashPath))
                    {
                        logger.LogVerbose(
                            $"Acquired lock for the installation of {packageIdentity.Id} {packageIdentity.Version}");

                        logger.LogMinimal(string.Format(
                                              CultureInfo.CurrentCulture,
                                              Strings.Log_InstallingPackage,
                                              packageIdentity.Id,
                                              packageIdentity.Version));

                        cancellationToken.ThrowIfCancellationRequested();

                        // We do not stop the package extraction after this point
                        // based on CancellationToken, but things can still be stopped if the process is killed.
                        if (Directory.Exists(targetPath))
                        {
                            // If we had a broken restore, clean out the files first
                            var info = new DirectoryInfo(targetPath);

                            foreach (var file in info.GetFiles())
                            {
                                file.Delete();
                            }

                            foreach (var dir in info.GetDirectories())
                            {
                                dir.Delete(true);
                            }
                        }
                        else
                        {
                            Directory.CreateDirectory(targetPath);
                        }

                        var targetTempNupkg = Path.Combine(targetPath, Path.GetRandomFileName());
                        var tempHashPath = Path.Combine(targetPath, Path.GetRandomFileName());
                        var packageSaveMode = packageExtractionContext.PackageSaveMode;

                        // Extract the nupkg
                        var copiedNupkg = await packageDownloader.CopyNupkgFileToAsync(targetTempNupkg, cancellationToken);

                        if (packageSaveMode.HasFlag(PackageSaveMode.Nuspec) || packageSaveMode.HasFlag(PackageSaveMode.Files))
                        {
                            try
                            {
                                telemetry.StartIntervalMeasure();

                                await VerifyPackageSignatureAsync(
                                    packageDownloader.Source,
                                    telemetry.OperationId,
                                    packageIdentity,
                                    packageExtractionContext,
                                    packageDownloader.SignedPackageReader,
                                    token);

                                telemetry.EndIntervalMeasure(PackagingConstants.PackageVerifyDurationName);
                            }
                            catch (SignatureException)
                            {
                                try
                                {
                                    // Dispose of it now because it is holding a lock on the temporary .nupkg file.
                                    packageDownloader.Dispose();

                                    DeleteTargetAndTempPaths(targetPath, targetTempNupkg);
                                }
                                catch (IOException ex)
                                {
                                    logger.LogWarning(string.Format(
                                                          CultureInfo.CurrentCulture,
                                                          Strings.ErrorUnableToDeleteFile,
                                                          targetTempNupkg,
                                                          ex.Message));
                                }

                                telemetry.TelemetryEvent = new PackageExtractionTelemetryEvent(
                                    packageExtractionContext.PackageSaveMode,
                                    NuGetOperationStatus.Failed,
                                    ExtractionSource.RestoreCommand,
                                    packageIdentity);
                                throw;
                            }
                        }

                        if (packageSaveMode.HasFlag(PackageSaveMode.Nuspec))
                        {
                            var nuspecFileNameFromReader = await packageDownloader.CoreReader.GetNuspecFileAsync(cancellationToken);
                            var packageFiles = new[] { nuspecFileNameFromReader };
                            var packageFileExtractor = new PackageFileExtractor(
                                packageFiles,
                                XmlDocFileSaveMode.None);
                            var packageDirectoryPath = Path.GetDirectoryName(targetNuspec);

                            var extractedNuspecFilePath = (await packageDownloader.CoreReader.CopyFilesAsync(
                                                               packageDirectoryPath,
                                                               packageFiles,
                                                               packageFileExtractor.ExtractPackageFile,
                                                               logger,
                                                               cancellationToken))
                                                          .SingleOrDefault();

                            // CopyFilesAsync(...) just extracts files to a directory.
                            // We may have to fix up the casing of the .nuspec file name.
                            if (!string.IsNullOrEmpty(extractedNuspecFilePath))
                            {
                                if (PathUtility.IsFileSystemCaseInsensitive)
                                {
                                    var nuspecFileName = Path.GetFileName(targetNuspec);
                                    var actualNuspecFileName = Path.GetFileName(extractedNuspecFilePath);

                                    if (!string.Equals(nuspecFileName, actualNuspecFileName, StringComparison.Ordinal))
                                    {
                                        var tempNuspecFilePath = Path.Combine(packageDirectoryPath, Path.GetRandomFileName());

                                        File.Move(extractedNuspecFilePath, tempNuspecFilePath);
                                        File.Move(tempNuspecFilePath, targetNuspec);
                                    }
                                }
                                else if (!File.Exists(targetNuspec))
                                {
                                    File.Move(extractedNuspecFilePath, targetNuspec);
                                }
                            }
                        }

                        if (packageSaveMode.HasFlag(PackageSaveMode.Files))
                        {
                            var hashFileName = Path.GetFileName(hashPath);
                            var packageFiles = (await packageDownloader.CoreReader.GetFilesAsync(cancellationToken))
                                               .Where(file => ShouldInclude(file, hashFileName));
                            var packageFileExtractor = new PackageFileExtractor(
                                packageFiles,
                                packageExtractionContext.XmlDocFileSaveMode);
                            await packageDownloader.CoreReader.CopyFilesAsync(
                                targetPath,
                                packageFiles,
                                packageFileExtractor.ExtractPackageFile,
                                logger,
                                token);
                        }

                        var packageHash = await packageDownloader.GetPackageHashAsync("SHA512", cancellationToken);

                        File.WriteAllText(tempHashPath, packageHash);

                        // Now rename the tmp file
                        if (packageExtractionContext.PackageSaveMode.HasFlag(PackageSaveMode.Nupkg))
                        {
                            if (copiedNupkg)
                            {
                                // Dispose of it now because it is holding a lock on the temporary .nupkg file.
                                packageDownloader.Dispose();

                                File.Move(targetTempNupkg, targetNupkg);
                            }
                        }
                        else
                        {
                            try
                            {
                                File.Delete(targetTempNupkg);
                            }
                            catch (IOException ex)
                            {
                                logger.LogWarning(string.Format(
                                                      CultureInfo.CurrentCulture,
                                                      Strings.ErrorUnableToDeleteFile,
                                                      targetTempNupkg,
                                                      ex.Message));
                            }
                        }

                        // Note: PackageRepository relies on the hash file being written out as the
                        // final operation as part of a package install to assume a package was fully installed.
                        // Rename the tmp hash file
                        File.Move(tempHashPath, hashPath);

                        logger.LogVerbose($"Completed installation of {packageIdentity.Id} {packageIdentity.Version}");

                        telemetry.TelemetryEvent = new PackageExtractionTelemetryEvent(
                            packageExtractionContext.PackageSaveMode,
                            NuGetOperationStatus.Succeeded,
                            ExtractionSource.RestoreCommand,
                            packageIdentity);
                        return true;
                    }
                    else
                    {
                        logger.LogVerbose("Lock not required - Package already installed "
                                          + $"{packageIdentity.Id} {packageIdentity.Version}");

                        telemetry.TelemetryEvent = new PackageExtractionTelemetryEvent(
                            packageExtractionContext.PackageSaveMode,
                            NuGetOperationStatus.NoOp,
                            ExtractionSource.RestoreCommand,
                            packageIdentity);
                        return false;
                    }
                },
                                                                             token : token));
            }
        }
예제 #10
0
        /// <summary>
        /// Uses a copy function to install a package to a global packages directory.
        /// </summary>
        /// <param name="copyToAsync">
        /// A function which should copy the package to the provided destination stream.
        /// </param>
        /// <param name="packageExtractionContext">
        /// The version folder path context, which encapsulates all of the parameters to observe
        /// while installing the package.
        /// </param>
        /// <param name="token">The cancellation token.</param>
        /// <returns>
        /// True if the package was installed. False if the package already exists and therefore
        /// resulted in no copy operation.
        /// </returns>
        public static async Task <bool> InstallFromSourceAsync(
            string source,
            PackageIdentity packageIdentity,
            Func <Stream, Task> copyToAsync,
            VersionFolderPathResolver versionFolderPathResolver,
            PackageExtractionContext packageExtractionContext,
            CancellationToken token,
            Guid parentId = default(Guid))
        {
            if (copyToAsync == null)
            {
                throw new ArgumentNullException(nameof(copyToAsync));
            }

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

            var logger       = packageExtractionContext.Logger;
            var extractionId = Guid.NewGuid();

            using (var telemetry = TelemetryActivity.CreateTelemetryActivityWithNewOperationId(parentId))
            {
                var targetPath   = versionFolderPathResolver.GetInstallPath(packageIdentity.Id, packageIdentity.Version);
                var targetNuspec = versionFolderPathResolver.GetManifestFilePath(packageIdentity.Id, packageIdentity.Version);
                var targetNupkg  = versionFolderPathResolver.GetPackageFilePath(packageIdentity.Id, packageIdentity.Version);
                var hashPath     = versionFolderPathResolver.GetHashPath(packageIdentity.Id, packageIdentity.Version);

                logger.LogVerbose(
                    $"Acquiring lock for the installation of {packageIdentity.Id} {packageIdentity.Version}");

                // Acquire the lock on a nukpg before we extract it to prevent the race condition when multiple
                // processes are extracting to the same destination simultaneously
                return(await ConcurrencyUtilities.ExecuteWithFileLockedAsync(targetNupkg,
                                                                             action : async cancellationToken =>
                {
                    // If this is the first process trying to install the target nupkg, go ahead
                    // After this process successfully installs the package, all other processes
                    // waiting on this lock don't need to install it again.
                    if (!File.Exists(hashPath))
                    {
                        logger.LogVerbose(
                            $"Acquired lock for the installation of {packageIdentity.Id} {packageIdentity.Version}");

                        logger.LogMinimal(string.Format(
                                              CultureInfo.CurrentCulture,
                                              Strings.Log_InstallingPackage,
                                              packageIdentity.Id,
                                              packageIdentity.Version));

                        cancellationToken.ThrowIfCancellationRequested();

                        // We do not stop the package extraction after this point
                        // based on CancellationToken, but things can still be stopped if the process is killed.
                        if (Directory.Exists(targetPath))
                        {
                            // If we had a broken restore, clean out the files first
                            var info = new DirectoryInfo(targetPath);

                            foreach (var file in info.GetFiles())
                            {
                                file.Delete();
                            }

                            foreach (var dir in info.GetDirectories())
                            {
                                dir.Delete(true);
                            }
                        }
                        else
                        {
                            Directory.CreateDirectory(targetPath);
                        }

                        var targetTempNupkg = Path.Combine(targetPath, Path.GetRandomFileName());
                        var tempHashPath = Path.Combine(targetPath, Path.GetRandomFileName());
                        var packageSaveMode = packageExtractionContext.PackageSaveMode;

                        try
                        {
                            // Extract the nupkg
                            using (var nupkgStream = new FileStream(
                                       targetTempNupkg,
                                       FileMode.Create,
                                       FileAccess.ReadWrite,
                                       FileShare.ReadWrite | FileShare.Delete,
                                       bufferSize: 4096,
                                       useAsync: true))
                            {
                                await copyToAsync(nupkgStream);
                                nupkgStream.Seek(0, SeekOrigin.Begin);

                                using (var packageReader = new PackageArchiveReader(nupkgStream))
                                {
                                    if (packageSaveMode.HasFlag(PackageSaveMode.Nuspec) || packageSaveMode.HasFlag(PackageSaveMode.Files))
                                    {
                                        telemetry.StartIntervalMeasure();

                                        await VerifyPackageSignatureAsync(
                                            source,
                                            telemetry.OperationId,
                                            packageIdentity,
                                            packageExtractionContext,
                                            packageReader,
                                            token);

                                        telemetry.EndIntervalMeasure(PackagingConstants.PackageVerifyDurationName);
                                    }

                                    var nuspecFile = packageReader.GetNuspecFile();
                                    if ((packageSaveMode & PackageSaveMode.Nuspec) == PackageSaveMode.Nuspec)
                                    {
                                        packageReader.ExtractFile(nuspecFile, targetNuspec, logger);
                                    }

                                    if ((packageSaveMode & PackageSaveMode.Files) == PackageSaveMode.Files)
                                    {
                                        var nupkgFileName = Path.GetFileName(targetNupkg);
                                        var nuspecFileName = Path.GetFileName(targetNuspec);
                                        var hashFileName = Path.GetFileName(hashPath);
                                        var packageFiles = packageReader.GetFiles()
                                                           .Where(file => ShouldInclude(file, hashFileName));
                                        var packageFileExtractor = new PackageFileExtractor(
                                            packageFiles,
                                            packageExtractionContext.XmlDocFileSaveMode);
                                        packageReader.CopyFiles(
                                            targetPath,
                                            packageFiles,
                                            packageFileExtractor.ExtractPackageFile,
                                            logger,
                                            token);
                                    }

                                    string packageHash;
                                    nupkgStream.Position = 0;
                                    packageHash = Convert.ToBase64String(new CryptoHashProvider("SHA512").CalculateHash(nupkgStream));

                                    File.WriteAllText(tempHashPath, packageHash);
                                }
                            }
                        }
                        catch (SignatureException)
                        {
                            try
                            {
                                DeleteTargetAndTempPaths(targetPath, targetTempNupkg);
                            }
                            catch (IOException ex)
                            {
                                logger.LogWarning(string.Format(
                                                      CultureInfo.CurrentCulture,
                                                      Strings.ErrorUnableToDeleteFile,
                                                      targetTempNupkg,
                                                      ex.Message));
                            }

                            telemetry.TelemetryEvent = new PackageExtractionTelemetryEvent(
                                packageExtractionContext.PackageSaveMode,
                                NuGetOperationStatus.Failed,
                                ExtractionSource.DownloadResource,
                                packageIdentity);
                            throw;
                        }

                        // Now rename the tmp file
                        if ((packageExtractionContext.PackageSaveMode & PackageSaveMode.Nupkg) ==
                            PackageSaveMode.Nupkg)
                        {
                            File.Move(targetTempNupkg, targetNupkg);
                        }
                        else
                        {
                            try
                            {
                                File.Delete(targetTempNupkg);
                            }
                            catch (IOException ex)
                            {
                                logger.LogWarning(string.Format(
                                                      CultureInfo.CurrentCulture,
                                                      Strings.ErrorUnableToDeleteFile,
                                                      targetTempNupkg,
                                                      ex.Message));
                            }
                        }

                        // Note: PackageRepository relies on the hash file being written out as the
                        // final operation as part of a package install to assume a package was fully installed.
                        // Rename the tmp hash file
                        File.Move(tempHashPath, hashPath);

                        logger.LogVerbose($"Completed installation of {packageIdentity.Id} {packageIdentity.Version}");

                        telemetry.TelemetryEvent = new PackageExtractionTelemetryEvent(
                            packageExtractionContext.PackageSaveMode,
                            NuGetOperationStatus.Succeeded,
                            ExtractionSource.DownloadResource,
                            packageIdentity);
                        return true;
                    }
                    else
                    {
                        logger.LogVerbose("Lock not required - Package already installed "
                                          + $"{packageIdentity.Id} {packageIdentity.Version}");

                        telemetry.TelemetryEvent = new PackageExtractionTelemetryEvent(
                            packageExtractionContext.PackageSaveMode,
                            NuGetOperationStatus.NoOp,
                            ExtractionSource.DownloadResource,
                            packageIdentity);
                        return false;
                    }
                },
                                                                             token : token));
            }
        }
예제 #11
0
        public static async Task <IEnumerable <string> > ExtractPackageAsync(
            string source,
            PackageReaderBase packageReader,
            PackagePathResolver packagePathResolver,
            PackageExtractionContext packageExtractionContext,
            CancellationToken token,
            Guid parentId = default(Guid))
        {
            if (packageReader == null)
            {
                throw new ArgumentNullException(nameof(packageReader));
            }

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

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

            token.ThrowIfCancellationRequested();

            var packageSaveMode = packageExtractionContext.PackageSaveMode;
            var extractionId    = Guid.NewGuid();
            var filesAdded      = new List <string>();

            using (var telemetry = TelemetryActivity.CreateTelemetryActivityWithNewOperationId(parentId))
            {
                var packageIdentityFromNuspec = await packageReader.GetIdentityAsync(token);

                try
                {
                    telemetry.StartIntervalMeasure();

                    await VerifyPackageSignatureAsync(
                        source,
                        telemetry.OperationId,
                        packageIdentityFromNuspec,
                        packageExtractionContext,
                        packageReader,
                        token);

                    telemetry.EndIntervalMeasure(PackagingConstants.PackageVerifyDurationName);
                }
                catch (SignatureException)
                {
                    telemetry.TelemetryEvent = new PackageExtractionTelemetryEvent(
                        packageExtractionContext.PackageSaveMode,
                        NuGetOperationStatus.Failed,
                        ExtractionSource.NuGetFolderProject,
                        packageIdentityFromNuspec);
                    throw;
                }

                var packageDirectoryInfo = Directory.CreateDirectory(packagePathResolver.GetInstallPath(packageIdentityFromNuspec));
                var packageDirectory     = packageDirectoryInfo.FullName;

                var packageFiles = await packageReader.GetPackageFilesAsync(packageSaveMode, token);

                var packageFileExtractor = new PackageFileExtractor(packageFiles, packageExtractionContext.XmlDocFileSaveMode);

                filesAdded.AddRange(await packageReader.CopyFilesAsync(
                                        packageDirectory,
                                        packageFiles,
                                        packageFileExtractor.ExtractPackageFile,
                                        packageExtractionContext.Logger,
                                        token));

                if (packageSaveMode.HasFlag(PackageSaveMode.Nupkg))
                {
                    var nupkgFilePath = Path.Combine(packageDirectory, packagePathResolver.GetPackageFileName(packageIdentityFromNuspec));
                    var filePath      = await packageReader.CopyNupkgAsync(nupkgFilePath, token);

                    if (!string.IsNullOrEmpty(filePath))
                    {
                        filesAdded.Add(filePath);
                    }
                }

                // Now, copy satellite files unless requested to not copy them
                if (packageExtractionContext.CopySatelliteFiles)
                {
                    filesAdded.AddRange(await CopySatelliteFilesAsync(
                                            packageReader,
                                            packagePathResolver,
                                            packageSaveMode,
                                            packageExtractionContext,
                                            token));
                }

                telemetry.TelemetryEvent = new PackageExtractionTelemetryEvent(
                    packageExtractionContext.PackageSaveMode,
                    NuGetOperationStatus.Succeeded,
                    ExtractionSource.NuGetFolderProject,
                    packageIdentityFromNuspec);
                return(filesAdded);
            }
        }
예제 #12
0
        public static async Task <IEnumerable <string> > ExtractPackageAsync(
            string source,
            Stream packageStream,
            PackagePathResolver packagePathResolver,
            PackageExtractionContext packageExtractionContext,
            CancellationToken token,
            Guid parentId = default(Guid))
        {
            if (packageStream == null)
            {
                throw new ArgumentNullException(nameof(packageStream));
            }

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

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

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

            var packageSaveMode    = packageExtractionContext.PackageSaveMode;
            var filesAdded         = new List <string>();
            var nupkgStartPosition = packageStream.Position;

            using (var telemetry = TelemetryActivity.CreateTelemetryActivityWithNewOperationId(parentId))
            {
                using (var packageReader = new PackageArchiveReader(packageStream, leaveStreamOpen: true))
                {
                    var packageIdentityFromNuspec = await packageReader.GetIdentityAsync(CancellationToken.None);

                    var installPath          = packagePathResolver.GetInstallPath(packageIdentityFromNuspec);
                    var packageDirectoryInfo = Directory.CreateDirectory(installPath);
                    var packageDirectory     = packageDirectoryInfo.FullName;

                    try
                    {
                        telemetry.StartIntervalMeasure();

                        await VerifyPackageSignatureAsync(
                            source,
                            telemetry.OperationId,
                            packageIdentityFromNuspec,
                            packageExtractionContext,
                            packageReader,
                            token);

                        telemetry.EndIntervalMeasure(PackagingConstants.PackageVerifyDurationName);
                    }
                    catch (SignatureException)
                    {
                        telemetry.TelemetryEvent = new PackageExtractionTelemetryEvent(
                            packageExtractionContext.PackageSaveMode,
                            NuGetOperationStatus.Failed,
                            ExtractionSource.NuGetFolderProject,
                            packageIdentityFromNuspec);
                        throw;
                    }

                    var packageFiles = await packageReader.GetPackageFilesAsync(packageSaveMode, token);

                    if ((packageSaveMode & PackageSaveMode.Nuspec) == PackageSaveMode.Nuspec)
                    {
                        var sourceNuspecFile = packageFiles.Single(p => PackageHelper.IsManifest(p));

                        var targetNuspecPath = Path.Combine(
                            packageDirectory,
                            packagePathResolver.GetManifestFileName(packageIdentityFromNuspec));

                        // Extract the .nuspec file with a well known file name.
                        filesAdded.Add(packageReader.ExtractFile(
                                           sourceNuspecFile,
                                           targetNuspecPath,
                                           packageExtractionContext.Logger));

                        packageFiles = packageFiles.Except(new[] { sourceNuspecFile });
                    }

                    var packageFileExtractor = new PackageFileExtractor(packageFiles, packageExtractionContext.XmlDocFileSaveMode);

                    filesAdded.AddRange(await packageReader.CopyFilesAsync(
                                            packageDirectory,
                                            packageFiles,
                                            packageFileExtractor.ExtractPackageFile,
                                            packageExtractionContext.Logger,
                                            token));

                    if ((packageSaveMode & PackageSaveMode.Nupkg) == PackageSaveMode.Nupkg)
                    {
                        // During package extraction, nupkg is the last file to be created
                        // Since all the packages are already created, the package stream is likely positioned at its end
                        // Reset it to the nupkgStartPosition
                        packageStream.Seek(nupkgStartPosition, SeekOrigin.Begin);

                        var nupkgFilePath = Path.Combine(
                            packageDirectory,
                            packagePathResolver.GetPackageFileName(packageIdentityFromNuspec));

                        filesAdded.Add(packageStream.CopyToFile(nupkgFilePath));
                    }

                    // Now, copy satellite files unless requested to not copy them
                    if (packageExtractionContext.CopySatelliteFiles)
                    {
                        filesAdded.AddRange(await CopySatelliteFilesAsync(
                                                packageReader,
                                                packagePathResolver,
                                                packageSaveMode,
                                                packageExtractionContext,
                                                token));
                    }
                    telemetry.TelemetryEvent = new PackageExtractionTelemetryEvent(
                        packageExtractionContext.PackageSaveMode,
                        NuGetOperationStatus.Succeeded,
                        ExtractionSource.NuGetFolderProject,
                        packageIdentityFromNuspec);
                }

                return(filesAdded);
            }
        }
예제 #13
0
        public static async Task <IEnumerable <string> > ExtractPackageAsync(
            string source,
            PackageReaderBase packageReader,
            Stream packageStream,
            PackagePathResolver packagePathResolver,
            PackageExtractionContext packageExtractionContext,
            CancellationToken token,
            Guid parentId = default(Guid))
        {
            if (packageStream == null)
            {
                throw new ArgumentNullException(nameof(packageStream));
            }

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

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

            var packageSaveMode    = packageExtractionContext.PackageSaveMode;
            var extractionId       = Guid.NewGuid();
            var nupkgStartPosition = packageStream.Position;
            var filesAdded         = new List <string>();


            using (var telemetry = TelemetryActivity.CreateTelemetryActivityWithNewOperationId(parentId))
            {
                var packageIdentityFromNuspec = await packageReader.GetIdentityAsync(token);

                try
                {
                    telemetry.StartIntervalMeasure();

                    await VerifyPackageSignatureAsync(
                        source,
                        telemetry.OperationId,
                        packageIdentityFromNuspec,
                        packageExtractionContext,
                        packageReader,
                        token);

                    telemetry.EndIntervalMeasure(PackagingConstants.PackageVerifyDurationName);
                }
                catch (SignatureException)
                {
                    telemetry.TelemetryEvent = new PackageExtractionTelemetryEvent(
                        packageExtractionContext.PackageSaveMode,
                        NuGetOperationStatus.Failed,
                        ExtractionSource.NuGetFolderProject,
                        packageIdentityFromNuspec);
                    throw;
                }

                var packageDirectoryInfo = Directory.CreateDirectory(packagePathResolver.GetInstallPath(packageIdentityFromNuspec));
                var packageDirectory     = packageDirectoryInfo.FullName;

                var packageFiles = await packageReader.GetPackageFilesAsync(packageSaveMode, token);

                var packageFileExtractor = new PackageFileExtractor(packageFiles, packageExtractionContext.XmlDocFileSaveMode);
                filesAdded.AddRange(await packageReader.CopyFilesAsync(
                                        packageDirectory,
                                        packageFiles,
                                        packageFileExtractor.ExtractPackageFile,
                                        packageExtractionContext.Logger,
                                        token));

                var nupkgFilePath = Path.Combine(packageDirectory, packagePathResolver.GetPackageFileName(packageIdentityFromNuspec));
                if (packageSaveMode.HasFlag(PackageSaveMode.Nupkg))
                {
                    // During package extraction, nupkg is the last file to be created
                    // Since all the packages are already created, the package stream is likely positioned at its end
                    // Reset it to the nupkgStartPosition
                    if (packageStream.Position != 0)
                    {
                        if (!packageStream.CanSeek)
                        {
                            throw new ArgumentException(Strings.PackageStreamShouldBeSeekable);
                        }

                        packageStream.Position = 0;
                    }

                    filesAdded.Add(packageStream.CopyToFile(nupkgFilePath));
                }

                // Now, copy satellite files unless requested to not copy them
                if (packageExtractionContext.CopySatelliteFiles)
                {
                    filesAdded.AddRange(await CopySatelliteFilesAsync(
                                            packageReader,
                                            packagePathResolver,
                                            packageSaveMode,
                                            packageExtractionContext,
                                            token));
                }

                telemetry.TelemetryEvent = new PackageExtractionTelemetryEvent(
                    packageExtractionContext.PackageSaveMode,
                    NuGetOperationStatus.Succeeded,
                    ExtractionSource.NuGetFolderProject,
                    packageIdentityFromNuspec);

                return(filesAdded);
            }
        }
예제 #14
0
        public async Task <RestoreResult> ExecuteAsync(CancellationToken token)
        {
            using (var telemetry = TelemetryActivity.CreateTelemetryActivityWithNewOperationId(ParentId))
            {
                _operationId = telemetry.OperationId;
                var telemetryEvent = new TelemetryEvent(ProjectRestoreInformation);
                telemetry.TelemetryEvent = telemetryEvent;
                var restoreTime = Stopwatch.StartNew();

                // Local package folders (non-sources)
                var localRepositories = new List <NuGetv3LocalRepository>
                {
                    _request.DependencyProviders.GlobalPackages
                };

                localRepositories.AddRange(_request.DependencyProviders.FallbackPackageFolders);

                var contextForProject = CreateRemoteWalkContext(_request, _logger);

                CacheFile cacheFile = null;
                if (NoOpRestoreUtilities.IsNoOpSupported(_request))
                {
                    var cacheFileAndStatus = EvaluateCacheFile();
                    cacheFile = cacheFileAndStatus.Key;
                    if (cacheFileAndStatus.Value)
                    {
                        if (NoOpRestoreUtilities.VerifyAssetsAndMSBuildFilesAndPackagesArePresent(_request))
                        {
                            // Replay Warnings and Errors from an existing lock file in case of a no-op.
                            await MSBuildRestoreUtility.ReplayWarningsAndErrorsAsync(_request.ExistingLockFile, _logger);

                            restoreTime.Stop();

                            return(new NoOpRestoreResult(
                                       _success,
                                       _request.ExistingLockFile,
                                       _request.ExistingLockFile,
                                       _request.ExistingLockFile.Path,
                                       cacheFile,
                                       _request.Project.RestoreMetadata.CacheFilePath,
                                       _request.ProjectStyle,
                                       restoreTime.Elapsed));
                        }
                    }
                }

                // Restore
                var graphs = await ExecuteRestoreAsync(
                    _request.DependencyProviders.GlobalPackages,
                    _request.DependencyProviders.FallbackPackageFolders,
                    contextForProject,
                    token);

                // Create assets file
                var assetsFile = BuildAssetsFile(
                    _request.ExistingLockFile,
                    _request.Project,
                    graphs,
                    localRepositories,
                    contextForProject);

                _success &= await ValidateRestoreGraphsAsync(graphs, _logger);

                // Check package compatibility
                var checkResults = await VerifyCompatibilityAsync(
                    _request.Project,
                    _includeFlagGraphs,
                    localRepositories,
                    assetsFile,
                    graphs,
                    _request.ValidateRuntimeAssets,
                    _logger);


                if (checkResults.Any(r => !r.Success))
                {
                    _success = false;
                }


                // Determine the lock file output path
                var assetsFilePath = GetAssetsFilePath(assetsFile);
                // Determine the cache file output path
                var cacheFilePath = NoOpRestoreUtilities.GetCacheFilePath(_request, assetsFile);

                // Tool restores are unique since the output path is not known until after restore
                if (_request.LockFilePath == null &&
                    _request.ProjectStyle == ProjectStyle.DotnetCliTool)
                {
                    _request.LockFilePath = assetsFilePath;
                }

                // Generate Targets/Props files
                var msbuildOutputFiles = Enumerable.Empty <MSBuildOutputFile>();

                if (contextForProject.IsMsBuildBased)
                {
                    msbuildOutputFiles = BuildAssetsUtils.GetMSBuildOutputFiles(
                        _request.Project,
                        assetsFile,
                        graphs,
                        localRepositories,
                        _request,
                        assetsFilePath,
                        _success,
                        _logger);
                }

                // If the request is for a lower lock file version, downgrade it appropriately
                DowngradeLockFileIfNeeded(assetsFile);

                // Revert to the original case if needed
                await FixCaseForLegacyReaders(graphs, assetsFile, token);

                // Write the logs into the assets file
                var logs = _logger.Errors
                           .Select(l => AssetsLogMessage.Create(l))
                           .ToList();

                _success &= !logs.Any(l => l.Level == LogLevel.Error);

                assetsFile.LogMessages = logs;

                if (cacheFile != null)
                {
                    cacheFile.Success = _success;
                }

                restoreTime.Stop();

                // Create result
                return(new RestoreResult(
                           _success,
                           graphs,
                           checkResults,
                           msbuildOutputFiles,
                           assetsFile,
                           _request.ExistingLockFile,
                           assetsFilePath,
                           cacheFile,
                           cacheFilePath,
                           _request.ProjectStyle,
                           restoreTime.Elapsed));
            }
        }