News for hackers. Stuff that matters.
Re:Announcing the new Rust package manager, Cargo by defen on Monday March 17, 2014 @11:44PM (#7419962)
It's been a while (almost 2 years) and I don't use ruby much any more, so my memory is a little hazy and for all I know the issues have been fixed. My main complaints were that too much magic made it difficult to tell what was being loaded from where; and that it was a ton of work to get proper automated deployments set up (with puppet...in a way that didn't make assumptions about the target machine - RVM was also a huge culprit here). Also, at times it was painfully slow. To be fair I'm not super familiar with the internals - it's totally possible that it's all ruby's fault and any ruby package manager would have the same issues. For every day development bundler was mostly great - it was just painful to get proper deployments working.

I much prefer how npm handles things.

Re:Announcing the new Rust package manager, Cargo by steveklabnik on Monday March 17, 2014 @11:56PM (#7420019)
Things have changed quite a bit in the last two years. Especially around speed. So things are a lot better now in Bundler land, and should be better with Cargo, too. Cool.

> I much prefer how npm handles things.

Can you elaborate on how npm handles things in a better way?

Re:Announcing the new Rust package manager, Cargo by TheHydroImpulse on Tuesday March 18, 2014 @12:08AM (#7420089)
For one, I love local by default. Having a package manager that deals with a global context makes things considerably more complex. Having everything local allows you to isolate one crate's (if we're speaking in Rust terms) dependencies to another crates' dependencies.

NPM also has the ability to have isolated dependencies from each other dependency. For example, module A can pin module B to version 2, whereas module C can pin module B to version 3. So you have independent copies.

Now, that worked for a dynamic language where you don't have to deal with static/dynamic linking. Would it be appropriate to statically link two modules that are the same, but at different versions? Maybe not. That would lead to massive binary sizes.

Re:Announcing the new Rust package manager, Cargo by steveklabnik on Tuesday March 18, 2014 @12:19AM (#7420138)
Thank you.

> I love local by default.

Roger. It's hard to articulate my own thoughts about this, but I feel like Bundler enables the best of both worlds here.[1] That said, it's obviously a preference.

> NPM also has the ability to have isolated dependencies from each other dependency.

Ahh yes, I've heard about this. In Ruby, it's not really feasible due to the language, and I'm a bit skeptical that it doesn't lead to super extra complexity, but then again, I haven't used it myself...

Totally agree regarding static/dynamic linking. Though isn't it the same thing with NPM: you still have two copies of the library.

1: http://words.steveklabnik.com/how-to-not-rely-on-rubygemsorg...

Re:Announcing the new Rust package manager, Cargo by jdlshore on Tuesday March 18, 2014 @01:35AM (#7420371)
> I'm a bit skeptical that [isolated dependencies] doesn't lead to super extra complexity...

It's braindead simple. It's an emergent property of the way node loads modules, which is also pretty darn simple.

When you give Node a package to require, if it doesn't refer to a relative or absolute path, it walks up the directory structure looking for `node_modules`. When it finds one, it looks inside for the module you asked for. If it doesn't find it, it keeps walking up the directory tree.

So you can have multiple module repositories in a directory tree. A given file will always find the one that's "closest."

Npm takes advantage of this by installing every module's dependencies in a `node_modules` directory in the root directory of that module. Subdependencies' dependencies go in their node_modules directory. Voila! Isolated dependencies, braindead simple, albeit with a crazy deep directory structure. (node_modules/foo/node_modules/bar/node_modules/baz...)

Node/npm has the best dependency handling I've yet seen, and I think it's because it doesn't try to outsmart me or go for anachronistic disk space optimizations.

Re:Announcing the new Rust package manager, Cargo by shadowmint on Tuesday March 18, 2014 @06:32AM (#7421132)
To be fair though, this works because loading a symbol foo in an isolated scope in javascript is a safe operation.

If you were trying to namespace each of those symbols as you went because of a global symbol table (>_> ... c), then this would be a much more complex task.

It's important to realize that rust libraries are c libraries, complete with symbol information; Rust does mangle symbol names per crate by default, but I'm not 100% sure would stop you from having some issues where the public symbols in a crate caused global symbol table conflicts.

Don't know though, just speculating.

Re:Announcing the new Rust package manager, Cargo by mercurial on Tuesday March 18, 2014 @02:23AM (#7420461)
I'm not sure what's anachronistic about efficient use of disk space, but in any case that's nothing that can't be solved via hardlink deduplication.
Re:Announcing the new Rust package manager, Cargo by jdlshore on Tuesday March 18, 2014 @02:50AM (#7420526)
> I'm not sure what's anachronistic about efficient use of disk space

Consider this: A frequently used module in one of my trees is "glob". It's repeated four times in two different versions. It takes 207K each time, including subdependencies. The wasted space is 414K... more than a whole floppy! ;-)

Or to put it another way, I've wasted 0.00017% of my rather small 250GB SSD.

Optimizing that is anachronistic.

> that's nothing that can't be solved via hardlink deduplication

Yep, and `npm dedupe` [1] does something similar. This does have the potential to become massively complex, though. You have to re-dupe when one dependency upgrades but another doesn't, and you also need to deal with the fact that two modules' dependencies may be sharing memory space that a module author was expecting to have to herself. (Modules are cached, so changes to "module global" variables are shared, but modules loaded from different locations are cached independently.)

[1] https://www.npmjs.org/doc/cli/npm-dedupe.html

Re:Announcing the new Rust package manager, Cargo by mercurial on Tuesday March 18, 2014 @03:28AM (#7420612)
> Optimizing that is anachronistic.

On the other hand, my Java .m2 directory counts 2469 jar files for a total of 2.4G. My considerably smaller .cabal is still 253MB. I won't complain if hardlinking prevents package repo sizes from going out of hands.

> Yep, and `npm dedupe` [1] does something similar.

Not quite. From what I understand, it attempts to manipulate the package hierarchy. On the other hand, hard link deduplication doesn't need to do any such thing, it simply needs to hardlink files with the same checksum. No intelligence required. Some time ago, I used rsync to do this kind of thing when deploying large binary dependencies, and it is very practical (IMHO, hard links get too little love).

Re:Announcing the new Rust package manager, Cargo by jdlshore on Tuesday March 18, 2014 @02:46PM (#7424057)
Fair enough.
Re:Announcing the new Rust package manager, Cargo by riffraff on Tuesday March 18, 2014 @06:22AM (#7421111)
when everything has it's own version of a dependency don't you risk to get into a condition where you get e.g. incompatible objects Lib-v1.Foo and Lib-v2.Foo ?
Re:Announcing the new Rust package manager, Cargo by rat87 on Tuesday March 18, 2014 @01:48PM (#7423605)
> NPM also has the ability to have isolated dependencies from each other dependency. For example, module A can pin module B to version 2, whereas module C can pin module B to version 3. So you have independent copies.

That seems like a bad idea even in a dynamic language, perhaps especially in a dynamic language. What if you return a type from module A that is defined in module BV2 to module C suddenly it can't find the method(or the method does something different then expected). At least in a static language you could prevent this to some extent. It seems like it would be better to have version ranges and fetch the newest released version or fail if no version is acceptable with interactive/cmdline overrides.

Re:Announcing the new Rust package manager, Cargo by defen on Tuesday March 18, 2014 @12:47AM (#7420235)
Fundamentally, I think it boils down to the fact that node's module loader is dumb, and npm doesn't try to be a smart module loader on top of that - it just installs dependencies to where node's dumb loader will be able to find them. And, because of CommonJS, it's easy to tell it exactly where it's allowed to look.

One way this manifests itself in a nice way is with local installs - let's say you have a package that depends on modules A, B, and C. Each of those modules has its own dependencies. The default behavior when you install the package is that A, B, and C have copies of all their dependencies (so if all 3 depend on D, you get 3 copies of D), and so forth all the way down. This does waste disk space, but for the most part node modules are small and disk space is cheap. The advantage is that you don't have to worry about conflicting dependencies, or subtle changes breaking things in hard-to-find ways.

Like a sibling commenter said, I have no idea if this model will transfer well to Rust.

Re:Announcing the new Rust package manager, Cargo by TheHydroImpulse on Monday March 17, 2014 @11:57PM (#7420026)
That's what made it intolerable when I started getting into Ruby years ago. Perhaps this can also be attributed to Ruby being slow, but it was (and still is) too slow to install anything or run commands. This isn't bundler's fault, though, as gem and many ruby CLIs also run super slowly.