Skip to content

Making GX pleasant to use #179

@Stebalien

Description

@Stebalien

I'd like to propose a way forward to make gx nicer to use. Basically, for me at least, the biggest time-sink is the lack of a dependency resolution system. Step 1 aims at working around the limitations in gx-workspace and step 2 aims to integrate better with existing package managers.

Motivation

  1. Every dependency must update shared transitive dependencies in lock-step.
  2. Updating a dependency deep in the dependency tree is really painful.
  3. Updating dependencies often means firing off a bunch of PRs to get updated package.json files merged.
  4. Dependencies not stored in gx are painful to use.
  5. Using gx packages with other package managers can be painful.

Ignore the below proposal and take a look at #179 (comment)

Proposal

Step 1

This step aims to solve issues 1-4.

In this step, we'd add a feature to gx that's basically like gx-workspace but works on published packages instead of repos. That is, you'd run gx update --everywhere SomeHash to update the hash everywhere in the dependency tree. This tool would then:

  1. Modify the package.json files in the published package.
  2. Re-publish and get a new hash.

(@whyrusleeping has proposed this in the past)

One big downside is that we'd get a new package hash for every modified dependency. IPFS will deduplicate the files but this could still cause problems (users need to be very careful to pin everything).

The other downside is that we have no way to check these updates (other than to run the tests, which we should probably do). That is, packages can't specify semver constraints (yes, these don't guarantee anything but they can help).

Step 2

This step aims to solve issue 5 and the two issues introduced in step 1.

In this step, we'd switch to a package.json/package-lock.json setup following NPM's file formats as closely as possible. Ideally, we'd be able to make gx work with NPM packages without much trouble.

That is:

  1. Add a generated package-lock.json file. We can use this file to lock in packages to specific IPFS hashes (and specific git commits for compatibility). This file MUST be checked into version control. Note: This fill will list every hash of every transitive dependency. This means we can update a transitive dependency without modifying the dependency.
  2. Use the NPM dependency list format in package.json complete with semver, repos, etc.

This gives us:

  1. Semver. That is, we can check semver versions when updating transitive dependencies and solving transitive dependency conflicts.
  2. Fixes the downside from step 1. That is, we don't have to modify dependencies to update transitive dependencies.
  3. Potentially allows us to integrate with tools like NPM. Ideally, we'd be able to use gx with javascript for our builds while allowing everyone else to continue using NPM without any additional work (they'd just wouldn't get the same guarantees).
  4. Makes it easier to integrate with tools like go's dep. We should be able to autogenerate Godep.toml/Godep.lock files from our package.json/package-lock.json files.

However, this also has a drawback: We wouldn't be able to have a global $GOPATH/src/gx tree anymore because we'd need to rewrite each package's dependencies differently. This wasn't a problem in step 1 because we created entirely new packages when updating transitive dependencies.

On the other hand, I'm not sure if this drawback is that bad. gx-go rw is now fast enough that we can rewrite dependencies on the fly (on build) as long as we have a central place to cache unrewritten gx packages. That is:

  1. Hardlink all files, gx and package (cp -rl), into a temporary GOPATH. This is a really fast operation.
  2. Run gx-go rw (this doesn't modify files in-place so the hardlinking won't be a problem).
  3. Build.

We can even do this on Windows (Windows has hardlink support).

Note: we wouldn't have to rewrite all of our packages all at once, we'd just have to make sure to do so from the top down.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions