Skip to content
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

Bash installer #256

Merged
merged 58 commits into from
Mar 2, 2020
Merged

Bash installer #256

merged 58 commits into from
Mar 2, 2020

Conversation

itchyny
Copy link
Contributor

@itchyny itchyny commented Jan 23, 2020

Hi, I looked into the installer and translated into bash one line by one. Needs some more works (not sure how to compare version string.. maybe I'll implement this with arrays parameter substitution works). I love Homebrew, thank you all.

Why?

but shell script is hard to write

I introduced shellcheck integration. This tool catches various common mistakes in shell script and there's no reason to follow it.

a few notes

  • Intentional changes
    • Basically I ported keeping the behavior of the original script but I intentionally introduced some changes.
      • Since user_chmods are already chmod 755, there's no need to chmod zsh_dirs bc13488
      • Print a newline after the donation link 589c653
      • Print audible bell only when the stdout is tty 4f0094f
  • Always check the length of the array when iterating through it
    • for x in ${arr[@]} splits an element containing a space, for x in "${a[@]}" aborts with unbound variable when set -u, "${a[@]-}" emits an empty string when the array is empty, "${a[@]+"${a[@]}"}" (see https://stackoverflow.com/questions/7577052) works actually but the syntax is ugly. Checking the length is much simpler and readable.
  • Including Linuxbrew to this script is not that difficult (maybe). Note that the flags of stat is not portable.

@MikeMcQuaid
Copy link
Member

@itchyny Did a full review of this, some testing and made some tweaks/fixes where I saw them. As a starting point: this is an incredible first contribution, I'm really impressed 👏. I think it's now at a stage where I'm happy to have this merged. I just want to have a few other maintainers give their 👀 on it and ensure I only merge this at a time where I can be around to make any quick fixes should problems pop up. Let me know what you think of any of my changes. Again: great work!

@Homebrew/maintainers would appreciate as many of you as possible taking a look at this and offering any thoughts. Thanks!


# Use an extra newline and bold to avoid this being missed.
ohai "Homebrew has enabled anonymous aggregate formulae and cask analytics."
echo "$(cat <<EOS
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why echo and cat at once? cat alone should suffice.

# This script installs to /usr/local only. To install elsewhere (which is
# unsupported) you can untar https://github.com/Homebrew/brew/tarball/master
# anywhere you like.
HOMEBREW_PREFIX="/usr/local"
Copy link
Member

@vitorgalvao vitorgalvao Feb 27, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bash has a lot of pitfalls and places where things can go wrong if we’re distracted.

I’d feel safer if every variable would be readonly when possible (i.e. if it’s not, you know it will change) and used single quotes unless double quotes are necessary.

tty_reset="$(tty_escape 0)"

shell_join() {
local arg
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly, local variables should be local -r (local and readonly).

MACOS_OLDEST_SUPPORTED="10.13"

# no analytics during installation
export HOMEBREW_NO_ANALYTICS_THIS_RUN=1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To make a variable readonly and exported at the same time, declare -rx works.


####################################################################### script
if [[ "$OSTYPE" == "linux-gnu" ]]; then
abort "$(cat <<'EOABORT'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, it’s weird to me that a function is called and then cat is called inside. In this case, there’s also the case that EOABORT is quoted, which is inconsistent with the rest of the code.

}

should_install_command_line_tools() {
if version_gt "$macos_version" "10.13"; then
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All variables should be ${var} instead of $var. That’s one of those simple things that can save us from a world of trouble by doing everywhere, and we definitely do not want this script to fail due to mistakes.

In addition, it makes the script consistent throughout, since several cases already use the former notation.

ohai "You are using macOS ${macos_version}."
ohai "${who} do not provide support for this ${what}."

echo "$(cat <<EOS
Copy link
Member

@vitorgalvao vitorgalvao Feb 27, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, I don’t get the use of cat, as echo alone would suffice. And we can make it look nicer by keeping the indentation and removing it on output, like so:

echo "
  Some message
  With ${variables}
" | sed -E 's/^ {2}//'

Replacing the 2 with however many spaces we have at the start of the line.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally prefer simpler and less magical (no undenting).

cat <<EOS
Hello, world!
EOS

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I disagree that the sed call is either complex or magical, especially when you consider the script as a whole, but I won’t bikeshed it. Not using echo and cat at the same time should be considered, though.

There’s also

cat <<-EOS
	Hello
	World
EOS

The <<- removes the indentation (not as good as Ruby’s <<~), but it only works with tabs.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Undenting is also probably not worth the complexity, agreed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or we could just echo every line separately, which also aligns nicely with ohai, as seen below.

@dawidd6
Copy link
Member

dawidd6 commented Feb 28, 2020

Initial Linux support on top of this PR branch: https://github.com/dawidd6/install/tree/install-sh-linux.

if [[ "$OSTYPE" == "linux-gnu" ]]; then
abort "$(cat <<'EOABORT'
To install Homebrew on Linux, paste at a terminal prompt:
sh -c "$(curl -fsSL https://raw.githubusercontent.com/Linuxbrew/install/master/install.sh)"
Copy link
Member

@vitorgalvao vitorgalvao Feb 28, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should be explicit (/bin/bash -c). /bin/sh is often a link to something else and can change (e.g. in Ubuntu it used to point to bash and later dash), which might mean unexpected breakage when we least expect it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But it's a sh script actually, not bash.

https://github.com/Linuxbrew/install/blob/master/install.sh

Look at the shebang.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dawidd6 in this PR it's #!/bin/bash. On most systems /bin/sh runs bash or some other interpreter in compatibility mode, IIRC.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When you run sh -c "…" the shebang line is ignored. The script will be run using sh, not with whatever the shebang line specifies. We should either remove Bash-isms from the script and test with dash, or change the installation instructions to bash -c "…".

@MikeMcQuaid
Copy link
Member

@vitorgalvao and others: I appreciate the style suggestions but as this PR is otherwise ready to go (and I'm limited in the windows in which I can merge it and it's limiting other things going in until it's done) I'm going to merge as-is and accept PRs to tweak style. Ideally all style checks will be enforced by shellcheck or similar.

The sh -c I'm also leaving as-is as it's what was in the existing code (which I think is worthing sticking as close to as possible for this PR) and it should go away as soon as we get Linux support in here.

@MikeMcQuaid MikeMcQuaid merged commit f782bb3 into Homebrew:master Mar 2, 2020
@MikeMcQuaid
Copy link
Member

Thanks so much for your first, incredible contribution! Without people like you submitting PRs we couldn't run this project. You rock, @itchyny!

@itchyny
Copy link
Contributor Author

itchyny commented Mar 2, 2020

Great, thank you all for throughout reviews! I'm honored and I love Homebrew!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Port installer to Bash
7 participants