Skip to content

Instantly share code, notes, and snippets.

@Tarmil
Last active November 20, 2019 13:38
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Tarmil/88ab4c8af7528e638e5d5de4e9e9c2d1 to your computer and use it in GitHub Desktop.
Save Tarmil/88ab4c8af7528e638e5d5de4e9e9c2d1 to your computer and use it in GitHub Desktop.
Override NuGet/Paket package references with local projects
<?xml version="1.0" encoding="utf-8"?>
<Project>
<!--
Override NuGet (or Paket) references with a set of local projects.
Usage:
* Add this file at the root above all your projects, so that they all gain the capability to override a package.
* In a solution where you want to override a package, add a file Directory.Build.props like the following:
<?xml version="1.0" encoding="utf-8"?>
<Project>
<ItemGroup>
<PackageOverride Include="PackageA">
<Projects>$(MSBuildThisFileDirectory)PackageA\PackageA\PackageA.csproj</Projects>
</PackageOverride>
<PackageOverride Include="PackageB">
<Projects>
$(MSBuildThisFileDirectory)PackageB\PackageB.AssemblyA\PackageB.AssemblyA.csproj;
$(MSBuildThisFileDirectory)PackageB\PackageB.AssemblyB\PackageB.AssemblyB.csproj
</Projects>
</PackageOverride>
<PackageOverride Include="PackageC">
<Assemblies>
$(MSBuildThisFileDirectory)PackageB\PackageB.AssemblyA\bin\Debug\net452\PackageB.AssemblyA.dll;
$(MSBuildThisFileDirectory)PackageB\PackageB.AssemblyB\bin\Debug\net452\PackageB.AssemblyB.dll
</Assemblies>
</PackageOverride>
</ItemGroup>
</Project>
With the above:
* Any project that references the package PackageA will reference the project PackageA instead.
* Any project that references the package PackageB will reference the projects PackageB.AssemblyA and PackageB.AssemblyB instead.
* Any project that references the package PackageC will reference the assemblies listed instead.
If there's a Directory.Build.targets anywhere in your solution, add the following at the top of it so that it keeps looking for this one:
<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.targets', '$(MSBuildThisFileDirectory)../'))" Condition="Exists($([MSBuild]::GetPathOfFileAbove('Directory.Build.targets', '$(MSBuildThisFileDirectory)../')))" />
Similarly, if there's a Directory.Build.props anywhere in your solution, add the following at the top of it so that it keeps looking for your overrides:
<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.targets', '$(MSBuildThisFileDirectory)../'))" Condition="Exists($([MSBuild]::GetPathOfFileAbove('Directory.Build.targets', '$(MSBuildThisFileDirectory)../')))" />
CAVEAT: This script correctly overrides transitive dependencies of package dependencies; however it does not override transitive dependencies of project dependencies.
That is, if project A depends on local project B, which depends on package P, then overriding P will result in A not referencing P's override.
To fix this, add a package reference from A to P.
-->
<ItemGroup>
<_OldPackageReference Include="@(PackageReference)" />
<PackageReference Remove="@(PackageOverride)" /><!-- Works in VS -->
</ItemGroup>
<Target Name="_OverridePackages" AfterTargets="CollectPackageReferences">
<ItemGroup>
<_PackageOverride Include="@(PackageOverride)"
Condition="( '@(PackageReference)' == '@(PackageOverride)' or '@(_OldPackageReference)' == '@(PackageOverride)' ) and %(Identity) != '' " />
<PackageReference Remove="@(_PackageOverride)" /><!-- Works in dotnet build -->
<ProjectReference Include="%(_PackageOverride.Projects)"
Condition=" '$(MSBuildProjectFullPath)' != %(_PackageOverride.Projects) " />
<Reference Include="@(_PackageOverride->Metadata('Assemblies'))" />
</ItemGroup>
<Warning Text="Overriding NuGet package @(_PackageOverride)" Condition="'%(Identity)' != ''" />
<!-- <Warning Text="Override assemblies: @(_PackageOverride->Metadata('Assemblies'))" /> -->
</Target>
</Project>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment