/// <summary>
        /// Performs a cleanup and consistency check for the package store.
        /// </summary>
        /// <param name="packageIndex">Interface used to ensure that the package index is correct.</param>
        /// <exception cref="ArgumentNullException"><paramref name="packageIndex"/> is null.</exception>
        public override void Clean(IPackageIndex packageIndex)
        {
            if (packageIndex == null)
            {
                throw new ArgumentNullException("packageIndex");
            }

            InitPackageStore();

            _logger.Debug("Clean('" + packageIndex + "') called");

            if (_fileSystemOperations.DirectoryExists(RootPath))
            {
                _logger.DebugFormat("Enumerating directories in {0}...", RootPath);

                IEnumerable <string> packageDirectories;
                try
                {
                    packageDirectories = _fileSystemOperations.EnumerateDirectories(RootPath);
                }
                catch (Exception ex)
                {
                    _logger.Error(string.Format("Could not access RootPath '{0}'. Skipping feed cleanup.", RootPath), ex);
                    return;
                }

                foreach (var packageDirectory in packageDirectories)
                {
                    _logger.DebugFormat("Enumerating all nupkg files in packageDirectory '{0}'", packageDirectory);

                    bool any = false;
                    var  packageFileNames = _fileSystemOperations.EnumerateFiles(packageDirectory, "*.nupkg");
                    foreach (var fileName in packageFileNames)
                    {
                        _logger.DebugFormat("Inspecting package '{0}'", fileName);
                        var localFileName = _fileSystemOperations.GetFileName(fileName);

                        any = true;
                        try
                        {
                            using (var stream = TryOpenStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete))
                            {
                                if (stream != null)
                                {
                                    _logger.DebugFormat("Validating {0}...", localFileName);
                                    if (packageIndex.ValidatePackage(stream))
                                    {
                                        _logger.DebugFormat("Verifying that {0} is the correct file name...", localFileName);
                                        stream.Position = 0;
                                        var package          = NuGetPackage.ReadFromNupkgFile(stream);
                                        var expectedFileName = package.Id + "." + package.Version + ".nupkg";
                                        if (!string.Equals(localFileName, expectedFileName, StringComparison.OrdinalIgnoreCase))
                                        {
                                            _logger.WarnFormat("File {0} has incorrect name; should be {1}", localFileName, expectedFileName);
                                            _logger.DebugFormat("Renaming {0} to {1}...", localFileName, expectedFileName);

                                            var fullExpectedFileName = Path.Combine(packageDirectory, expectedFileName);
                                            if (File.Exists(fullExpectedFileName))
                                            {
                                                try
                                                {
                                                    _logger.Debug("Deleting target file '" + fullExpectedFileName + "'");
                                                    _fileSystemOperations.DeleteFile(fullExpectedFileName);
                                                }
                                                catch (Exception ex)
                                                {
                                                    _logger.Error("Exception while deleting target file '" + fullExpectedFileName + "'", ex);
                                                }
                                            }
                                            try
                                            {
                                                _logger.DebugFormat("Moving package from '{0}' to '{1}'.", fileName, fullExpectedFileName);
                                                _fileSystemOperations.MoveFile(fileName, fullExpectedFileName);
                                                _logger.Debug("Package renamed.");
                                            }
                                            catch (Exception ex)
                                            {
                                                _logger.Error("Could not rename package.", ex);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            _logger.Error(string.Format("Could not validate '{0}'", fileName), ex);
                            StoredProcs.PackageIndexingErrors_LogIndexingError(FeedId, localFileName, ex.Message,
                                                                               Encoding.UTF8.GetBytes(ex.StackTrace ?? string.Empty)
                                                                               ).Execute();
                        }
                    }

                    if (!any)
                    {
                        try
                        {
                            _logger.DebugFormat("Deleting empty directory {0}...", packageDirectory);
                            _fileSystemOperations.DeleteDirectory(packageDirectory);
                        }
                        catch
                        {
                            _logger.Warn("Directory could not be deleted; it may not be empty.");
                        }
                    }
                }

                packageIndex.RemoveRemaining();
            }
            else
            {
                _logger.DebugFormat("Package root path '{0}' not found. Nothing to do.", RootPath);
            }
        }
Ejemplo n.º 2
0
        public override void Import(IBuildImporterContext context)
        {
            var configurer = (NuGetConfigurer)this.GetExtensionConfigurer();

            if (configurer.AlwaysClearNuGetCache)
            {
                this.LogDebug("Clearing NuGet cache...");
                if (NuGetConfigurer.ClearCache())
                {
                    this.LogDebug("Cache cleared!");
                }
                else
                {
                    this.LogWarning("Error clearing cache; a file may be locked.");
                }
            }

            var nugetExe = configurer != null ? configurer.NuGetExe : null;

            if (string.IsNullOrEmpty(nugetExe))
            {
                nugetExe = Path.Combine(Path.GetDirectoryName(typeof(NuGetBuildImporter).Assembly.Location), "nuget.exe");
            }

            var packageSource = Util.CoalesceStr(this.PackageSource, configurer != null ? configurer.PackageSource : null);

            var args = "install \"" + this.PackageId + "\" -ExcludeVersion -NoCache";

            if (!string.IsNullOrEmpty(this.PackageVersion))
            {
                args += " -Version \"" + this.PackageVersion + "\"";
            }
            if (this.IncludePrerelease)
            {
                args += " -Prerelease";
            }
            if (!string.IsNullOrEmpty(packageSource))
            {
                args += " -Source \"" + packageSource + "\"";
            }

            var tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());

            try
            {
                Directory.CreateDirectory(tempPath);

                args += " -OutputDirectory \"" + tempPath + "\"";

                if (!string.IsNullOrWhiteSpace(this.AdditionalArguments))
                {
                    args += " " + this.AdditionalArguments;
                }

                this.LogDebug($"Executing {nugetExe} {args}");
                this.LogInformation("Executing NuGet...");

                using (var process = new LocalProcess(new RemoteProcessStartInfo {
                    FileName = nugetExe, Arguments = args
                }))
                {
                    process.OutputDataReceived += this.Process_OutputDataReceived;
                    process.ErrorDataReceived  += this.Process_ErrorDataReceived;
                    process.Start();
                    process.WaitForExit();

                    if (process.ExitCode != 0)
                    {
                        this.LogError($"NuGet failed with exit code {process.ExitCode}.");
                        return;
                    }
                }

                this.LogInformation("NuGet indicated successful package install.");

                var packageRootPath = Path.Combine(tempPath, this.PackageId);
                var artifactName    = this.PackageId;

                if (this.CaptureIdAndVersion || this.IncludeVersionInArtifactName)
                {
                    try
                    {
                        var nupkgPath = Path.Combine(packageRootPath, this.PackageId + ".nupkg");
                        this.LogDebug($"Attempting to gather metadata from {nupkgPath}...");
                        var nuspec = NuGetPackage.ReadFromNupkgFile(nupkgPath);

                        var packageId      = nuspec.Id;
                        var packageVersion = nuspec.Version.OriginalString;

                        if (this.CaptureIdAndVersion)
                        {
                            this.LogDebug("Setting $ImportedPackageId = " + packageId);
                            SetBuildVariable(context, "ImportedPackageId", packageId);

                            this.LogDebug("Setting $ImportedPackageVersion = " + packageVersion);
                            SetBuildVariable(context, "ImportedPackageVersion", packageVersion);
                        }

                        if (this.IncludeVersionInArtifactName)
                        {
                            artifactName = packageId + "." + packageVersion;
                        }
                    }
                    catch (Exception ex)
                    {
                        this.LogError("Could not read package metadata: " + ex.ToString());
                        return;
                    }
                }

                var rootCapturePath = Path.Combine(packageRootPath, (this.PackageArtifactRoot ?? string.Empty).Replace('/', '\\').TrimStart('/', '\\'));
                this.LogDebug($"Capturing files in {rootCapturePath}...");

                var rootEntry = Util.Files.GetDirectoryEntry(
                    new GetDirectoryEntryCommand
                {
                    Path            = rootCapturePath,
                    IncludeRootPath = true,
                    Recurse         = true
                }
                    ).Entry;

                using (var agent = BuildMasterAgent.CreateLocalAgent())
                {
                    var fileOps    = agent.GetService <IFileOperationsExecuter>();
                    var matches    = Util.Files.Comparison.GetMatches(rootCapturePath, rootEntry, new[] { "!\\" + this.PackageId + ".nupkg", "*" });
                    var artifactId = new ArtifactIdentifier(context.ApplicationId, context.ReleaseNumber, context.BuildNumber, context.DeployableId, artifactName);

                    this.LogInformation($"Creating artifact {artifactName}...");
                    using (var artifact = new ArtifactBuilder(artifactId))
                    {
                        artifact.RootPath = rootCapturePath;

                        foreach (var match in matches)
                        {
                            artifact.Add(match, fileOps);
                        }

                        artifact.Commit();
                    }

                    this.LogInformation("Artifact created.");
                }
            }
            finally
            {
                try
                {
                    DirectoryEx.Delete(tempPath);
                }
                catch
                {
                }
            }
        }