/// <summary> /// Returns a dictionary mapping of IPackages to their included files. /// </summary> /// <param name="package"></param> /// <param name="result"></param> /// <returns></returns> private IEnumerable <IPackage> GetDependencyAssemblyList(IPackage package, PackageAuditResult result) { var packageDependencies = new List <IPackage>(); foreach (var dependency in package.Dependencies) { //HACK Slow and wrong and evil and I HATE ODATA. var dependencyPackage = _feedPackages.FirstOrDefault(p => p.Id.Equals(dependency.Id, StringComparison.OrdinalIgnoreCase)); if (dependencyPackage == null) { result.UnresolvedDependencies.Add(dependency); continue; } packageDependencies.Add(dependencyPackage); } return(packageDependencies); }
/// <summary> /// Audits a feed and provides back a set of results /// </summary> /// <returns></returns> public List <PackageAuditResult> Audit(IPackage packageToAudit = null) { StartPackageListDownload(this, new EventArgs()); _feedPackages = _packageRepository.GetPackages().Where(p => p.IsLatestVersion).OrderBy(p => p.Id).ToList(); FinishedPackageListDownload(this, new EventArgs()); //If we are auditing the whole feed, use the whole feed as the audit package list..... _auditPackages = packageToAudit == null ? _feedPackages : new List <IPackage>(new[] { packageToAudit }); foreach (var package in _auditPackages) { //OData wont let us query this remotely (again, f**k OData). if (_unlisted == false && package.Listed == false) { continue; } StartPackageAudit(this, new PackageAuditEventArgs { Package = package }); //Try the next one if we are using this one as an exception if (_wildcards.Any(w => w.IsMatch(package.Id.ToLowerInvariant()))) { PackageIgnored(this, new PackageIgnoreEventArgs { IgnoredPackage = package, Wildcard = true }); continue; } if (_exceptions.Any(e => e.Equals(package.Id, StringComparison.OrdinalIgnoreCase))) { PackageIgnored(this, new PackageIgnoreEventArgs { IgnoredPackage = package, StringMatch = true }); continue; } var currentResult = new PackageAuditResult { Package = package }; var actualAssemblyReferences = GetPackageAssemblyReferenceList(package, currentResult); //Prune dependency list based on additional assemblies included in the package... actualAssemblyReferences = RemoveInternallySatisfiedDependencies(actualAssemblyReferences, package); var packageDependencies = GetDependencyAssemblyList(package, currentResult).ToList(); actualAssemblyReferences = RemoveAssemblyExclusions(actualAssemblyReferences, currentResult); var usedDependencies = new List <IPackage>(); foreach (var actualDependency in actualAssemblyReferences) { var possibles = GetPossiblePackagesForAssembly(actualDependency, packageDependencies).ToList(); usedDependencies.AddRange(possibles.Select(p => p)); if (!possibles.Any()) { currentResult.UnresolvedAssemblyReferences.Add(actualDependency); if (_checkForFeedResolvableAssemblies) { //May be expensive.... if (GetPossiblePackagesForAssembly(actualDependency, _feedPackages).Any()) { currentResult.FeedResolvableReferences.Add(actualDependency); } } if (_checkGac) { if (CanResolveToGac(actualDependency.FullName) || CanResolveToGac(actualDependency.Name)) { currentResult.GacResolvableReferences.Add(actualDependency); } } } else { currentResult.ResolvedAssemblyReferences.Add(actualDependency); } } currentResult.UsedPackageDependencies.AddRange(packageDependencies.Where(usedDependencies.Contains).Select(l => l)); currentResult.UnusedPackageDependencies.AddRange(packageDependencies.Where(p => !usedDependencies.Contains(p)).Select(l => l)); _results.Add(currentResult); FinishedPackageAudit(this, new PackageAuditEventArgs { Package = package }); } _unresolvableAssemblyReferences = GetUnresolvedAssemblies(_results); UpdateUnresolvablePackageAuditResults(_results, _unresolvableAssemblyReferences); return(_results); }
/// <summary> /// Gets a list of AssemblyNames referenced by the files in a package /// </summary> /// <param name="package">The package to check.</param> /// <param name="result">A result to append errors to.</param> /// <returns></returns> private static IEnumerable <AssemblyName> GetPackageAssemblyReferenceList(IPackage package, PackageAuditResult result) { var actualDependencies = new List <AssemblyName>(); foreach (var file in package.GetFiles().Where(f => f.Path.EndsWith(".dll") || f.Path.EndsWith("*.exe"))) { using (var stream = file.GetStream()) { try { var assembly = Assembly.Load(stream.ReadAllBytes()); actualDependencies.AddRange(assembly.GetReferencedAssemblies()); } catch (Exception) { result.UnloadablePackageFiles.Add(file.Path); } } } return(actualDependencies.Where(d => !IsProbablySystemAssembly(d)).Distinct(new AssemblyNameEqualityComparer())); }
private IEnumerable <AssemblyName> RemoveAssemblyExclusions(IEnumerable <AssemblyName> actualAssemblyReferences, PackageAuditResult currentResult) { var actualAssemblyReferencesList = actualAssemblyReferences.ToList(); var assemblyReferences = new List <AssemblyName>(actualAssemblyReferencesList); foreach (var assembly in actualAssemblyReferencesList) { if (_assemblyWildcards.Any(w => w.IsMatch(assembly.Name.ToLowerInvariant()))) { assemblyReferences.Remove(assembly); currentResult.AuditExclusionReferences.Add(assembly); } if (_assemblyExceptions.Any(e => e.Equals(assembly.Name, StringComparison.OrdinalIgnoreCase))) { assemblyReferences.Remove(assembly); currentResult.AuditExclusionReferences.Add(assembly); } } return(assemblyReferences); }
/// <summary> /// Audits a feed and provides back a set of results /// </summary> /// <returns></returns> public List<PackageAuditResult> Audit(IPackage packageToAudit = null) { StartPackageListDownload(this, new EventArgs()); _feedPackages = _packageRepository.GetPackages().Where(p => p.IsLatestVersion).OrderBy(p => p.Id).ToList(); FinishedPackageListDownload(this, new EventArgs()); //If we are auditing the whole feed, use the whole feed as the audit package list..... _auditPackages = packageToAudit == null ? _feedPackages : new List<IPackage>(new[] {packageToAudit}); foreach (var package in _auditPackages) { //OData wont let us query this remotely (again, f**k OData). if (_unlisted == false && package.Listed == false) continue; StartPackageAudit(this, new PackageAuditEventArgs {Package = package}); //Try the next one if we are using this one as an exception if (_wildcards.Any(w => w.IsMatch(package.Id.ToLowerInvariant()))) { PackageIgnored(this, new PackageIgnoreEventArgs {IgnoredPackage = package, Wildcard = true}); continue; } if (_exceptions.Any(e => e.Equals(package.Id,StringComparison.OrdinalIgnoreCase))) { PackageIgnored(this, new PackageIgnoreEventArgs { IgnoredPackage = package, StringMatch = true }); continue; } var currentResult = new PackageAuditResult {Package = package}; var actualAssemblyReferences = GetPackageAssemblyReferenceList(package, currentResult); //Prune dependency list based on additional assemblies included in the package... actualAssemblyReferences = RemoveInternallySatisfiedDependencies(actualAssemblyReferences, package); var packageDependencies = GetDependencyAssemblyList(package, currentResult).ToList(); actualAssemblyReferences = RemoveAssemblyExclusions(actualAssemblyReferences, currentResult); var usedDependencies = new List<IPackage>(); foreach (var actualDependency in actualAssemblyReferences) { var possibles = GetPossiblePackagesForAssembly(actualDependency, packageDependencies).ToList(); usedDependencies.AddRange(possibles.Select(p => p)); if (!possibles.Any()) { currentResult.UnresolvedAssemblyReferences.Add(actualDependency); if (_checkForFeedResolvableAssemblies) { //May be expensive.... if (GetPossiblePackagesForAssembly(actualDependency, _feedPackages).Any()) currentResult.FeedResolvableReferences.Add(actualDependency); } if (_checkGac) { if (CanResolveToGac(actualDependency.FullName) || CanResolveToGac(actualDependency.Name)) currentResult.GacResolvableReferences.Add(actualDependency); } } else currentResult.ResolvedAssemblyReferences.Add(actualDependency); } currentResult.UsedPackageDependencies.AddRange(packageDependencies.Where(usedDependencies.Contains).Select(l => l)); currentResult.UnusedPackageDependencies.AddRange(packageDependencies.Where(p => !usedDependencies.Contains(p)).Select(l => l)); _results.Add(currentResult); FinishedPackageAudit(this, new PackageAuditEventArgs{Package = package}); } _unresolvableAssemblyReferences = GetUnresolvedAssemblies(_results); UpdateUnresolvablePackageAuditResults(_results, _unresolvableAssemblyReferences); return _results; }
/// <summary> /// Gets a list of AssemblyNames referenced by the files in a package /// </summary> /// <param name="package">The package to check.</param> /// <param name="result">A result to append errors to.</param> /// <returns></returns> private static IEnumerable<AssemblyName> GetPackageAssemblyReferenceList(IPackage package, PackageAuditResult result) { var actualDependencies = new List<AssemblyName>(); foreach (var file in package.GetFiles().Where(f => f.Path.EndsWith(".dll") || f.Path.EndsWith("*.exe"))) { using (var stream = file.GetStream()) { try { var assembly = Assembly.Load(stream.ReadAllBytes()); actualDependencies.AddRange(assembly.GetReferencedAssemblies()); } catch (Exception) { result.UnloadablePackageFiles.Add(file.Path); } } } return actualDependencies.Where(d => !IsProbablySystemAssembly(d)).Distinct(new AssemblyNameEqualityComparer()); }
/// <summary> /// Returns a dictionary mapping of IPackages to their included files. /// </summary> /// <param name="package"></param> /// <param name="result"></param> /// <returns></returns> private IEnumerable<IPackage> GetDependencyAssemblyList(IPackage package, PackageAuditResult result) { var packageDependencies = new List<IPackage>(); foreach (var dependency in package.DependencySets.SelectMany(s => s.Dependencies)) { //HACK Slow and wrong and evil and I HATE ODATA. var dependencyPackage = _feedPackages.FirstOrDefault(p => p.Id.Equals(dependency.Id, StringComparison.OrdinalIgnoreCase)); if (dependencyPackage == null) { result.UnresolvedDependencies.Add(dependency); continue; } packageDependencies.Add(dependencyPackage); } return packageDependencies; }
private IEnumerable<AssemblyName> RemoveAssemblyExclusions(IEnumerable<AssemblyName> actualAssemblyReferences, PackageAuditResult currentResult) { var actualAssemblyReferencesList = actualAssemblyReferences.ToList(); var assemblyReferences = new List<AssemblyName>(actualAssemblyReferencesList); foreach (var assembly in actualAssemblyReferencesList) { if (_assemblyWildcards.Any(w => w.IsMatch(assembly.Name.ToLowerInvariant()))) { assemblyReferences.Remove(assembly); currentResult.AuditExclusionReferences.Add(assembly); } if (_assemblyExceptions.Any(e => e.Equals(assembly.Name, StringComparison.OrdinalIgnoreCase))) { assemblyReferences.Remove(assembly); currentResult.AuditExclusionReferences.Add(assembly); } } return assemblyReferences; }