thoughtbot / laptop

A shell script to set up a macOS laptop for web and mobile development.
https://thoughtbot.com
MIT License
8.5k stars 1.91k forks source link

Do the scripts really need to be ZSH scripts? #138

Closed pbrisbin closed 10 years ago

pbrisbin commented 11 years ago

The setup script itself being shebang'd for zshell means that the Linux version must be split: One prerequisite script to install zshell and another to do the actual setup. It's odd (IMO) for an automation tool to require 2 steps.

I propose we make the scripts bash. Bash is available by default on both Mac and Linux and has many niceties above trying to stay sh-compatible.

We're not using any zshell-only features; the only place the script being zshell is useful is when we want to execute ruby commands within the rbenv context we've previously setup for zshell. To address this, I would simply do something like

# setup rbenv
echo "..." >> ~/.zshrc

# run a command in that context
zsh -i -l -c 'gem install foo bar ...'

I think the above approach is clearer and more rubust regardless, and doesn't require we re-source or re-exec anything mid-script to modify the environment.

mike-burns commented 11 years ago

If we're going to drop zsh in order to go with the lowest common denominator, let's go with POSIX sh. It's actually installed on all unix machines, plus some systems (e.g. Debian, FreeBSD, Ubuntu) run sh scripts faster than bash scripts. Most of the zsh scripts in the laptop suite are actually POSIX compliant already, or nearly so.

mike-burns commented 11 years ago

Just looked: the existing scripts do nothing fancy. They should convert to POSIX sh without any code change.

pbrisbin commented 11 years ago

It's interesting to hear you argue "why not be portable when you can?" vs my argument "why worry about portability when you don't have to?".

I think the more likely change going forward would be that we'd have a use for some non-POSIX feature (regex tests, substitutions, string indexing, etc) than that we'd want to support a system that doesn't have bash available. Therefore, I think bash is the better choice.

Examples that (I think) are not POSIX:

process substitution, would have to use stdin
  ruby <(curl -fsS https://raw.github.com/mxcl/homebrew/go)

echo with special characters, would replace all with printf
  echo "\n# recommended by brew doctor" >> ~/.zshrc

source, should be .
  source ~/.zshrc

Obviously these could be made portable, but why?

djcp commented 11 years ago

I am all for having a single linux script and getting rid of the prerequisites oddness, as long as the end result would be the same - a fully configured zshell ruby/rails environment.

kevinSuttle commented 11 years ago

I'm wondering too if the chsh -s /usr/bin/zsh can be automated. I had it at the beginning of my manifest at one point, but removed it until I got a more informed answer.

I personally also would do this again at the end after I brew install zsh, (chsh -s usr/local/bin/zsh), after /etc/shells is appended with /usr/local/Cellar/zsh/5.0.2/bin/zsh.

thcipriani commented 10 years ago

While I can see the argument for full POSIX compliance, Laptop only supports precise, quantal, wheezy, raring and jessie which all default to using bash with version 4.2. I don't see a good reason to support less feature rich shells or pre-bash 4 features.

The problem is that users have to do a prerequisite for Linux installs (also, the exec ($which zsh) -l has been a little hit-and-miss for me, but switching to bash until the end of this script solves that nicely).

If anyone is interested in POSIX compliance, I ran the scripts through the checkbashisms perl script and came up with these (which, sadly, is most of what I've contributed to the project :shipit:)

possible bashism in linux line 20 (alternative test command ([[ foo ]] should be [ foo ])):
if [[ ":$PATH:" != *":$HOME/.bin:"* ]]; then
possible bashism in linux line 22 (should be '.', not 'source'):
  source ~/.zshrc
possible bashism in linux line 27 (printf %q|%b):
  printf "\n%b\n" "$1"
possible bashism in linux line 39 ('command' with option other than -p):
  if command -v aptitude >/dev/null; then
possible bashism in linux line 99 (should be '.', not 'source'):
  source ~/.zshrc
possible bashism in linux-prerequisites line 17 (printf %q|%b):
  printf "\n%b\n" "$1"
possible bashism in linux-prerequisites line 29 ('command' with option other than -p):
  if command -v aptitude >/dev/null; then
possible bashism in mac line 20 (alternative test command ([[ foo ]] should be [ foo ])):
if [[ ":$PATH:" != *":$HOME/.bin:"* ]]; then
possible bashism in mac line 22 (should be '.', not 'source'):
  source ~/.zshrc
possible bashism in mac line 27 (printf %q|%b):
  printf "\n%b\n" "$1"
possible bashism in mac line 31 (alternative test command ([[ foo ]] should be [ foo ])):
if [[ -f /etc/zshenv ]]; then
possible bashism in mac line 33 (brace expansion):
    sudo mv /etc/{zshenv,zshrc}
possible bashism in mac line 38 (<() process substituion):
  ruby <(curl -fsS https://raw.github.com/mxcl/homebrew/go)
possible bashism in mac line 43 (unsafe echo with backslash):
    echo "\n# recommended by brew doctor" >> ~/.zshrc
possible bashism in mac line 44 (unsafe echo with backslash):
    echo "export PATH='/usr/local/bin:$PATH'\n" >> ~/.zshrc
possible bashism in mac line 45 (should be '.', not 'source'):
    source ~/.zshrc
possible bashism in mac line 92 (should be '.', not 'source'):
  source ~/.zshrc
gabebw commented 10 years ago

This is totally subjective: sh scares me, because I feel like it's so basic that I wouldn't know what I can and can't use. I'd be fine switching to bash, because I know bash, and I'm pretty sure that I know which fancy bits we use are zsh (apparently none, as some commenters pointed out).

My two cents.

mike-burns commented 10 years ago

Also totally subjective: I dislike bash and don't have it installed whenever possible. I consider bash a third-party interpreter, and not a very good one either in comparison with Ruby or Python.

croaky commented 10 years ago

I'd love to remove the prerequisites reduce the two-step install process to one step.

If my shell is set to zsh before I run this script, and the script is bash or sh, that's fine as long as bash or sh is installed on the machine?

It seems like it's a shorter path to get the script working on bash as opposed to sh based on the bashisms test above. If @mike-burns or someone else opened a PR for a sh version first, though, I could probably be convinced.

Does someone want to turn this conversation into code? I'm not sure I know how to tackle it.

pbrisbin commented 10 years ago

If my shell is set to zsh before I run this script, and the script is bash or sh, that's fine as long as bash or sh is installed on the machine?

Yes, that's correct.

I agree that it would take very little effort to make this Bash. ZSH is already a third-party interpreter that is not Ruby or Python, so I see this lateral move as net-positive since it removes the need for the pre-req script.

I'll go ahead with a PR as soon as I get time to do so.

djcp commented 10 years ago

awyiss - fixed here: https://github.com/thoughtbot/laptop/commit/5d749c0aed643770d8f806734b38b0a55bea3999