Skip to content

Instantly share code, notes, and snippets.

@munificent
Created January 30, 2014 00:12
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save munificent/8700021 to your computer and use it in GitHub Desktop.
Save munificent/8700021 to your computer and use it in GitHub Desktop.
A new pub command?

I'm starting to work on a new pub command. I've got two goals for it.

Use case 1: Pre-populating your cache (bug #16265)

The first is that it can be used to install a package into your system cache. For example, maybe you're about to go off the grid and you want to make sure you have a bunch of stuff cached locally before you fall off the Internet. pub get does this implicitly, of course, but you may not have any packages that depend on the stuff you're downloading. You just want to pull it down.

Our specific use case is that we are starting to run tests of packages. Since hitting the network can fail, we'd like to do that separately from running pub get so that we can handle the failure more gracefully.

The idea is you could do:

$ pub ___ some_package -v "<=2.0.0"

Where ___ is the name of this command. That will find the latest version of some_package that matches <=2.0.0 and install it into your cache. You can call this command anywhere, you don't have to be in a package.

Use case 2: Making package binaries available from the command line (bug #7874)

Once that's in place, the next use case for this command is for working with packages that contain command line applications. Once you've used this command to pull down some package, it could then do some unspecified shenanigans to look in that package's bin directory and put the stuff in there on your PATH.

I will not be working on that functionality just yet. Right now, I'm only focused on use case 1, but I want to design the command in anticipation of use case 2. Here's where you come in. I'd like some feedback on what that command should be called.

Reclaiming pub install?

The command to pull down your dependencies used to be pub install before we renamed it to pub get. The old name still works now as an alias for get.

We can't come up with a better name for this "put stuff in my system cache and maybe add binaries to my PATH" command than install. So our proposal is to take that command back and make it not just be a synonym for get anymore. It would look something like:

# Download the latest version of "foo" from pub into my cache.
$ pub install foo

# Download foo 1.0.0 from pub into my cache.
$ pub install foo -v 1.0.0

# Install foo from the Git repo at some/git/path.
$ pub install -s git some/git/path

# Download all versions of foo matching that version constraint.
$ pub install foo -v ">1.0.0 <2.0.0" --all

I'm a little iffy on some of those arguments, but you get the idea. Thoughts?

@dmah42
Copy link

dmah42 commented Jan 30, 2014

How do you feel about overloading 'pub get'?

i.e.

# Download the packages that this package depends on
$ pub get

# Download a specific package
$ pub get foo

# The rest as above.

@fmorgado
Copy link

+1 for the proposal, and 'pub get foo'

@munificent
Copy link
Author

We talked about overloading get, but we felt that was confusing. The two commands do very different stuff. In particular, pub get is only meaningful when inside a package, while pub install (or whatever we call) isn't related to any particular package and can be run from anywhere.

Given that, it seemed best to separate them.

@izaera
Copy link

izaera commented Jan 30, 2014

How about "fetch" or "download"?

My 1.1 cents ;-).

@zoechi
Copy link

zoechi commented Jan 30, 2014

1

pub cache add xxx
pub cache remove xxx
pub cache purge

2

There should be a way to maintain which packages should be downloaded this way.
I wouldn't want to maintain (download updates) manually for those packages.
I would probably create a dummy package with just a pubspec.yaml.

If all packages that should be used as command line applications are dependencies of such a local meta-package
it would be easy to update all at once like for example using apt-get.
pubspec.yaml would contain a list of all packages that I want downloaded and I have a place where I can maintain the versions I want.
A disadvantage is that this way all packages need to fulfill common dependency constraints.

Some ideas:

  • Create a new package type.
  • An option in pubspec.yaml or another name for pubspec.yaml (to make it more obvious) to set the package type.
  • I think this package type needs not to be able to be published (only local)
  • No common version constraints for listed dependencies (if dependency A depends on Dt '=>1.0<2.0' and B depends on Dt '<=1.0' this should work)
  • Create symlinks in the bin directory for the executables provided by the dependencies.
    This way only one path is needed for all dependencies that contain executables.
  • Add an option to the standard pubspec.yaml that allows to add some setup metadata like a list of the executables it provides (to create the symlinks), or an install script (something like configure in linux,
    like what Andrew suggested)
  • pub get/install fetches all defined dependencies
  • pub upgrade updates all defined dependencies
  • maybe a new option may be needed like pub configure xxx to re-execute the configuration script.

@munificent
Copy link
Author

There should be a way to maintain which packages should be downloaded this way.

I don't look at it as saying "these are the packages that I explicitly cache" versus "these are the packages that I implicitly cache by way of pub get". Those two sets overlap. If you were to explicitly install a package and then pub get a package that depended on that, pub get would use the one you previously cached.

I wouldn't want to maintain (download updates) manually for those packages.

It's always been a tenet of pub's design that it doesn't spontaneously upgrade things on you. So, when we support putting package binaries on your PATH, there will be some manual effort required to upgrade that package.

However, that probably won't be as bad as it sounds. Our intent is that the binary on your path should be "context aware". For example, let's say you have a package foo that exposes some foo command. You explicitly install that into your cache and pub does the magic it needs to put that on your PATH.

Pub will pick the most recent stable version of foo at the point in time that you install it. When you run foo outside of a package, that's the version of it that it will use. If you want it to use a later version, you'll need to manually upgrade this "global" foo.

However, if you run foo from within a package that depends on foo, you should get the version of foo that your package depends on. Our goal is to never need to create something like virtualenv or rvm for Dart. Pub should do that isolation for you implicitly. It does that already for dependencies, so it just means we need to preserve that behavior for binaries.

pub cache add xxx
pub cache remove xxx
pub cache purge

Pub already has a cache command with subcommands (the only one is list right now), so that's not a bad idea. remove and purge are tricky because they will break existing symlinks, but add could work.

My main concern with that is that for use case 2 where you want something on your PATH, pub cache add doesn't seem like the right way to express that. Maybe the right answer is to have a separate command for the two use cases.

@seaneagan
Copy link

I like 2 separate commands, pub cache add and pub install SGTM, to avoid having to pass a flag to enable use case 2 which seems more common, and use case 2 also may need extra arguments like only installing a particular binary instead of all of them. There might also be other pub sub-commands which need similar arguments to specify a specific pub package to operate on:

Run a package's tests (no argument => current package):

pub test -s git some/git/path

Generate docs for a package (no argument => current package):

pub doc foo

Add dependency to the local pubspec.yaml, possibly check if dependency is valid first:

pub depend -v <=2.0.0 foo

@munificent
Copy link
Author

OK, let it be known henceforth and forever that the command to install a package into your system cache shall be:

pub cache add <package_name>

@Scorpiion
Copy link

pub cache add <package_name>

Sounds like a great feature, been thinking of writing a separate program just to manually sync the cache outside of pub, but if it get's integrated that's even better!

@kevmoo
Copy link

kevmoo commented Jan 31, 2014

If you go w/ pub install make sure we have a full major release where install throws and points folks to get.

Force an unlearn before you teach something new.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment