Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FR (Versioning): Improve NuGet Version Range Support #50

Open
anonhostpi opened this issue Jan 18, 2024 · 11 comments
Open

FR (Versioning): Improve NuGet Version Range Support #50

anonhostpi opened this issue Jan 18, 2024 · 11 comments
Assignees
Labels
enhancement New feature or request

Comments

@anonhostpi
Copy link
Contributor

anonhostpi commented Jan 18, 2024

Should fix the following comment from #49:
- #49 (comment)

+1, sharing the temp path causes errors if two packages contain the same file eg large depencency trees like Azure.Monitor.OpenTelemetry.Exporter

Part of the issue is that Azure.Monitor.OpenTelemetry.Explorer is likely using an older version, and that the Bootstrapper is detecting an unbounded version range (which is currently not supported).

However, a bit of work has been already done to improve Import-Package's versioning control when the -CachePath parameter was introduced, so logic to compare semantic versions may already be available.

@anonhostpi anonhostpi added the enhancement New feature or request label Jan 18, 2024
@anonhostpi anonhostpi self-assigned this Jan 18, 2024
@anonhostpi
Copy link
Contributor Author

Improving the NuGet Version Range handling should also help with 2 other problems:

  1. What to do when 2 dependencies in the dependency tree require 2 different ranges of the same package
  2. Should help improve the $loaded logic.

@anonhostpi
Copy link
Contributor Author

anonhostpi commented Jan 19, 2024

To make this work this would require a change to all of the versioning and version control logic.

Thankfully, we could likely get away with using $bootstrapper.GetAllVersions() to help with most of it.

Figuring out which packages are in range she probably be done by Resolve-CachedPackage.

However, something clever will have to be done about determining the range overlap.

  • This may warrant an entire code refactor

@anonhostpi
Copy link
Contributor Author

I think a starting point would be to add a field to PackageData that caches a call to GetAllVersions().

In theory, this would do 2 things:

  • Would optimize and limit calls to the NuGet API
  • Could possibly allow range and version selection to be moved outside of Build-PackageData

This could also allow for a lot more advanced version control logic, since PackageData is currently limited to GetStable() and GetPrerelease()

@anonhostpi
Copy link
Contributor Author

This would likely warrant recursion when selecting dependencies for the best range of a package.

To optimize looping, I think the best option is to only recurse when the upper bounds of a range has changed.

@anonhostpi
Copy link
Contributor Author

The upper and lower bounds should include 3 versions:

  • the boundary itself
  • the stable version in range closest to the boundary
  • the prerelease version in range closest to the boundary
    • calculating this for the lower boundary will be interesting, because typically the stable version would be closest to the lower bound
    • an interesting edge case would be how to handle boundaries that are prereleases.

@anonhostpi
Copy link
Contributor Author

Another problem that would warrant a complete refactor is that currently due to Import-Package's simplistic version control, Import-Package is able to load dependencies at the same time that it builds the dependency tree.

While I might be able to keep this design in mind:

To optimize looping, I think the best option is to only recurse when the upper bounds of a range has changed.

I think it might be best to separate loading and tree parsing into 2 separate steps. This would slow Import-Package down, but would allow me to add more features down the road.

@anonhostpi
Copy link
Contributor Author

anonhostpi commented Jan 19, 2024

An optimization that could help with dependency loading is using the v3-flatcontainer API to download just the nuspec, instead of the entire .nupkg when parsing the dependency tree.

EDIT: PartialZip is available in C# and could be transpiled to PowerShell (or installed during the bootstrapper process)

@anonhostpi
Copy link
Contributor Author

An optimization that could help with dependency loading is using the v3-flatcontainer API to download just the nuspec, instead of the entire .nupkg when parsing the dependency tree.

Example implementation:

# NuGet Package ID and Version
$packageId = "YOUR_PACKAGE_ID"
$packageVersion = "YOUR_PACKAGE_VERSION"

# NuGet API URL
$url = "https://api.nuget.org/v3-flatcontainer/$packageId/$packageVersion/$packageId.nuspec"

# Fetch and parse the .nuspec XML data
try {
    $response = Invoke-WebRequest -Uri $url
    $nuspecXml = [xml]$response.Content  # Parses the content as XML

    # The XML data is now stored in the variable $nuspecXml
    Write-Host "Successfully fetched and parsed .nuspec data for package $packageId version $packageVersion"
    # Display the XML content
    $nuspecXml.OuterXml
} catch {
    Write-Host "Error fetching or parsing .nuspec data: $_"
}

# You can now use the variable $nuspecXml to work with the XML data

@anonhostpi
Copy link
Contributor Author

anonhostpi commented Jan 19, 2024

Adding such support would also likely warrant refactoring any filesystem modifications done by Resolve-CachedPackages, as the current design would cause a performance hit any time the ranges are updated, if this change is implemented.

@anonhostpi
Copy link
Contributor Author

EDIT: PartialZip is available in C# and could be transpiled to PowerShell (or installed during the bootstrapper process)

It doesn't look like NuGet supports byte ranges. It also looks like they don't have an API for exposing the content of the .nupkgs:

@anonhostpi
Copy link
Contributor Author

Feature implementation started. See: pwsh-cs-tools/Import-Package@28550db

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant