IsLatestVersion is always true for ZipPackage object

Nov 17, 2011 at 3:44 PM
Edited Nov 17, 2011 at 3:50 PM

I've noticed in the Nuget source that for a ZipPackage object that the return value for IsLatestVersion is always true which is kind of weird so figured I'd just post the info I have about it.

Say I create 2 nupkg packages with the same name but different versions and put them in my files system for a local package repository and I want to show in a UI which one of the 2 is the latest version, this will not be possible by using the packages IsLatest property. I'm sure there's some reasons for this to be hard coded but in my case i need to know this information, i guess the reason would be because you'd have to look up all packages to determine this information even if you just wanted to query for one?

In my case howevre, my UI lists all of my packages in my local repository so I already have all of the info from all packages. I've then just created a custom PackageModel which contains a boolean called IsLatestVersion and have a helper method to check against all packages as to whether the current one I'm iterating through is the latest. Perhaps there's a better approach to this but this seems to work. 

var packages = PackageContext.LocalPackageManager.SourceRepository
    .GetPackages()
    .ToArray();
 
Func<IPackagebool> checkLatest = (p) =>
    {
        var packagesForId = packages.Where(x => x.Id == p.Id).ToArray();
        //need to check major/minor version first, then need to go by DatePublished.
        var biggestMajor = packagesForId.Max(x => x.Version.Major);
        if (p.Version.Major < biggestMajor) return false;
        //this means the major versions are the same, so now check minor
        var biggestMinor = packagesForId
            .Where(x => x.Version.Major == biggestMajor)
            .Max(x => x.Version.Minor);
        if (p.Version.Minor < biggestMinor) return false;
        //this means the minor version are the same, so now check published date
        var published = packagesForId
            .Where(x => x.Version.Major == biggestMajor
                && x.Version.Minor == biggestMinor
                && x.Published.HasValue).ToArray();
        if (!p.Published.HasValue && published.Count(x => x.Published.HasValue) > 0)
            return false;
        var maxPublish = published.Max(x => x.Published.Value);
        if (p.Published.Value < maxPublish) return false;
                    
        return true;
    };
 
var models =  packages.Select(x => new PackageModel
    {
        IsLatestVersion = checkLatest(x),
        IsVersionInstalled = PackageContext.LocalPackageManager.LocalRepository.FindPackage(x.Id, x.Version) != null,
        Metadata = x,
        IsPackageInstalled = x.IsInstalled(PackageContext.LocalPackageManager.LocalRepository)
    }).ToArray();
 
return models;

Nov 17, 2011 at 3:52 PM

Also, if anyone has a nicer way to see if a Version is later than another, I've probably overlooked something but would assume its in .Net or Nuget natively ?

Developer
Nov 17, 2011 at 5:52 PM

The reason we don't set the IsLatest property for LocalPackageRepository \ ZipPackage is because for a lot of operations we try to optimize by looking for specific packages (by guessing the package path) and do not crack open any of the other packages on disk. Setting IsLatest would require us to look up every package on every GetPackages which would kill perf.

Version and correspondingly the newly added SemanticVersion type have overloaded <, > operators and implement IComparable. So you should be fine doing something like .

        var packagesForId = packages.Where(x => x.Id == p.Id).ToArray();
        //need to check major/minor version first, then need to go by DatePublished.
        var biggestMajor = packagesForId.Max(x => x.Version);

Not sure why you're using the published date to check this though - there's really nothing stopping you from uploading an older version of a package after you're published a newer version, so using that as a basis would be incorrect.

Nov 17, 2011 at 10:49 PM

Cool, thx for the response. I figured that is the case but seemed a little confusing, i wonder if there's some way to make this more clear to developers that certain package formats are unable to provider certain information even though they have properties for it. Maybe a bool flag indicating what the IPackage supports like 'CanCheckIsLatestVersion' (kind of like how the Stream object has these types of flags) .

I guess the reason i was checking published date was because i don't know another way to check if a version is later than another if their major and minor versions are the same since i know a lot of assemblies have the build and revision numbers auto generated for them, which i assume would get used for their NuGet package version if they have automoated that process.

Developer
Nov 28, 2011 at 5:26 PM

The assumption is that any property hanging off of IServerPackageMetadata is only available when pulling from the server. I guess we could add the property though to make it more explicit. Could you file a bug (maybe just copy to work item) or send in a pull request for this change?