• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/bin/sh
2
3# A word about this shell script:
4#
5# It must work everywhere, including on systems that lack
6# a /bin/bash, map 'sh' to ksh, ksh97, bash, ash, or zsh,
7# and potentially have either a posix shell or bourne
8# shell living at /bin/sh.
9#
10# See this helpful document on writing portable shell scripts:
11# https://www.gnu.org/s/hello/manual/autoconf/Portable-Shell.html
12#
13# The only shell it won't ever work on is cmd.exe.
14
15if [ "x$0" = "xsh" ]; then
16  # run as curl | sh
17  # on some systems, you can just do cat>npm-install.sh
18  # which is a bit cuter.  But on others, &1 is already closed,
19  # so catting to another script file won't do anything.
20  # Follow Location: headers, and fail on errors
21  curl -f -L -s https://www.npmjs.org/install.sh > npm-install-$$.sh
22  ret=$?
23  if [ $ret -eq 0 ]; then
24    (exit 0)
25  else
26    echo "Uninstalling npm-install-$$.sh" >&2
27    rm npm-install-$$.sh
28    echo "Failed to download script" >&2
29    exit $ret
30  fi
31  sh npm-install-$$.sh
32  ret=$?
33  echo "Uninstalling npm-install-$$.sh" >&2
34  rm npm-install-$$.sh
35  exit $ret
36fi
37
38# See what "npm_config_*" things there are in the env,
39# and make them permanent.
40# If this fails, it's not such a big deal.
41configures="`env | grep 'npm_config_' | sed -e 's|^npm_config_||g'`"
42
43npm_config_loglevel="error"
44if [ "x$npm_debug" = "x" ]; then
45  (exit 0)
46else
47  echo "Running in debug mode."
48  echo "Note that this requires bash or zsh."
49  set -o xtrace
50  set -o pipefail
51  npm_config_loglevel="verbose"
52fi
53export npm_config_loglevel
54
55# make sure that node exists
56node=`which node 2>&1`
57ret=$?
58# if not found, try "nodejs" as it is the case on debian
59if [ $ret -ne 0 ]; then
60  node=`which nodejs 2>&1`
61  ret=$?
62fi
63if [ $ret -eq 0 ] && [ -x "$node" ]; then
64  (exit 0)
65else
66  echo "npm cannot be installed without node.js." >&2
67  echo "Install node first, and then try again." >&2
68  echo "" >&2
69  echo "Maybe node is installed, but not in the PATH?" >&2
70  echo "Note that running as sudo can change envs." >&2
71  echo ""
72  echo "PATH=$PATH" >&2
73  exit $ret
74fi
75
76# set the temp dir
77TMP="${TMPDIR}"
78if [ "x$TMP" = "x" ]; then
79  TMP="/tmp"
80fi
81TMP="${TMP}/npm.$$"
82rm -rf "$TMP" || true
83mkdir "$TMP"
84if [ $? -ne 0 ]; then
85  echo "failed to mkdir $TMP" >&2
86  exit 1
87fi
88
89BACK="$PWD"
90
91ret=0
92tar="${TAR}"
93if [ -z "$tar" ]; then
94  tar="${npm_config_tar}"
95fi
96if [ -z "$tar" ]; then
97  tar=`which tar 2>&1`
98  ret=$?
99fi
100
101if [ $ret -eq 0 ] && [ -x "$tar" ]; then
102  echo "tar=$tar"
103  if [ $tar --version > /dev/null 2>&1 ]; then
104    echo "version:"
105    $tar --version
106  fi
107  ret=$?
108fi
109
110if [ $ret -eq 0 ]; then
111  (exit 0)
112else
113  echo "No suitable tar program found."
114  exit 1
115fi
116
117
118
119# Try to find a suitable make
120# If the MAKE environment var is set, use that.
121# otherwise, try to find gmake, and then make.
122# If no make is found, then just execute the necessary commands.
123
124# XXX For some reason, make is building all the docs every time.  This
125# is an annoying source of bugs. Figure out why this happens.
126MAKE=NOMAKE
127
128if [ "x$MAKE" = "x" ]; then
129  make=`which gmake 2>&1`
130  if [ $? -eq 0 ] && [ -x "$make" ]; then
131    (exit 0)
132  else
133    make=`which make 2>&1`
134    if [ $? -eq 0 ] && [ -x "$make" ]; then
135      (exit 0)
136    else
137      make=NOMAKE
138    fi
139  fi
140else
141  make="$MAKE"
142fi
143
144if [ -x "$make" ]; then
145  (exit 0)
146else
147  # echo "Installing without make. This may fail." >&2
148  make=NOMAKE
149fi
150
151# If there's no bash, then don't even try to clean
152if [ -x "/bin/bash" ]; then
153  (exit 0)
154else
155  clean="no"
156fi
157
158node_version=`"$node" --version 2>&1`
159ret=$?
160if [ $ret -ne 0 ]; then
161  echo "You need node to run this program." >&2
162  echo "node --version reports: $node_version" >&2
163  echo "with exit code = $ret" >&2
164  echo "Please install node before continuing." >&2
165  exit $ret
166fi
167
168t="${npm_install}"
169if [ -z "$t" ]; then
170  # switch based on node version.
171  # note that we can only use strict sh-compatible patterns here.
172  case $node_version in
173    0.[01234567].* | v0.[01234567].*)
174      echo "You are using an outdated and unsupported version of" >&2
175      echo "node ($node_version).  Please update node and try again." >&2
176      exit 99
177      ;;
178    *)
179      echo "install npm@latest"
180      t="latest"
181      ;;
182  esac
183fi
184
185# need to echo "" after, because Posix sed doesn't treat EOF
186# as an implied end of line.
187url=`(curl -SsL https://registry.npmjs.org/npm/$t; echo "") \
188     | sed -e 's/^.*tarball":"//' \
189     | sed -e 's/".*$//'`
190
191ret=$?
192if [ "x$url" = "x" ]; then
193  ret=125
194  # try without the -e arg to sed.
195  url=`(curl -SsL https://registry.npmjs.org/npm/$t; echo "") \
196       | sed 's/^.*tarball":"//' \
197       | sed 's/".*$//'`
198  ret=$?
199  if [ "x$url" = "x" ]; then
200    ret=125
201  fi
202fi
203if [ $ret -ne 0 ]; then
204  echo "Failed to get tarball url for npm/$t" >&2
205  exit $ret
206fi
207
208
209echo "fetching: $url" >&2
210
211cd "$TMP" \
212  && curl -SsL "$url" \
213     | $tar -xzf - \
214  && cd "$TMP"/* \
215  && (ret=0
216      if [ $ret -ne 0 ]; then
217        echo "Aborted 0.x cleanup.  Exiting." >&2
218        exit $ret
219      fi) \
220  && (if [ "x$configures" = "x" ]; then
221        (exit 0)
222      else
223        echo "./configure $configures"
224        echo "$configures" > npmrc
225      fi) \
226  && (if [ "$make" = "NOMAKE" ]; then
227        (exit 0)
228      elif "$make" uninstall install; then
229        (exit 0)
230      else
231        make="NOMAKE"
232      fi
233      if [ "$make" = "NOMAKE" ]; then
234        "$node" bin/npm-cli.js rm npm -gf
235        "$node" bin/npm-cli.js install -gf $("$node" bin/npm-cli.js pack | tail -1)
236      fi) \
237  && cd "$BACK" \
238  && rm -rf "$TMP" \
239  && echo "It worked"
240
241ret=$?
242if [ $ret -ne 0 ]; then
243  echo "It failed" >&2
244fi
245exit $ret
246