ponylang / pony-stable

:horse: A simple dependency manager for the Pony language.
BSD 2-Clause "Simplified" License
134 stars 18 forks source link

Implement Versioning #54

Closed Vorlent closed 6 years ago

Vorlent commented 6 years ago

Right now pony-stable still has no concept of versions.

I'd like pony-stable to follow the model of Rust's Cargo but we can avoid version ranges for now.

A basic package manager needs to do implement these rough functions.

  1. Define the dependencies inside a manifest.

  2. Optional: If version ranges will be supported the package manager has to use constraint solving to generate the current dependency graph and save it in a lockfile. The lockfile has to be commited to the repository to ensure reproducible builds.

  3. Fetch the dependencies and store them in this flat path structure:

    <package-name>/<version>/<package-contents>

    (Let's avoid the recursive mess that NPM used to create before version 3.)

  4. The last step is to give the compiler information about the location of the packages.

pony-stable already does 1., 3., 4. partially but it's still missing features such as version information.

What I'd like to see is the ability to specify the version in the manifest.

Without version ranges there are two primary version types in this scenario: static/pinned versions like 2.5.3 which could be denoted '=2.5.3' (in line with NPM and Cargo) moving versions like latest or master that follow a branch which could be denoted as ':latest' (afaik no package manager uses colons as a prefix)

Side Note: These symbols were chosen to leave room for version ranges if the need arises.

Step 1., 2., 3. can be implemented without modifying ponyc.

Step 4. is problematic when there is more than one version of a single package.

Here is an example dependency graph:

A version 1.0.1
    B version 1.3.5
       C version 2.3.0
    D version 1.0.9
       C version 1.4.0

Right now there can only be one version of C. When B uses "C" the compiler looks for .deps/C rather than .deps/C/2.3.0 and D uses "C" it also chooses .deps/C rather than .deps/C/1.4.0.

Ponyc has to be changed to support some sort of "package redirection" for specific packages.

Alternatively we could also use pony_packages and redirect from pony_packages/C to .deps/C/2.3.0 on the filesystem layer via symlinks.

I'm still not sure how to pass on the redirection information to the compiler.

Here are the two approaches I've figured out so far.

Package specific PONYPATHs via command line parameters. The path of the package is specified and the paths of the dependency packages. The command may become very large and hit limits of the CLI.

ponyc --package-path /path/to/package/D/1.0.9=/path/to/package/C/1.4.0 --package-path /path/to/package/B/1.3.5=/path/to/package/C/2.3.0

The alternative is that pony-stable generates a json file that contains this information and the compiler reads the redirect information from it.

{
    path: "/path/to/project"
    dependencies: {
        "B": {
            path: "/path/to/project/.deps/B/1.3.5",
            dependencies: {
                "C": {
                    path: "/path/to/project/.deps/C/2.3.0",
                    dependencies: {}
                }
            }
        },
        "D": {
            path: "/path/to/project/.deps/D/1.0.9",
            dependencies: {
                "C": {
                    path: "/path/to/project/.deps/C/1.4.0",
                    dependencies: {}
                }
            }
        }
    }
}
SeanTAllen commented 6 years ago

@Vorlent can you clarify "has no concept of versions"?

do you mean, that dependencies always use HEAD? if yes, then that isn't the case. However, there are certainly improvements that can be made. It doesn't for example, do ranges. You can use a specific git tag/commit. For example...

https://github.com/WallarooLabs/wallaroo/blob/master/machida/bundle.json#L8

Vorlent commented 6 years ago

Okay I didn't know about the ability to specify versions inside tags.

Handling the minor and patch versions with tags this way is perfectly okay as long as the library does not have any breaking changes. But when backwards compatiblity is broken you need to be able to use two major versions of the same library in one program. Does pony-stable handle this in any way?

Let's take the pony-inspect library. Suddenly one day version 2.0.0 of pony-inspect is released. How do I use it via pony-stable?

Does pony-stable offer a solution beyond just putting the major version into the package name like this?

use "inspect"
use "inspect2"
SeanTAllen commented 6 years ago

you would change the version in your bundle.json to match the API you are using in your code:

{
  "deps": [
      { "type": "github",
        "repo": "jemc/pony-inspect",
        "tag": "2.0.0"
      }
  ]
}

you would version your bundle.json along with your changes to upgrade to whatever the API changes were for the new version of pony-inspect.

Vorlent commented 6 years ago

Ok. Thank you.