protected virtual void ExtractPackageFilesToProject(IPackage package)
{
// BUG 491: Installing a package with incompatible binaries still does a partial install.
// Resolve assembly references and content files first so that if this fails we never do anything to the project
List<IPackageAssemblyReference> assemblyReferences = Project.GetCompatibleItemsCore(package.AssemblyReferences).ToList();
List<FrameworkAssemblyReference> frameworkReferences = Project.GetCompatibleItemsCore(package.FrameworkAssemblies).ToList();
List<IPackageFile> contentFiles = Project.GetCompatibleItemsCore(package.GetContentFiles()).ToList();
List<IPackageFile> buildFiles = Project.GetCompatibleItemsCore(package.GetBuildFiles()).ToList();
// If the package doesn't have any compatible assembly references or content files,
// throw, unless it's a meta package.
if (assemblyReferences.Count == 0 && frameworkReferences.Count == 0 && contentFiles.Count == 0 && buildFiles.Count == 0 &&
(package.FrameworkAssemblies.Any() || package.AssemblyReferences.Any() || package.GetContentFiles().Any() || package.GetBuildFiles().Any()))
{
// for portable framework, we want to show the friendly short form (e.g. portable-win8+net45+wp8) instead of ".NETPortable, Profile=Profile104".
FrameworkName targetFramework = Project.TargetFramework;
string targetFrameworkString = targetFramework.IsPortableFramework()
? VersionUtility.GetShortFrameworkName(targetFramework)
: targetFramework != null ? targetFramework.ToString() : null;
throw new InvalidOperationException(
String.Format(CultureInfo.CurrentCulture,
NuGetResources.UnableToFindCompatibleItems, package.GetFullName(), targetFrameworkString));
}
// IMPORTANT: this filtering has to be done AFTER the 'if' statement above,
// so that we don't throw the exception in case the <References> filters out all assemblies.
FilterAssemblyReferences(assemblyReferences, package.PackageAssemblyReferences);
try
{
// Log target framework info for debugging
LogTargetFrameworkInfo(package, assemblyReferences, contentFiles, buildFiles);
// Add content files
Project.AddFiles(contentFiles, _fileTransformers);
// Add the references to the reference path
foreach (IPackageAssemblyReference assemblyReference in assemblyReferences)
{
if (assemblyReference.IsEmptyFolder())
{
continue;
}
// Get the physical path of the assembly reference
string referencePath = Path.Combine(PathResolver.GetInstallPath(package), assemblyReference.Path);
string relativeReferencePath = PathUtility.GetRelativePath(Project.Root, referencePath);
if (Project.ReferenceExists(assemblyReference.Name))
{
Project.RemoveReference(assemblyReference.Name);
}
// The current implementation of all ProjectSystem does not use the Stream parameter at all.
// We can't change the API now, so just pass in a null stream.
Project.AddReference(relativeReferencePath, Stream.Null);
}
// Add GAC/Framework references
foreach (FrameworkAssemblyReference frameworkReference in frameworkReferences)
{
if (!Project.ReferenceExists(frameworkReference.AssemblyName))
{
Project.AddFrameworkReference(frameworkReference.AssemblyName);
}
}
foreach (var importFile in buildFiles)
{
string fullImportFilePath = Path.Combine(PathResolver.GetInstallPath(package), importFile.Path);
Project.AddImport(
fullImportFilePath,
importFile.Path.EndsWith(".props", StringComparison.OrdinalIgnoreCase) ? ProjectImportLocation.Top : ProjectImportLocation.Bottom);
}
}
finally
{
if (_packageReferenceRepository != null)
{
// save the used project's framework if the repository supports it.
_packageReferenceRepository.AddPackage(package.Id, package.Version, package.DevelopmentDependency, Project.TargetFramework);
}
else
{
// Add package to local repository in the finally so that the user can uninstall it
// if any exception occurs. This is easier than rolling back since the user can just
// manually uninstall things that may have failed.
// If this fails then the user is out of luck.
LocalRepository.AddPackage(package);
}
}
}