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

Support for mutliple mayor versions of the same package #593

Closed
yorickpeterse opened this issue Jul 12, 2023 · 2 comments
Closed

Support for mutliple mayor versions of the same package #593

yorickpeterse opened this issue Jul 12, 2023 · 2 comments
Assignees
Labels
compiler Changes related to the compiler feature New things to add to Inko, such as a new standard library module
Milestone

Comments

@yorickpeterse
Copy link
Collaborator

Description

Based on the discussion found here:

Inko's package manager doesn't allow for multiple mayor versions of the same package. This is annoying, and can make upgrading packages a challenge. Go's approach to this problem (given it uses the same version algorithm) is to treat different mayor versions as different packages, thus "http" 1.2.3 and "http" 2.0.0 are treated as being entirely different.

Go does make the mistake of special-casing v0/v1 so you don't need to include the version in the import, but I think that's a mistake as it's not consistent and it's ambiguous. For Inko, we'd make the version explicit in the import, thus you'd need to write this:

import yaml::v0::Generator
import http::v1::Client
import json::v2::Parser

Including the versions in the import takes some getting used to, but it beats having to switch to a massively complex SAT solving scheme and compiling dependencies on a per package basis, and dealing with all the troubles this will probably bring.

Implementation wise this would be pretty simple:

  1. We allow different mayor versions of the same package. The version selection algorithm uses hashing internally, using the package URI as the key. This needs to be changed to be (URI, mayor version) (or something along those lines)
  2. When moving packages into ./dep/src, instead of placing package "foo" in ./dep/src/foo, we place it in ./dep/src/vMAYOR/foo, where MAYOR is the mayor version number
  3. We update the documentation to mention this

Related work

No response

@yorickpeterse yorickpeterse added feature New things to add to Inko, such as a new standard library module compiler Changes related to the compiler labels Jul 12, 2023
@yorickpeterse
Copy link
Collaborator Author

yorickpeterse commented Jul 12, 2023

When moving packages into ./dep/src, instead of placing package "foo" in ./dep/src/foo, we place it in ./dep/src/vMAYOR/foo, where MAYOR is the mayor version number

On second though, this isn't quite what I want, because it means you have to write import foo::v1::foo. We could rename src/foo.inko to v1.inko, then you can do import foo::v1, but that would only work if the name of the package matches the name of the module, which isn't a requirement.

Then there's another issue: a module may import other modules from the same package. Should those imports also specify the mayor version number? If so, that would complicate local development as you'll end up with e.g. import my_module::v2::bla but v2 doesn't exist (e.g. when running unit tests), so the import fails.

@yorickpeterse yorickpeterse changed the title When installing a package, scope it to its mayor version, and allow different mayor versions to be installed Support for mutliple mayor versions of the same package Jul 12, 2023
@yorickpeterse
Copy link
Collaborator Author

Thinking out loud here:

I really don't want version numbers of full URIs in imports (e.g. import 'yorickpeterse/http/cookie' ... or something like that). This is repetitive, makes renaming a PITA, and makes bumping mayor versions annoying (both as a consumer and producer of the library).

What we could do is introduce a canonical alias/name for packages in inko.pkg, which defaults to the last component in the package URI (so for yorickpeterse/http that becomes http). So inko.pkg ends up looking like this:

require github.com/yorickpeterse/http http 1.0.1 ece1027ada626bddd1efc74ba88a87dbdc19522c

The syntax would be:

require URI LOCAL-NAME VERSION HASH

Within inko.pkg you still can't specify multiple mayor versions of the same package URI (even when using different local names), but sub dependencies can specify a different mayor version.

The structure in ./dep would be as follows:

./dep/github.com/yorickpeterse/http/v1/inko.pkg
./dep/github.com/yorickpeterse/http/v1/http.inko
./dep/github.com/yorickpeterse/http/v1/http/cookie.inko
...

When processing the import http::cookie::Cookie, we do the following:

  1. We take the file path of the module containing this import, and chop off everything after src/. So if the import occurs in bla/src/foo/bar/baz.inko, we end up with bla/src.
  2. We attempt to import the file relative to this path, so bla/src/http/cookie.inko. If this succeeds, we're done. This ensures local imports are always prioritised over imports of third-party packages.
  3. We take bla/src and get its parent directory, leaving us with bla. We then parse and cache bla/inko.pkg (or we just parse all of them ahead of time).
  4. We take the root component of the path of the module we're importing, which is http in this case.
  5. We look up the corresponding entry in the inko.pkg parsed in step 3, using the local name as the key. If we don't find anything, we produce a compile-time error. This prevents importing of transient dependencies.
  6. If we find an entry, we take the package URI and mayor version and turn that into a path relative to dep, so we end up with ./dep/github.com/yorickpeterse/http/v1
  7. We attempt the import relative to this path. If this fails, we produce a compile-time error

The local name is explicit so you can deal with the rare scenario of two different packages having the same last component, by just giving them a different local name.

This setup should allow us to keep the current import setup, while supporting multiple mayor versions, and without the current problem of different packages introducing conflicting module names. It does complicate processing imports a bit, and parsing of inko.pkg files needs to be moved from the CLI into the compiler (but still be available to the compiler).

With that said, I've probably overlooked something, so this will need some time to "simmer".

@yorickpeterse yorickpeterse self-assigned this Jul 19, 2023
@yorickpeterse yorickpeterse added this to the 0.13.0 milestone Jul 19, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler Changes related to the compiler feature New things to add to Inko, such as a new standard library module
Projects
None yet
Development

No branches or pull requests

1 participant