Skip to content
This repository has been archived by the owner on Dec 18, 2017. It is now read-only.

Commit

Permalink
Print the source of depedencies for dnu list --assembly
Browse files Browse the repository at this point in the history
  • Loading branch information
troydai committed Apr 10, 2015
1 parent f3d42ea commit d04ee4e
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 35 deletions.
84 changes: 71 additions & 13 deletions src/Microsoft.Framework.PackageManager/List/AssemblyWalker.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
Expand All @@ -18,38 +19,74 @@ public class AssemblyWalker
private readonly FrameworkName _framework;
private readonly ApplicationHostContext _hostContext;
private readonly string _runtimeFolder;
private readonly bool _showDetails;
private readonly Reports _reports;

private HashSet<string> _assemblyFilePaths;
private Dictionary<string, HashSet<string>> _dependencyAssemblySources;
private Dictionary<string, HashSet<string>> _dependencyPackageSources;

public AssemblyWalker(
FrameworkName framework,
ApplicationHostContext hostContext,
string runtimeFolder)
string runtimeFolder,
bool showDetails,
Reports reports)
{
_framework = framework;
_hostContext = hostContext;
_runtimeFolder = runtimeFolder;
_showDetails = showDetails;
_reports = reports;
}

public ISet<string> Walk(IGraphNode<LibraryDescription> root)
public void Walk(IGraphNode<LibraryDescription> root)
{
var assemblies = new HashSet<string>();
_assemblyFilePaths = new HashSet<string>();
_dependencyAssemblySources = new Dictionary<string, HashSet<string>>();
_dependencyPackageSources = new Dictionary<string, HashSet<string>>();

var libraries = new HashSet<LibraryDescription>();
root.DepthFirstPreOrderWalk(visitNode: (node, _) => VisitLibrary(node, _, libraries, assemblies));
root.DepthFirstPreOrderWalk(visitNode: (node, _) => VisitLibrary(node, _, libraries));

_reports.Information.WriteLine("\n[Target framework {0} ({1})]\n",
_framework.ToString(), VersionUtility.GetShortFrameworkName(_framework));

return assemblies;
foreach (var assemblyFilePath in _assemblyFilePaths.OrderBy(assemblyName => assemblyName))
{
_reports.Information.WriteLine(assemblyFilePath);
if (_showDetails)
{
var assemblyName = Path.GetFileNameWithoutExtension(assemblyFilePath);

HashSet<string> packagesSources;
if (_dependencyPackageSources.TryGetValue(assemblyName, out packagesSources) && packagesSources.Any())
{
_reports.Information.WriteLine(" from package: {0}", string.Join(", ", packagesSources.ToArray()));
}

HashSet<string> assemblySources;
if (_dependencyAssemblySources.TryGetValue(assemblyName, out assemblySources) && assemblySources.Any())
{
_reports.Information.WriteLine(" from assembly: {0}", string.Join(", ", assemblySources.ToArray()));
}
}
}
}

private bool VisitLibrary(IGraphNode<LibraryDescription> node,
IEnumerable<IGraphNode<LibraryDescription>> ancestors,
ISet<LibraryDescription> visitedLibraries,
ISet<string> assemblies)
ISet<LibraryDescription> visitedLibraries)
{
if (visitedLibraries.Add(node.Item))
{
foreach (var loadableAssembly in node.Item.LoadableAssemblies)
{
AddDependencySource(_dependencyPackageSources, loadableAssembly, node.Item.Identity.Name);

DepthFirstGraphTraversal.PreOrderWalk(
root: loadableAssembly,
visitNode: (assemblyNode, assemblyAncestors) => VisitAssembly(assemblyNode, assemblyAncestors, assemblies),
visitNode: (assemblyName, assemblyAncestors) => VisitAssembly(assemblyName, assemblyAncestors),
getChildren: GetAssemblyDependencies);
}

Expand All @@ -65,31 +102,38 @@ private IEnumerable<string> GetAssemblyDependencies(string assemblyName)
if (filepath != null && File.Exists(filepath))
{
var assemblyInfo = new AssemblyInformation(filepath, processorArchitecture: null);
return assemblyInfo.GetDependencies();
var dependencies = assemblyInfo.GetDependencies();

foreach (var dependency in dependencies)
{
AddDependencySource(_dependencyAssemblySources, dependency, assemblyName);
}

return dependencies;
}
else
{
return Enumerable.Empty<string>();
}
}

private bool VisitAssembly(string assembly, IEnumerable<string> ancestors, ISet<string> assemblies)
private bool VisitAssembly(string assemblyName, IEnumerable<string> ancestors)
{
// determine if keep walking down the path
if (ancestors.Any(a => a == assembly))
if (ancestors.Any(a => string.Equals(a, assemblyName, StringComparison.Ordinal)))
{
// break the reference loop
return false;
}

var filepath = ResolveAssemblyFilePath(assembly);
var filepath = ResolveAssemblyFilePath(assemblyName);
if (filepath == null)
{
return false;
}

filepath = Path.GetFullPath(filepath);
assemblies.Add(filepath);
_assemblyFilePaths.Add(filepath);

return true;
}
Expand All @@ -115,5 +159,19 @@ private string ResolveAssemblyFilePath(string assemblyName)

return null;
}

private static void AddDependencySource(Dictionary<string, HashSet<string>> dependencySources,
string dependency,
string source)
{
HashSet<string> sources;
if (!dependencySources.TryGetValue(dependency, out sources))
{
sources = new HashSet<string>();
dependencySources.Add(dependency, sources);
}

sources.Add(source);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,21 +36,16 @@ public bool Execute()
return true;
}

// 2. Walk the local dependencies
var assemblyWalker = new AssemblyWalker(_framework, _hostContext, _options.RuntimeFolder);
var assemblies = assemblyWalker.Walk(root);

foreach (var assemblyName in assemblies.OrderBy(assemblyName => assemblyName))
{
_options.Reports.Information.WriteLine(assemblyName);
}
// 2. Walk the local dependencies and print the assemblies list
var assemblyWalker = new AssemblyWalker(_framework, _hostContext, _options.RuntimeFolder, _options.Details, _options.Reports);
assemblyWalker.Walk(root);

return true;
}

private void Render(IGraphNode<LibraryDescription> root)
{
var renderer = new LibraryDependencyFlatRenderer(_options.HideDependents, _options.ResultsFilter, _options.Project.Dependencies.Select(dep => dep.LibraryRange.Name));
var renderer = new LibraryDependencyFlatRenderer(_options.Details, _options.ResultsFilter, _options.Project.Dependencies.Select(dep => dep.LibraryRange.Name));
var content = renderer.GetRenderContent(root);

if (content.Any())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public DependencyListOptions(Reports reports, CommandArgument path)

public IEnumerable<string> TargetFrameworks { get; set; }

public bool HideDependents { get; set; }
public bool Details { get; set; }

public string ResultsFilter { get; set; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace Microsoft.Framework.PackageManager.List
public class LibraryDependencyFinder
{
public static IGraphNode<LibraryDescription> Build([NotNull] IList<LibraryDescription> libraries,
[NotNull]Runtime.Project project)
[NotNull] Runtime.Project project)
{
var libDictionary = libraries.ToDictionary(desc => desc.Identity);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ namespace Microsoft.Framework.PackageManager.List
{
public class LibraryDependencyFlatRenderer
{
private readonly bool _hideDependent;
private readonly bool _showDetails;
private readonly string _filterPattern;
private readonly HashSet<string> _listedProjects;

public LibraryDependencyFlatRenderer(bool hideDependent, string filterPattern, IEnumerable<string> listedProjects)
public LibraryDependencyFlatRenderer(bool showDetails, string filterPattern, IEnumerable<string> listedProjects)
{
_hideDependent = hideDependent;
_showDetails = showDetails;
_filterPattern = filterPattern;
_listedProjects = new HashSet<string>(listedProjects);
}
Expand Down Expand Up @@ -87,10 +87,12 @@ private void RenderLibraries(IEnumerable<LibraryDescription> descriptions,
results.Add(string.Format("{0} - Unresolved", libDisplay).Red().Bold());
}

if (!_hideDependent)
if (_showDetails)
{
results.Add(libDisplay.Bold());

var dependents = string.Join(", ", dependenciesMap[description].Select(dep => dep.ToString()).OrderBy(name => name));
results.Add(string.Format(" -> {0}", dependents));
results.Add(string.Format(" from: {0}", dependents));
}
}
}
Expand Down
10 changes: 4 additions & 6 deletions src/Microsoft.Framework.PackageManager/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,11 @@
using System.Net;
using System.Reflection;
using System.Threading;
using Microsoft.Framework.PackageManager.Packages;
using Microsoft.Framework.PackageManager.List;
using Microsoft.Framework.PackageManager.Packages;
using Microsoft.Framework.PackageManager.Publish;
using Microsoft.Framework.Runtime;
using Microsoft.Framework.Runtime.Common.CommandLine;
using System.Linq;
using System.Diagnostics;

namespace Microsoft.Framework.PackageManager
{
Expand Down Expand Up @@ -370,8 +368,8 @@ public int Main(string[] args)
var runtimeFolder = c.Option("--runtime <PATH>",
"The folder containing all available framework assemblies",
CommandOptionType.SingleValue);
var hideDependents = c.Option("--hide-dependents",
"Hide the immediate dependents of libraries referenced in the project",
var details = c.Option("--details",
"Show the details of how each dependency is introduced",
CommandOptionType.NoValue);
var resultsFilter = c.Option("--filter <PATTERN>",
"Filter the libraries referenced by the project base on their names. The matching pattern supports * and ?",
Expand All @@ -386,7 +384,7 @@ public int Main(string[] args)
TargetFrameworks = frameworks.Values,
ShowAssemblies = showAssemblies.HasValue(),
RuntimeFolder = runtimeFolder.Value(),
HideDependents = hideDependents.HasValue(),
Details = details.HasValue(),
ResultsFilter = resultsFilter.Value()
};
Expand Down

0 comments on commit d04ee4e

Please sign in to comment.