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

please remove `node` symlink from iojs installer #796

Closed
sintaxi opened this Issue Feb 11, 2015 · 60 comments

Comments

Projects
None yet
@sintaxi

sintaxi commented Feb 11, 2015

Is there a good reason the iojs installer creates a node symlink? Its seems quite invasive to me and not in the spirit of being a good open source citizen so I'm hoping there is a good reason for it to be there. If not, please remove it.

Apart from it being inappropriate its also inconvenient as I'm sure many people want to dabble with iojs while maintaining their production NodeJS systems. This makes it more challenging and will create unexpected behaviour for those who do not read the installer process.

banners_and_alerts_and_install_io_js_and_downloads

@Florian-R

This comment has been minimized.

Show comment
Hide comment
@Florian-R

Florian-R Feb 11, 2015

#389 #631 #776 and probably a shitload of others.

Florian-R commented Feb 11, 2015

#389 #631 #776 and probably a shitload of others.

@targos

This comment has been minimized.

Show comment
Hide comment
@targos

targos Feb 11, 2015

Member

If you need Node.js and io.js to coexist on your system, you can use nvm

Member

targos commented Feb 11, 2015

If you need Node.js and io.js to coexist on your system, you can use nvm

@sintaxi

This comment has been minimized.

Show comment
Hide comment
@sintaxi

sintaxi Feb 11, 2015

Is it really to much to ask for an explanation for this? What purpose does this symlink serve?

I would like to switch https://github.com/sintaxi/harp to iojs but this is preventing me from doing that as I'm not comfortable forcing the harp community to abandon NodeJS. This behaviour hostile and unprofessional and the lack of explanation leads me to believe this "feature" is self-serving and not operating in good faith. Please don't dismiss this without an explanation as to why iojs feels compelled to override competing binaries on my machine.

sintaxi commented Feb 11, 2015

Is it really to much to ask for an explanation for this? What purpose does this symlink serve?

I would like to switch https://github.com/sintaxi/harp to iojs but this is preventing me from doing that as I'm not comfortable forcing the harp community to abandon NodeJS. This behaviour hostile and unprofessional and the lack of explanation leads me to believe this "feature" is self-serving and not operating in good faith. Please don't dismiss this without an explanation as to why iojs feels compelled to override competing binaries on my machine.

@tonylukasavage

This comment has been minimized.

Show comment
Hide comment
@tonylukasavage

tonylukasavage Feb 11, 2015

This does seem like a good case for a simple confirmation in the installer as to whether or not you want the symlink

tonylukasavage commented Feb 11, 2015

This does seem like a good case for a simple confirmation in the installer as to whether or not you want the symlink

@brianloveswords

This comment has been minimized.

Show comment
Hide comment
@brianloveswords

brianloveswords Feb 11, 2015

@sintaxi I think the explanation is here: #249 (comment) (and there's an even longer discussion at #631)

brianloveswords commented Feb 11, 2015

@sintaxi I think the explanation is here: #249 (comment) (and there's an even longer discussion at #631)

@targos

This comment has been minimized.

Show comment
Hide comment
@targos

targos Feb 11, 2015

Member

It is like MariaDB vs MySQL : io.js is a replacement for Node. Too many modules/scripts rely on the node executable.

Member

targos commented Feb 11, 2015

It is like MariaDB vs MySQL : io.js is a replacement for Node. Too many modules/scripts rely on the node executable.

@vkurchatkin

This comment has been minimized.

Show comment
Hide comment
@vkurchatkin

vkurchatkin Feb 11, 2015

Member

This was closed primarily because it is a duplicate. You can find extensive explanation in linked issues

Member

vkurchatkin commented Feb 11, 2015

This was closed primarily because it is a duplicate. You can find extensive explanation in linked issues

@vkurchatkin

This comment has been minimized.

Show comment
Hide comment
@vkurchatkin

vkurchatkin Feb 11, 2015

Member

@sintaxi your harp project relies on this as well as many other packages: https://github.com/sintaxi/harp/blob/master/bin/harp#L1

Member

vkurchatkin commented Feb 11, 2015

@sintaxi your harp project relies on this as well as many other packages: https://github.com/sintaxi/harp/blob/master/bin/harp#L1

@sintaxi

This comment has been minimized.

Show comment
Hide comment
@sintaxi

sintaxi Feb 11, 2015

Harp is asking for NodeJS because that is what it depends on.

I would like Harp to depend on iojs instead but I'm not going to force the entire Harp community to abandon NodeJS just because Harp wants to use iojs. I can't in good conscience force this decision on them because its not my place to make that decision for them.

sintaxi commented Feb 11, 2015

Harp is asking for NodeJS because that is what it depends on.

I would like Harp to depend on iojs instead but I'm not going to force the entire Harp community to abandon NodeJS just because Harp wants to use iojs. I can't in good conscience force this decision on them because its not my place to make that decision for them.

@Fishrock123

This comment has been minimized.

Show comment
Hide comment
@Fishrock123

Fishrock123 Feb 11, 2015

Member

@sintaxi io.js symlinks to node so that it is usable as node, and so that your files with #!/usr/bin/env node will not break.

Member

Fishrock123 commented Feb 11, 2015

@sintaxi io.js symlinks to node so that it is usable as node, and so that your files with #!/usr/bin/env node will not break.

@sintaxi

This comment has been minimized.

Show comment
Hide comment
@sintaxi

sintaxi Feb 11, 2015

@vkurchatkin btw - thanks for the explanation. If you prefer to close this ticket I can move discussion to issue #249

sintaxi commented Feb 11, 2015

@vkurchatkin btw - thanks for the explanation. If you prefer to close this ticket I can move discussion to issue #249

@sintaxi

This comment has been minimized.

Show comment
Hide comment
@sintaxi

sintaxi Feb 11, 2015

@Fishrock123 I understand the explanation it just isn't based on facts. If the user has NodeJS installed which is what the script is asking for, it will run just fine. In reality the scripts are much more likely to break if some systems run node as nodejs and others run iojs.

sintaxi commented Feb 11, 2015

@Fishrock123 I understand the explanation it just isn't based on facts. If the user has NodeJS installed which is what the script is asking for, it will run just fine. In reality the scripts are much more likely to break if some systems run node as nodejs and others run iojs.

@indexzero

This comment has been minimized.

Show comment
Hide comment
@indexzero

indexzero Feb 11, 2015

@Fishrock123 what about a bin shim that would run iojs or node depending on external config? Or maybe at least making this an option in the installer?

indexzero commented Feb 11, 2015

@Fishrock123 what about a bin shim that would run iojs or node depending on external config? Or maybe at least making this an option in the installer?

@Fishrock123

This comment has been minimized.

Show comment
Hide comment
@Fishrock123

Fishrock123 Feb 11, 2015

Member

@sintaxi considering the aim is to keep backwards compatibility, how is this more of an issue than upgrading to 0.12?

@indexzero not sure, I'm probably not the best person to cc for that. :)

Member

Fishrock123 commented Feb 11, 2015

@sintaxi considering the aim is to keep backwards compatibility, how is this more of an issue than upgrading to 0.12?

@indexzero not sure, I'm probably not the best person to cc for that. :)

@kenperkins

This comment has been minimized.

Show comment
Hide comment
@kenperkins

kenperkins Feb 11, 2015

Contributor

There's also a significant amount of commentary in #43

Contributor

kenperkins commented Feb 11, 2015

There's also a significant amount of commentary in #43

@Qard

This comment has been minimized.

Show comment
Hide comment
@Qard

Qard Feb 11, 2015

Member

If you want to know why the symlink is required, try removing it and seeing just how broken everything in the ecosystem gets. So many things assume the binary name is "node" that, if we want to maintain compatibility, we have to use the same name or the vast majority of tools are just plain broken.

There may be some clever way to make a wrapper script that can figure out what to run from some environment variable hack, but I don't think it'd be much less intrusive than just using a version manager, like nvm.

Really, I think the solution is just to merge back with node.js at some point and forget all this symlink nonsense. The new foundation is a good step in that direction, but it needs further evaluation to see if merging aligns with the goals of io.js.

Member

Qard commented Feb 11, 2015

If you want to know why the symlink is required, try removing it and seeing just how broken everything in the ecosystem gets. So many things assume the binary name is "node" that, if we want to maintain compatibility, we have to use the same name or the vast majority of tools are just plain broken.

There may be some clever way to make a wrapper script that can figure out what to run from some environment variable hack, but I don't think it'd be much less intrusive than just using a version manager, like nvm.

Really, I think the solution is just to merge back with node.js at some point and forget all this symlink nonsense. The new foundation is a good step in that direction, but it needs further evaluation to see if merging aligns with the goals of io.js.

@sintaxi

This comment has been minimized.

Show comment
Hide comment
@sintaxi

sintaxi Feb 12, 2015

@Fishrock123 its in issue because the script is asking to use the node runtime not iojs. But users cant even have both installed along side each other. This is makes scripts far more likely to break and much more difficult to debug when users run into issues. Q: "Which version of node are you running? can you run node --version for me?" A: "it says I'm running node version 1.0.0", Q: "cool, is that node node or iojs node? ?" A: "Wut?".

sintaxi commented Feb 12, 2015

@Fishrock123 its in issue because the script is asking to use the node runtime not iojs. But users cant even have both installed along side each other. This is makes scripts far more likely to break and much more difficult to debug when users run into issues. Q: "Which version of node are you running? can you run node --version for me?" A: "it says I'm running node version 1.0.0", Q: "cool, is that node node or iojs node? ?" A: "Wut?".

@indexzero

This comment has been minimized.

Show comment
Hide comment
@indexzero

indexzero Feb 12, 2015

@Qard as the author of one of the most globally installed modules (forever) I can say with certainty that the symlink is necessary. I (and authors like me) do not want to change how our main executables are structured

indexzero commented Feb 12, 2015

@Qard as the author of one of the most globally installed modules (forever) I can say with certainty that the symlink is necessary. I (and authors like me) do not want to change how our main executables are structured

@sintaxi

This comment has been minimized.

Show comment
Hide comment
@sintaxi

sintaxi Feb 12, 2015

If you want to know why the symlink is required, try removing it and seeing just how broken everything in the ecosystem gets. So many things assume the binary name is "node" that, if we want to maintain compatibility, we have to use the same name or the vast majority of tools are just plain broken.

Removing the symlink only breaks my node scripts because iojs chose to clobber my node binary on install. Currently the best way to avoid these problems is to not install iojs in the first place.

If this is a package ecosystem issue than lets raise awareness and get people to update their modules to something that is sustainable. People will update because those that don't will get left behind.

sintaxi commented Feb 12, 2015

If you want to know why the symlink is required, try removing it and seeing just how broken everything in the ecosystem gets. So many things assume the binary name is "node" that, if we want to maintain compatibility, we have to use the same name or the vast majority of tools are just plain broken.

Removing the symlink only breaks my node scripts because iojs chose to clobber my node binary on install. Currently the best way to avoid these problems is to not install iojs in the first place.

If this is a package ecosystem issue than lets raise awareness and get people to update their modules to something that is sustainable. People will update because those that don't will get left behind.

@vkurchatkin

This comment has been minimized.

Show comment
Hide comment
@vkurchatkin

vkurchatkin Feb 12, 2015

Member

io.js is a version of node. saying that it clobbers node binary is the same as saying that node 0.12 clobbers node 0.10 binary. If you need multiple versions on the same machine you can use nvm

Member

vkurchatkin commented Feb 12, 2015

io.js is a version of node. saying that it clobbers node binary is the same as saying that node 0.12 clobbers node 0.10 binary. If you need multiple versions on the same machine you can use nvm

@sintaxi

This comment has been minimized.

Show comment
Hide comment
@sintaxi

sintaxi Feb 12, 2015

@vkurchatkin This has nothing to do with MY needs.

If I tell users to install iojs because my modules depend on it than I am forcing NodeJS OFF other peoples machines which does not sit well with me. If you are saying you understand and that is something iojs is cool with than I suppose this discussion has come to an end but in my view that makes iojs a virus and not a suitable dependency for my project.

I would be profoundly disappointed if this is the case as I feel this project shows a lot of promise.

sintaxi commented Feb 12, 2015

@vkurchatkin This has nothing to do with MY needs.

If I tell users to install iojs because my modules depend on it than I am forcing NodeJS OFF other peoples machines which does not sit well with me. If you are saying you understand and that is something iojs is cool with than I suppose this discussion has come to an end but in my view that makes iojs a virus and not a suitable dependency for my project.

I would be profoundly disappointed if this is the case as I feel this project shows a lot of promise.

@vkurchatkin

This comment has been minimized.

Show comment
Hide comment
@vkurchatkin

vkurchatkin Feb 12, 2015

Member

@sintaxi I'm not sure what your needs are. I've tried running harp on io.js 1.2.0 and everything seems to work fine. FWIW I'm for adding option not to create symlink to installer. But it obviously makes io.js not compatible with existing ecosystem

Member

vkurchatkin commented Feb 12, 2015

@sintaxi I'm not sure what your needs are. I've tried running harp on io.js 1.2.0 and everything seems to work fine. FWIW I'm for adding option not to create symlink to installer. But it obviously makes io.js not compatible with existing ecosystem

@sintaxi

This comment has been minimized.

Show comment
Hide comment
@sintaxi

sintaxi Feb 12, 2015

I'm not sure what your needs are. I've tried running harp on io.js 1.2.0 and everything seems to work fine.

The problem I see is you may now have other projects on your system that don't work because you clobbered node by installing iojs. That is the concern I have. If I instruct users to install iojs they are (in most cases unknowingly) clobbering their NodeJS binary and I have doubts this behaviour would be expected.

If iojs wants to install to its own namespace and leave the rest of the system alone like every other program then Im a happy camper and iojs becomes an appealing dependency.

sintaxi commented Feb 12, 2015

I'm not sure what your needs are. I've tried running harp on io.js 1.2.0 and everything seems to work fine.

The problem I see is you may now have other projects on your system that don't work because you clobbered node by installing iojs. That is the concern I have. If I instruct users to install iojs they are (in most cases unknowingly) clobbering their NodeJS binary and I have doubts this behaviour would be expected.

If iojs wants to install to its own namespace and leave the rest of the system alone like every other program then Im a happy camper and iojs becomes an appealing dependency.

@Fishrock123

This comment has been minimized.

Show comment
Hide comment
@Fishrock123

Fishrock123 Feb 12, 2015

Member

Removing the symlink only breaks my node scripts because iojs chose to clobber my node binary on install. Currently the best way to avoid these problems is to not install iojs in the first place.

0.12 will do the same.

If I tell users to install iojs because my modules depend on it than I am forcing NodeJS OFF other peoples machines which does not sit well with me.

0.11 and 0.12 modules also do this. Tell people to use a node version manager.

If you are saying you understand and that is something iojs is cool with than I suppose this discussion has come to an end but in my view that makes iojs a virus and not a suitable dependency for my project.

By definition, io.js is neither malware, nor a computer virus.

io.js is a version of node. Period.

Member

Fishrock123 commented Feb 12, 2015

Removing the symlink only breaks my node scripts because iojs chose to clobber my node binary on install. Currently the best way to avoid these problems is to not install iojs in the first place.

0.12 will do the same.

If I tell users to install iojs because my modules depend on it than I am forcing NodeJS OFF other peoples machines which does not sit well with me.

0.11 and 0.12 modules also do this. Tell people to use a node version manager.

If you are saying you understand and that is something iojs is cool with than I suppose this discussion has come to an end but in my view that makes iojs a virus and not a suitable dependency for my project.

By definition, io.js is neither malware, nor a computer virus.

io.js is a version of node. Period.

@Fishrock123

This comment has been minimized.

Show comment
Hide comment
@Fishrock123

Fishrock123 Feb 12, 2015

Member

If iojs wants to install to its own namespace and leave the rest of the system alone like every other program then Im a happy camper and iojs becomes an appealing dependency.

See the above. io.js is a version of node.

Member

Fishrock123 commented Feb 12, 2015

If iojs wants to install to its own namespace and leave the rest of the system alone like every other program then Im a happy camper and iojs becomes an appealing dependency.

See the above. io.js is a version of node.

@sintaxi

This comment has been minimized.

Show comment
Hide comment
@sintaxi

sintaxi Feb 12, 2015

io.js is a version of node. Period.

This is disingenuous to say the least. Why then do we create an iojs binary if iojs is a version of node?

I think this project deserves more credit than you are giving it and this is putting far too much stock into the "node" name. I believe io.js can stand on its own and win the community over it doesn't need to stoop to these hostile tactics.

Yes modules will need to be updated but that is not as big of deal as its being made out to be. Most people already have node installed and will likely for quite sometime. Forcing people to pick a side is not putting the community first. There is no need for a standoff.

sintaxi commented Feb 12, 2015

io.js is a version of node. Period.

This is disingenuous to say the least. Why then do we create an iojs binary if iojs is a version of node?

I think this project deserves more credit than you are giving it and this is putting far too much stock into the "node" name. I believe io.js can stand on its own and win the community over it doesn't need to stoop to these hostile tactics.

Yes modules will need to be updated but that is not as big of deal as its being made out to be. Most people already have node installed and will likely for quite sometime. Forcing people to pick a side is not putting the community first. There is no need for a standoff.

@jmar777

This comment has been minimized.

Show comment
Hide comment
@jmar777

jmar777 Feb 12, 2015

Contributor

io.js is a version of node. Period.

Not really in any meaningful sense. This may be more true-ish if there was a stated compatibility goal (which seems to have been abandoned, from what I can tell?). As it stands, there are already breaking differences between iojs and node. And barring any progress on the reconciliation front that also results in API reconciliation (or whatever a better term for that is), it seems a bit reckless to just assume that they're interchangeable. That may have been 99% "ok" for the initial release (and making NPM work out-of-the-gate), but it ultimately seems short-sighted as API decisions continue to diverge over time.

Contributor

jmar777 commented Feb 12, 2015

io.js is a version of node. Period.

Not really in any meaningful sense. This may be more true-ish if there was a stated compatibility goal (which seems to have been abandoned, from what I can tell?). As it stands, there are already breaking differences between iojs and node. And barring any progress on the reconciliation front that also results in API reconciliation (or whatever a better term for that is), it seems a bit reckless to just assume that they're interchangeable. That may have been 99% "ok" for the initial release (and making NPM work out-of-the-gate), but it ultimately seems short-sighted as API decisions continue to diverge over time.

@vkurchatkin

This comment has been minimized.

Show comment
Hide comment
@vkurchatkin

vkurchatkin Feb 12, 2015

Member

As it stands, there are already breaking differences between iojs and node

Can you name some? io.js 1.x.x is supposed to be fully backwards compatible

Member

vkurchatkin commented Feb 12, 2015

As it stands, there are already breaking differences between iojs and node

Can you name some? io.js 1.x.x is supposed to be fully backwards compatible

@naholyr

This comment has been minimized.

Show comment
Hide comment
@naholyr

naholyr Feb 12, 2015

Contributor

If node is already installed, is the symlink created anyway?
If iojs is installed, does the node installer overwrite the binary?

If no and yes, there is no issue here.

Contributor

naholyr commented Feb 12, 2015

If node is already installed, is the symlink created anyway?
If iojs is installed, does the node installer overwrite the binary?

If no and yes, there is no issue here.

@ghost

This comment has been minimized.

Show comment
Hide comment
@ghost

ghost Feb 12, 2015

@naholyr The answers are YES and YES and Node.js does the same thing.

@sintaxi If you have both installed that would also break it without an NVM. Furthermore, to not "clobber" the Node instillation would make people think you can use both without a NVM which is not possible. This is not a hostile tactic this is just the fact that they can't be used together without a NVM.

Also, you do not need to change you reference due to the symlink. That way users can make a choice of which they will use. If you want you can include a recommendation for io.js but if that bothers you don't or include a warning.

ghost commented Feb 12, 2015

@naholyr The answers are YES and YES and Node.js does the same thing.

@sintaxi If you have both installed that would also break it without an NVM. Furthermore, to not "clobber" the Node instillation would make people think you can use both without a NVM which is not possible. This is not a hostile tactic this is just the fact that they can't be used together without a NVM.

Also, you do not need to change you reference due to the symlink. That way users can make a choice of which they will use. If you want you can include a recommendation for io.js but if that bothers you don't or include a warning.

@naholyr

This comment has been minimized.

Show comment
Hide comment
@naholyr

naholyr Feb 12, 2015

Contributor

Then wouldn't a good solution be the installer not to overwrite existing node binary?
If there is already a node binary, chances are you just want to test iojs, and especially not screw your existing configuration.
If there is none, obviously creating one looks like the only good idea.

How about that? default = do not overwrite + maybe a checkbox to change that.

Anyway I join the "use nvm" voices: I think it's already mandatory when working with node itself only.

Contributor

naholyr commented Feb 12, 2015

Then wouldn't a good solution be the installer not to overwrite existing node binary?
If there is already a node binary, chances are you just want to test iojs, and especially not screw your existing configuration.
If there is none, obviously creating one looks like the only good idea.

How about that? default = do not overwrite + maybe a checkbox to change that.

Anyway I join the "use nvm" voices: I think it's already mandatory when working with node itself only.

@ghost

This comment has been minimized.

Show comment
Hide comment
@ghost

ghost Feb 12, 2015

@naholyr The problem is if you don't overwrite the node binary neither will work.

ghost commented Feb 12, 2015

@naholyr The problem is if you don't overwrite the node binary neither will work.

@schme16

This comment has been minimized.

Show comment
Hide comment
@schme16

schme16 Feb 12, 2015

As echoed several times throughout this discussion, if you need them side-by-side, then you really have to use a NVM. That being said, the aim of iojs wasn't ever to be a new product with the intention of competing, it was to be a test ground that could be used to accelerate progress and introduce new features faster, safely (as most people would be using it in production already) and in a more iterative and predictable release schedule than how Joyent had been with NodeJS. I'd really suggest listening to NodeUp Podcast #81 as the had on Mikeal Rogers and Isaac Schlueter (iojs founders) and Chris Dickinson (of Wallmartlabs) where they basically only see the project continuing in its current for or a year or two, and that they wanted to get to a position that all the great things learned and contributed to iojs would be accepted and merged back into NodeJS core (Joyent permitting, which now that they have set up a foundation to oversee Node I cannot image them being opposed to).

On the question of hostility: iojs is not trying to steal consumers away from node, its first few releases (nightlies) didn't include the symlink, and so much was borked, as soooo many (too many to expect people to change overnight) modules require the node bin. I ABSOLUTELY agree that a checkbox should be added to the installer to allow you to not have the symlink (stubbed exe on windows) installed with the rest of iojs, but node (and therefore iojs) is supposed to be easy and just work, and therefore its good practice to default the symlink on.

tldr; you aren't meant to have both installed and expect them to work together, and if you find a situation where you do need to, you should be using nvm. iojs isn't being hostile it's being practical.

schme16 commented Feb 12, 2015

As echoed several times throughout this discussion, if you need them side-by-side, then you really have to use a NVM. That being said, the aim of iojs wasn't ever to be a new product with the intention of competing, it was to be a test ground that could be used to accelerate progress and introduce new features faster, safely (as most people would be using it in production already) and in a more iterative and predictable release schedule than how Joyent had been with NodeJS. I'd really suggest listening to NodeUp Podcast #81 as the had on Mikeal Rogers and Isaac Schlueter (iojs founders) and Chris Dickinson (of Wallmartlabs) where they basically only see the project continuing in its current for or a year or two, and that they wanted to get to a position that all the great things learned and contributed to iojs would be accepted and merged back into NodeJS core (Joyent permitting, which now that they have set up a foundation to oversee Node I cannot image them being opposed to).

On the question of hostility: iojs is not trying to steal consumers away from node, its first few releases (nightlies) didn't include the symlink, and so much was borked, as soooo many (too many to expect people to change overnight) modules require the node bin. I ABSOLUTELY agree that a checkbox should be added to the installer to allow you to not have the symlink (stubbed exe on windows) installed with the rest of iojs, but node (and therefore iojs) is supposed to be easy and just work, and therefore its good practice to default the symlink on.

tldr; you aren't meant to have both installed and expect them to work together, and if you find a situation where you do need to, you should be using nvm. iojs isn't being hostile it's being practical.

@Fishrock123

This comment has been minimized.

Show comment
Hide comment
@Fishrock123

Fishrock123 Feb 12, 2015

Member

Not really in any meaningful sense. This may be more true-ish if there was a stated compatibility goal (which seems to have been abandoned, from what I can tell?). As it stands, there are already breaking differences between iojs and node. And barring any progress on the reconciliation front that also results in API reconciliation (or whatever a better term for that is), it seems a bit reckless to just assume that they're interchangeable. That may have been 99% "ok" for the initial release (and making NPM work out-of-the-gate), but it ultimately seems short-sighted as API decisions continue to diverge over time.

The exact same problems occur from any major node version bump. (or minor, in Node.js land)

Member

Fishrock123 commented Feb 12, 2015

Not really in any meaningful sense. This may be more true-ish if there was a stated compatibility goal (which seems to have been abandoned, from what I can tell?). As it stands, there are already breaking differences between iojs and node. And barring any progress on the reconciliation front that also results in API reconciliation (or whatever a better term for that is), it seems a bit reckless to just assume that they're interchangeable. That may have been 99% "ok" for the initial release (and making NPM work out-of-the-gate), but it ultimately seems short-sighted as API decisions continue to diverge over time.

The exact same problems occur from any major node version bump. (or minor, in Node.js land)

@therebelrobot

This comment has been minimized.

Show comment
Hide comment
@therebelrobot

therebelrobot Feb 12, 2015

Member

Forcing people to pick a side is not putting the community first. There is no need for a standoff.

Like the standoff between 0.10 and 0.12. Or 0.8 and 0.10. If a user doesn't understand the nature of versioning and how different versions could override another, maybe they shouldn't be working in the industry. Yes, maybe there should be more documentation on how to have concurrent installs properly, that is something we as the website working group can take a look at (We're already talking about implementing a guide section). Yes, maybe there should be a checkbox to not override the node if already installed. But to call the entire project hostile, disingenuous and creating a standoff is hyperbolic at best.

Member

therebelrobot commented Feb 12, 2015

Forcing people to pick a side is not putting the community first. There is no need for a standoff.

Like the standoff between 0.10 and 0.12. Or 0.8 and 0.10. If a user doesn't understand the nature of versioning and how different versions could override another, maybe they shouldn't be working in the industry. Yes, maybe there should be more documentation on how to have concurrent installs properly, that is something we as the website working group can take a look at (We're already talking about implementing a guide section). Yes, maybe there should be a checkbox to not override the node if already installed. But to call the entire project hostile, disingenuous and creating a standoff is hyperbolic at best.

@kenperkins

This comment has been minimized.

Show comment
Hide comment
@kenperkins

kenperkins Feb 12, 2015

Contributor

There are probably 2 issues here really:

  1. Supporting multiple versions of node & iojs on the developer environment. I assert this is the domain of version managers like nvm. I would never use a .dmg to install node or iojs on my dev machine.
  2. Supporting multiple versions of node & iojs in production environments. This is a bit more complex:
    • Use containers to sandbox specific applications to a matching version of the runtime
    • Use individual computers or VMs to the same end
    • Install different binaries to different paths on a single machine and leverage them explicitly at application invocation. this is probably not worth the trouble considering how easy containerizing an app is
    • other?

Either way, the same problems exist whether you're using node v0.10 and v0.12 or node and iojs. This is not exclusive to iojs.

Contributor

kenperkins commented Feb 12, 2015

There are probably 2 issues here really:

  1. Supporting multiple versions of node & iojs on the developer environment. I assert this is the domain of version managers like nvm. I would never use a .dmg to install node or iojs on my dev machine.
  2. Supporting multiple versions of node & iojs in production environments. This is a bit more complex:
    • Use containers to sandbox specific applications to a matching version of the runtime
    • Use individual computers or VMs to the same end
    • Install different binaries to different paths on a single machine and leverage them explicitly at application invocation. this is probably not worth the trouble considering how easy containerizing an app is
    • other?

Either way, the same problems exist whether you're using node v0.10 and v0.12 or node and iojs. This is not exclusive to iojs.

@ljharb

This comment has been minimized.

Show comment
Hide comment
@ljharb

ljharb Feb 12, 2015

When you use npm or a global module name on the command line, which one wins? You'd have to manually set up your PATH to decide that (or else both node and iojs' installers would have to work around each other to provide the option, so I don't think that's tenable). What happens when you have two (conflicting) versions installed of a global module, one on node and one on iojs? What happens when you npm install -g something, and it installs to iojs, and the one in node's npm root -g gets shadowed?

I can't understand why anyone would expect to be able to use iojs and node at the same time on the same shell, nor how it would work in an intuitive, unsurprising, and robust fashion.

ljharb commented Feb 12, 2015

When you use npm or a global module name on the command line, which one wins? You'd have to manually set up your PATH to decide that (or else both node and iojs' installers would have to work around each other to provide the option, so I don't think that's tenable). What happens when you have two (conflicting) versions installed of a global module, one on node and one on iojs? What happens when you npm install -g something, and it installs to iojs, and the one in node's npm root -g gets shadowed?

I can't understand why anyone would expect to be able to use iojs and node at the same time on the same shell, nor how it would work in an intuitive, unsurprising, and robust fashion.

@jmar777

This comment has been minimized.

Show comment
Hide comment
@jmar777

jmar777 Feb 12, 2015

Contributor

The exact same problems occur from any major node version bump. (or minor, in Node.js land)

Having thought on this some more and reading over the comments, I think this makes more sense that I was initially giving it credit for. I do think this needs better communication and stronger guarantees, though (even/especially in the installer). It's not really fair to shrug this off as an analog for node clobbering another version of node:

  • It's almost universally expected for new versions of an app to clobber old versions of the same app (whereas it's almost never expected where the apps differ).
  • When upgrading node, the backwards compatibility situation is both documented and implicit in the version system.
  • I still haven't found any form of documentation stating in which cases iojs is drop-in replacement for node (where drop-in implies backwards-compatibility). Maybe that's a safe and/or implicit guarantee in all versions of iojs right now? If so, that needs to be more clearly documented. Regardless of the current state, though, I'll reiterate my request for if/where that guarantee (or at least stated intention) is being made for future versions. As it stands, I can't point to anything anywhere that says "the current version of iojs will always attempt to be a safe drop-in replacement for any version of node" (or perhaps a more qualified version of that, if necessary). Without something to that effect, it's necessarily scary for it to clobber node. I realize that without doing so, it breaks iojs. I'm just asserting that's not a valid enough reason to break node instead, without providing a clear reason why and providing a guarantee about whether or not that's a safe thing to do.

TLDR:

  • I agree with iojs clobbering node by default now (yay)...
  • ...but only with much better communication about why...
  • ...and some explicit, clear documentation about what the backwards-compatibility goals/guarantees are.

I realize this isn't the tone or spirit of the message, but I feel like what's currently being communicated is "we don't want to break our binary, so we'll replace (break) the other one instead, but don't worry because it will maybe/possibly/probably be a good drop-in replacement". I'm just looking for something more clear than the maybe/possibly/probably part. And for all I know, that's already very clearly documented somewhere - I just can't find it if it is.

Thanks :)

Contributor

jmar777 commented Feb 12, 2015

The exact same problems occur from any major node version bump. (or minor, in Node.js land)

Having thought on this some more and reading over the comments, I think this makes more sense that I was initially giving it credit for. I do think this needs better communication and stronger guarantees, though (even/especially in the installer). It's not really fair to shrug this off as an analog for node clobbering another version of node:

  • It's almost universally expected for new versions of an app to clobber old versions of the same app (whereas it's almost never expected where the apps differ).
  • When upgrading node, the backwards compatibility situation is both documented and implicit in the version system.
  • I still haven't found any form of documentation stating in which cases iojs is drop-in replacement for node (where drop-in implies backwards-compatibility). Maybe that's a safe and/or implicit guarantee in all versions of iojs right now? If so, that needs to be more clearly documented. Regardless of the current state, though, I'll reiterate my request for if/where that guarantee (or at least stated intention) is being made for future versions. As it stands, I can't point to anything anywhere that says "the current version of iojs will always attempt to be a safe drop-in replacement for any version of node" (or perhaps a more qualified version of that, if necessary). Without something to that effect, it's necessarily scary for it to clobber node. I realize that without doing so, it breaks iojs. I'm just asserting that's not a valid enough reason to break node instead, without providing a clear reason why and providing a guarantee about whether or not that's a safe thing to do.

TLDR:

  • I agree with iojs clobbering node by default now (yay)...
  • ...but only with much better communication about why...
  • ...and some explicit, clear documentation about what the backwards-compatibility goals/guarantees are.

I realize this isn't the tone or spirit of the message, but I feel like what's currently being communicated is "we don't want to break our binary, so we'll replace (break) the other one instead, but don't worry because it will maybe/possibly/probably be a good drop-in replacement". I'm just looking for something more clear than the maybe/possibly/probably part. And for all I know, that's already very clearly documented somewhere - I just can't find it if it is.

Thanks :)

@RobertWHurst

This comment has been minimized.

Show comment
Hide comment
@RobertWHurst

RobertWHurst Feb 13, 2015

I really don't like symlink for node either. Not only does this break node installs, but It requires that iojs mirror all expected behaviour for node. Correct me If I'm wrong here, but If someone writes a module that contains a call to node, shouldn't we expect node to be used? I'm talking about modules that are either globally installed, or have package scripts. If these modules we're built with node, then maybe they should be run on node. The same can be said for new modules that are authored against iojs. As far as I know this doesn't affect modules that are required by a script, am I correct? If someone wants to use modules that were written for node on iojs, or vice-versa then let them symlink manually. It may suck that you have to install node for older global modules, but for the sake of sanity, we shouldn't be touching other binaries.

I would add it's probably better to allow module authors to add iojs support rather than try to shoe horn the support for them in this way.

RobertWHurst commented Feb 13, 2015

I really don't like symlink for node either. Not only does this break node installs, but It requires that iojs mirror all expected behaviour for node. Correct me If I'm wrong here, but If someone writes a module that contains a call to node, shouldn't we expect node to be used? I'm talking about modules that are either globally installed, or have package scripts. If these modules we're built with node, then maybe they should be run on node. The same can be said for new modules that are authored against iojs. As far as I know this doesn't affect modules that are required by a script, am I correct? If someone wants to use modules that were written for node on iojs, or vice-versa then let them symlink manually. It may suck that you have to install node for older global modules, but for the sake of sanity, we shouldn't be touching other binaries.

I would add it's probably better to allow module authors to add iojs support rather than try to shoe horn the support for them in this way.

@mikeal

This comment has been minimized.

Show comment
Hide comment
@mikeal

mikeal Feb 13, 2015

Member

but It requires that iojs mirror all expected behaviour for node

This is a given no matter what. In order to remain compatible with all the modules in npm we can't break backwards compatiblity with old versions of node.

Correct me If I'm wrong here, but If someone writes a module that contains a call to node, shouldn't we expect node to be used?

This is actually very similar to what happens with different implementations of the jvm, all of which clobber the java binary.

Member

mikeal commented Feb 13, 2015

but It requires that iojs mirror all expected behaviour for node

This is a given no matter what. In order to remain compatible with all the modules in npm we can't break backwards compatiblity with old versions of node.

Correct me If I'm wrong here, but If someone writes a module that contains a call to node, shouldn't we expect node to be used?

This is actually very similar to what happens with different implementations of the jvm, all of which clobber the java binary.

@kenperkins

This comment has been minimized.

Show comment
Hide comment
@kenperkins

kenperkins Feb 13, 2015

Contributor

Edit: Considering @mikeal's comment below this speculation on my part is not particularly accurate

I think we could more explicitly declare a philosophy that's close to MariaDBs:

MariaDB is a community-developed fork of the MySQL relational database management system intended to remain free under the GNU GPL. Being a fork of a leading open source software system, it is notable for being led by the original developers of MySQL, who forked it due to concerns over its acquisition by Oracle. Contributors are required to share their copyright with the MariaDB Foundation.

The intent is also to maintain high compatibility with MySQL, ensuring a "drop-in" replacement capability with library binary equivalency and exact matching with MySQL APIs and commands. It includes the XtraDB storage engine for replacing InnoDB as well as a new storage engine, Aria, that intends to be both a transactional and non-transactional engine perhaps even included in future versions of MySQL.

Minor edits with s/MySQL/node and s/MariaDB/io.js:

io.js is a community-developed fork of the node.js javascript runtime intended to remain free under the MIT license. Being a fork of a leading open source software system, it is notable for being led by many of the original developers of node.js, who forked it due to concerns over its direction by Joyent. Contributors are required to share their copyright with the MariaDB Foundation.

The intent is also to maintain high compatibility with node.js, ensuring a "drop-in" replacement capability with library binary equivalency and exact matching with node.js APIs and commands.

I do wonder if that statement is actually part of the official plan of record, however.

Contributor

kenperkins commented Feb 13, 2015

Edit: Considering @mikeal's comment below this speculation on my part is not particularly accurate

I think we could more explicitly declare a philosophy that's close to MariaDBs:

MariaDB is a community-developed fork of the MySQL relational database management system intended to remain free under the GNU GPL. Being a fork of a leading open source software system, it is notable for being led by the original developers of MySQL, who forked it due to concerns over its acquisition by Oracle. Contributors are required to share their copyright with the MariaDB Foundation.

The intent is also to maintain high compatibility with MySQL, ensuring a "drop-in" replacement capability with library binary equivalency and exact matching with MySQL APIs and commands. It includes the XtraDB storage engine for replacing InnoDB as well as a new storage engine, Aria, that intends to be both a transactional and non-transactional engine perhaps even included in future versions of MySQL.

Minor edits with s/MySQL/node and s/MariaDB/io.js:

io.js is a community-developed fork of the node.js javascript runtime intended to remain free under the MIT license. Being a fork of a leading open source software system, it is notable for being led by many of the original developers of node.js, who forked it due to concerns over its direction by Joyent. Contributors are required to share their copyright with the MariaDB Foundation.

The intent is also to maintain high compatibility with node.js, ensuring a "drop-in" replacement capability with library binary equivalency and exact matching with node.js APIs and commands.

I do wonder if that statement is actually part of the official plan of record, however.

@mikeal

This comment has been minimized.

Show comment
Hide comment
@mikeal

mikeal Feb 13, 2015

Member

@kenperkins I have some similar language about ensuring compatibility in the roadmap and in the stability policy. The problem we have is that while we are compatible with node 0.12.0 JS API (not C++ because of the difference in v8) and not entirely with 0.10.x because of some differences (improvements) in streams, we still can't say we will ensure compatibility with 0.12.x because Joyent could add modified versions of our API additions or change behavior in a point release (there is no official policy they are committed to on this). All we can really say is what we've already stated in the stability policy which is that we won't break compatibility with prior releases on the JS side.

Member

mikeal commented Feb 13, 2015

@kenperkins I have some similar language about ensuring compatibility in the roadmap and in the stability policy. The problem we have is that while we are compatible with node 0.12.0 JS API (not C++ because of the difference in v8) and not entirely with 0.10.x because of some differences (improvements) in streams, we still can't say we will ensure compatibility with 0.12.x because Joyent could add modified versions of our API additions or change behavior in a point release (there is no official policy they are committed to on this). All we can really say is what we've already stated in the stability policy which is that we won't break compatibility with prior releases on the JS side.

@kenperkins

This comment has been minimized.

Show comment
Hide comment
@kenperkins

kenperkins Feb 13, 2015

Contributor

I'll have to make sure I don't re-use the MariaDB analogy then, considering that. Thanks for the clarification.

Contributor

kenperkins commented Feb 13, 2015

I'll have to make sure I don't re-use the MariaDB analogy then, considering that. Thanks for the clarification.

@notpushkin

This comment has been minimized.

Show comment
Hide comment
@notpushkin

notpushkin Mar 5, 2015

@targos Thanks for the nvm advice!

notpushkin commented Mar 5, 2015

@targos Thanks for the nvm advice!

@n2liquid

This comment has been minimized.

Show comment
Hide comment
@n2liquid

n2liquid Apr 27, 2015

Sorry to ressurect this thread, but can't io.js replace the node executable by an executable that will first check if another version of Node is installed and use that, otherwise it uses iojs?

That way, programs that strictly depend on iojs can use #!/usr/bin/env iojs, and iojs will try to run Node scripts if NodeJS itself is not present.

I honestly do not understand why no one is discussing this possibility. It seems like the most obvious one to me. I'm not saying it's perfect; it just seems the best to me. A version manager would be great, if only version managers didn't tend to suck so bad. They're my main grudge against Python and Ruby. I really didn't want to see Node going that way.

@indexzero, what do you think of that?

Edit:

Are packages compiled for iojs via npm installed on a special iojs directory or are they stored on the same directory Node uses? If the latter, than more would need to be done to get both to work side-by-side.

n2liquid commented Apr 27, 2015

Sorry to ressurect this thread, but can't io.js replace the node executable by an executable that will first check if another version of Node is installed and use that, otherwise it uses iojs?

That way, programs that strictly depend on iojs can use #!/usr/bin/env iojs, and iojs will try to run Node scripts if NodeJS itself is not present.

I honestly do not understand why no one is discussing this possibility. It seems like the most obvious one to me. I'm not saying it's perfect; it just seems the best to me. A version manager would be great, if only version managers didn't tend to suck so bad. They're my main grudge against Python and Ruby. I really didn't want to see Node going that way.

@indexzero, what do you think of that?

Edit:

Are packages compiled for iojs via npm installed on a special iojs directory or are they stored on the same directory Node uses? If the latter, than more would need to be done to get both to work side-by-side.

@rvagg

This comment has been minimized.

Show comment
Hide comment
@rvagg

rvagg Apr 28, 2015

Member

replace the node executable by an executable that will first check if another version of Node is installed and use that

So, if we overwrite an existing node installation with an executable, what is there to detect, since the previous one has been removed?

Member

rvagg commented Apr 28, 2015

replace the node executable by an executable that will first check if another version of Node is installed and use that

So, if we overwrite an existing node installation with an executable, what is there to detect, since the previous one has been removed?

@schme16

This comment has been minimized.

Show comment
Hide comment
@schme16

schme16 Apr 28, 2015

@rvagg: I think what @n2liquid means, is to replace the node binary inside the iojs directory with a binary that first checks if there is an existing node installation, and only links to the iojs binary when there isn't an existing node installation (feel free to correct me @n2liquid).

(@rvagg: totally off topic, but I loved the the latest NodeUp - Never enough of us ANZAC's around, haha)

schme16 commented Apr 28, 2015

@rvagg: I think what @n2liquid means, is to replace the node binary inside the iojs directory with a binary that first checks if there is an existing node installation, and only links to the iojs binary when there isn't an existing node installation (feel free to correct me @n2liquid).

(@rvagg: totally off topic, but I loved the the latest NodeUp - Never enough of us ANZAC's around, haha)

@rvagg

This comment has been minimized.

Show comment
Hide comment
@rvagg

rvagg Apr 28, 2015

Member

"iojs directory" only makes sense on Windows, everywhere else it's a shared PATH space like /usr/bin or /usr/local/bin where you have only one of a thing with a particular name.

Member

rvagg commented Apr 28, 2015

"iojs directory" only makes sense on Windows, everywhere else it's a shared PATH space like /usr/bin or /usr/local/bin where you have only one of a thing with a particular name.

@schme16

This comment has been minimized.

Show comment
Hide comment
@schme16

schme16 Apr 28, 2015

@rvagg: ahh, that's true, my Windows past is showing; feel free to ignore me.

schme16 commented Apr 28, 2015

@rvagg: ahh, that's true, my Windows past is showing; feel free to ignore me.

@n2liquid

This comment has been minimized.

Show comment
Hide comment
@n2liquid

n2liquid Apr 28, 2015

@rvagg: So I trust it you've considered deeply the possibility of replacing the node executable with a delegator script and to the best of your knowledge it's not viable, correct?

This is tough. I know it is. But it's insane to think there isn't a simple solution to it. GNU has come a long way, and there's still no easy way to handle this? This doesn't look like an uncommon scenario: Two or more packages offer the same executable. User can select which one he wants at anytime and if the one in use is removed, it falls back to another one, until there is no more options left; then the executable is gone.

I think I've seen some package managers offering such a feature (Portage?), but not all.

n2liquid commented Apr 28, 2015

@rvagg: So I trust it you've considered deeply the possibility of replacing the node executable with a delegator script and to the best of your knowledge it's not viable, correct?

This is tough. I know it is. But it's insane to think there isn't a simple solution to it. GNU has come a long way, and there's still no easy way to handle this? This doesn't look like an uncommon scenario: Two or more packages offer the same executable. User can select which one he wants at anytime and if the one in use is removed, it falls back to another one, until there is no more options left; then the executable is gone.

I think I've seen some package managers offering such a feature (Portage?), but not all.

@rvagg

This comment has been minimized.

Show comment
Hide comment
@rvagg

rvagg Apr 28, 2015

Member

Debian-based systems do it with alternatives but that needs to happen at a package-level, we're considering this over at https://github.com/nodesource/distributions but we have enough on our plate right now that it's not a high priority.

OS X installers are pretty rudimentary and I really don't know what the state-of-the-art is there (or if there is such a thing - they don't even do "uninstallers" on OS X).

Windows is ironically best placed to do this easily given the mechanism you're proposing.

However, what you've suggested involves a lot of magic on the user's behalf, you're making an assumption about what they are wanting to actually invoke and you don't have enough information to even make an informed assumption! The most straight-forward way to make an assumption about what the user is wanting to invoke is to just use the version they last installed, which is the current situation now across all of our installers. Running both io.js and Node.js on the same computer is something that only concerns some developers, most devs and I'd suggest almost all production deploys will only be using one version of one project. Given that version managers like nave, n, nvm, nvm.sh have adapted to the new reality of letting you install multiple versions and do it quite well, this issue is a very low priority for the project.

If you want to run Node.js, install that, if you want to run io.js, install that, if you want to run both for some reason, use a version manager, they are perfect for developers and give you an easy way to always grab the latest version as a bonus.

Member

rvagg commented Apr 28, 2015

Debian-based systems do it with alternatives but that needs to happen at a package-level, we're considering this over at https://github.com/nodesource/distributions but we have enough on our plate right now that it's not a high priority.

OS X installers are pretty rudimentary and I really don't know what the state-of-the-art is there (or if there is such a thing - they don't even do "uninstallers" on OS X).

Windows is ironically best placed to do this easily given the mechanism you're proposing.

However, what you've suggested involves a lot of magic on the user's behalf, you're making an assumption about what they are wanting to actually invoke and you don't have enough information to even make an informed assumption! The most straight-forward way to make an assumption about what the user is wanting to invoke is to just use the version they last installed, which is the current situation now across all of our installers. Running both io.js and Node.js on the same computer is something that only concerns some developers, most devs and I'd suggest almost all production deploys will only be using one version of one project. Given that version managers like nave, n, nvm, nvm.sh have adapted to the new reality of letting you install multiple versions and do it quite well, this issue is a very low priority for the project.

If you want to run Node.js, install that, if you want to run io.js, install that, if you want to run both for some reason, use a version manager, they are perfect for developers and give you an easy way to always grab the latest version as a bonus.

@schme16

This comment has been minimized.

Show comment
Hide comment
@schme16

schme16 commented May 1, 2015

@rvagg 👍

@afshinm

This comment has been minimized.

Show comment
Hide comment
@afshinm

afshinm commented May 14, 2015

+1

@Fishrock123

This comment has been minimized.

Show comment
Hide comment
@Fishrock123

Fishrock123 May 14, 2015

Member

Now that we've agreed to merge into the Node Foundation there's not really a point. Maybe if someone can put in the work for a patch to make it optional.

Member

Fishrock123 commented May 14, 2015

Now that we've agreed to merge into the Node Foundation there's not really a point. Maybe if someone can put in the work for a patch to make it optional.

@rambo-panda

This comment has been minimized.

Show comment
Hide comment
@rambo-panda

rambo-panda May 18, 2015

https://www.binarysludge.com/2015/01/14/how-to-uninstall-io-js-or-io-js-and-node-js-together/

sudo rm /usr/local/bin/node && ln -s /usr/local/Cellar/node/0.10.32/bin/node /usr/local/bin/node
node --version 
iojs --version

rambo-panda commented May 18, 2015

https://www.binarysludge.com/2015/01/14/how-to-uninstall-io-js-or-io-js-and-node-js-together/

sudo rm /usr/local/bin/node && ln -s /usr/local/Cellar/node/0.10.32/bin/node /usr/local/bin/node
node --version 
iojs --version
@anthonybrown

This comment has been minimized.

Show comment
Hide comment
@anthonybrown

anthonybrown Jun 30, 2015

👍 rambo-panda
Just came here from the binarysludge article, now I ask, why the symlink to node?

anthonybrown commented Jun 30, 2015

👍 rambo-panda
Just came here from the binarysludge article, now I ask, why the symlink to node?

@Fishrock123

This comment has been minimized.

Show comment
Hide comment
@Fishrock123

Fishrock123 Jun 30, 2015

Member

Why: in short, so that node executable files work properly. (See above for more context.)

No such symlinks will exist in the converged node because it will only be node.

Member

Fishrock123 commented Jun 30, 2015

Why: in short, so that node executable files work properly. (See above for more context.)

No such symlinks will exist in the converged node because it will only be node.

@nodejs nodejs locked and limited conversation to collaborators Jun 30, 2015

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