/// <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); } }