Home

Get Nuget Package version from query

Hi,

Is there a good way of reporting the package version used in a query? I'm targeting a pre-release package and want to add a dump of the package version to remind me, however, I'm not clear on the best way of getting to the global package info from the PackageID reference.

So far I've looked at theses options:

void Main()
{
Util.CurrentQuery.NuGetReferences.Dump("Get Nuget package refs"); //the NuGet refs only

var t = typeof(Microsoft.Identity.Client.ClientApplicationBase);
t.Assembly.GetName().Version.ToString().Dump("Assembly version"); //the assembly version
Util.CurrentQuery.GetRawHeader().Dump("GetRawHeader"); //the xml
}

Ideally, I'd also like to do the reverse as well - iterate through all NuGet packages and report on which queries they're being used in.

Best regards

John

Comments

  • edited June 2018
    The query file itself won't contain the NuGet version unless you've locked it to a specific version. And the assembly version won't usually help because isn't necessarily tied to the NuGet package version.

    Try this:
    var t = typeof(Microsoft.Identity.Client.ClientApplicationBase);
    t.Assembly.Location.Dump();
    You'll notice the NuGet package version inside the path. You could either parse this with regex, or more reliably, walk the directory structure up until you find a file called LINQPadPackageInfo.xml. If you look in that file, you'll find the currently downloaded version number.
  • Thanks Joe, that's interesting. The location seemed to work earlier using this:
    void Main()
    {
    	var t = typeof(Microsoft.Identity.Client.ClientApplicationBase);	
    	var assemblyPath = t.Assembly.Location;
    	var assemblyDirPath = Path.GetDirectoryName(assemblyPath);
    	var dirInf = FindAncestorDirectory(new DirectoryInfo(assemblyDirPath),"Microsoft.Identity.Client(Prerelease)", "linqpad");
    	var packageDoc = XDocument.Load(Path.Combine(dirInf.FullName,"LINQPadPackageInfo.xml"));
    	packageDoc.Root.Element("MainPackageVersion").Value.Dump("Nuget package version");
    }
    
    
    public DirectoryInfo FindAncestorDirectory(DirectoryInfo currentDirInfo, string targetDirectoryName, string stopDirectoryName = null)
    {
    	if (currentDirInfo != null)
    	{
    		var currentName = currentDirInfo.Name.ToLower();
    		var targetName = targetDirectoryName.ToLower();
    		var stopName = stopDirectoryName?.ToLower();
    		
    		if (currentName == targetName)
    		{
    			return currentDirInfo;
    		}
    		else if (currentName == stopName)
    		{
    			return null;
    		}
    		else
    		{
    			return FindAncestorDirectory(currentDirInfo.Parent, targetDirectoryName, stopDirectoryName);
    		}
    	}
    	return null;
    }

    However, more recent runs (having added a couple of extra packages for testing) has assemblyPath returning something in the temp directory and so, of course, looking for the folder by name doesn't work:

    "C:\Users\John\AppData\Local\Temp\LINQPad5\_soklyzql\shadow_csksxj\microsoft.identity.client.dll"


    I guess an alternative is to go top down, so this works:
    void Main()
    {
    	var localPackagesFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"LINQPad\NuGet.FW46");
    	
    	foreach (var r in Util.CurrentQuery.NuGetReferences)
    	{
    		var packageFolderName = $"{r.PackageID}{(r.IsPrerelease ? "(Prerelease)" : "")}";
    		var packageDoc = XDocument.Load(Path.Combine(localPackagesFolder, packageFolderName, "LINQPadPackageInfo.xml"));
    		packageDoc.Root.Element("MainPackageVersion").Value.Dump($"Nuget package version - {r.PackageID}");
    	}
    }
    Might Util.GetLocalNugetDirectory() be a candidate for a more reliable way of getting the local packages path?

    In any case, thanks very much for your help.

    Best regards

    John
  • Good point - I'll look into adding this into the next build.
  • Great. Thank you.

    For anyone else who stumbles across this here's an extension method:
    	public static IEnumerable<NugetRefInfo> NuGetReferenceInfos(this LINQPad.ObjectModel.Query qry)
    	{
    		var localPackagesFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"LINQPad\NuGet.FW46");
    
    		foreach (var r in qry.NuGetReferences)
    		{
    			var refInfo = new NugetRefInfo(r);
    			var packageFolderName = $"{refInfo.PackageID}{(refInfo.IsPrerelease ? "(Prerelease)" : "")}";
    			var infoFile = Path.Combine(localPackagesFolder, packageFolderName, "LINQPadPackageInfo.xml");
    			if (File.Exists(infoFile))
    			{
    				var packageDoc = XDocument.Load(infoFile);
    				refInfo.PackageVersion = packageDoc.Root.Element("MainPackageVersion").Value; 
    			}
    			yield return refInfo;
    		}
    	}
    
    	public class NugetRefInfo
    	{
    		private LINQPad.ObjectModel.NuGetReference _nugetRef;
    
    		public NugetRefInfo(LINQPad.ObjectModel.NuGetReference nugetRef)
    		{
    			_nugetRef = nugetRef;
    		}
    
    		public bool IsPrerelease => _nugetRef.IsPrerelease;
    		public string LockedToVersion => _nugetRef.LockedToVersion;
    		public string PackageID => _nugetRef.PackageID;
    		public string PackageVersion { get; set; }
    	}
    ...which can then be used either for the CurrentQuery or for all queries:
    void Main()
    {
    	//Current query
    	Util.CurrentQuery.NuGetReferenceInfos().Dump($"Current query ({Util.CurrentQuery.Name})");
    	
    	//All queries
    	foreach (var q in Util.GetMyQueries())
    	{
    		var refs = q.NuGetReferenceInfos(); //.Where(qr => qr.IsPrerelease);
    		if (refs?.Count() > 0)
    		{
    			refs?.Dump($"{q.Location}{q.Name}");
    		}
    	}
    }
Sign In or Register to comment.