Skip to content

Instantly share code, notes, and snippets.

@robertmclaws
Last active August 20, 2017 02:08
Show Gist options
  • Save robertmclaws/1cc9ea7fbcb3be56d0d46ecd6624c07b to your computer and use it in GitHub Desktop.
Save robertmclaws/1cc9ea7fbcb3be56d0d46ecd6624c07b to your computer and use it in GitHub Desktop.
Upgrades packages.config to VS2017's PackageReferences
// ===========================================
// Kill Packages.config With 🔥🔥🔥
// Prototype by Robert McLaws (@robertmclaws)
// Last Updated 19 Aug 2017
// ===========================================
//RWM: Set these to your specific project.
var projectFolder = @"D:\GitHub\SomeCoolApp\src\SomeProject";
var projectFile = @"SomeProject.csproj";
//RWM: Don't mess with these.
const string packagesConfigFile = "packages.config";
XNamespace defaultNs = "http://schemas.microsoft.com/developer/msbuild/2003";
var packageReferences = new XElement(defaultNs + "ItemGroup");
//RWM: Start by backing up the files.
File.Copy(Path.Combine(projectFolder, projectFile), Path.Combine(projectFolder, projectFile + ".bak"), true);
File.Copy(Path.Combine(projectFolder, packagesConfigFile), Path.Combine(projectFolder, packagesConfigFile + ".bak"));
//RWM: Load the files.
var project = XDocument.Load(Path.Combine(projectFolder, projectFile));
var packagesConfig = XDocument.Load(Path.Combine(projectFolder, packagesConfigFile));
var oldReferences = project.Root.Descendants().Where(c => c.Name.LocalName == "Reference");
var errors = project.Root.Descendants().Where(c => c.Name.LocalName == "Error");
var targets = project.Root.Descendants().Where(c => c.Name.LocalName == "Import");
foreach (var row in packagesConfig.Root.Elements().ToList())
{
//RWM: Create the new PackageReference.
packageReferences.Add(new XElement(defaultNs + "PackageReference",
new XAttribute("Include", row.Attribute("id").Value),
new XAttribute("Version", row.Attribute("version").Value)));
//RWM: Remove the old Standard Reference.
oldReferences.Where(c => c.Attribute("Include").Value.Split(new Char[] {','})[0].ToLower() == row.Attribute("id").Value.ToLower()).ToList()
.ForEach(c => c.Remove());
//RWM: Remove any remaining Standard References where the PackageId is in the HintPath.
oldReferences.Where(c => c.Descendants().Any(d => d.Value.Contains(row.Attribute("id").Value))).ToList()
.ForEach(c => c.Remove());
//RWM: Remove any Error conditions for missing Package Targets.
errors.Where(c => c.Attribute("Condition").Value.Contains(row.Attribute("id").Value)).ToList()
.ForEach(c => c.Remove());
//RWM: Remove any Package Targets.
targets.Where(c => c.Attribute("Project").Value.Contains(row.Attribute("id").Value)).ToList()
.ForEach(c => c.Remove());
}
//RWM: Fix up the project file by adding PackageReferences, removing packages.config, and pulling NuGet-added Targets.
project.Root.Elements().First(c => c.Name.LocalName == "ItemGroup").AddBeforeSelf(packageReferences);
var packageConfigReference = project.Root.Descendants().FirstOrDefault(c => c.Name.LocalName == "None" && c.Attribute("Include").Value == "packages.config");
if (packageConfigReference != null)
{
packageConfigReference.Remove();
}
var nugetBuildImports = project.Root.Descendants().FirstOrDefault(c => c.Name.LocalName == "Target" && c.Attribute("Name").Value == "EnsureNuGetPackageBuildImports");
if (nugetBuildImports != null && nugetBuildImports.Descendants().Count(c => c.Name.LocalName == "Error") == 0)
{
nugetBuildImports.Remove();
}
//RWM: Save the project and delete Packages.config.
File.WriteAllText(Path.Combine(projectFolder, projectFile), project.ToString());
File.Delete(Path.Combine(projectFolder, packagesConfigFile));
@clairernovotny
Copy link

Line 2 needs the 🔥 emoji. C# supports Unicode chars, what better place to use them?

@robertmclaws
Copy link
Author

Done. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment