Make serve-docs script more robust

* Make quit & reload actually kill the server, to prevent bind errors.
* Added an arg to bind to $HOSTNAME, instead of just localhost, for
  ease of code review.
* Makes option parsing a little more robust.
* Moves "build the jekyll tree" out of the "serve forever" loop.

PiperOrigin-RevId: 153840306
diff --git a/scripts/serve-docs.sh b/scripts/serve-docs.sh
index 4360653..27d1577 100755
--- a/scripts/serve-docs.sh
+++ b/scripts/serve-docs.sh
@@ -15,88 +15,129 @@
 
 set -eu
 
-if [ "${1-}" == "help" ]; then
+usage() {
   cat <<EOF
-Usage:
-$0 [port]
-     Builds docs and starts a web server serving docs on localhost:port
-     Default port is 12345.
-$0 <target directory> [<serving prefix>]
-     Builds docs as static web pages in <target directory>.
-     Replaces absolute paths in the resulting HTML with <serving prefix>,
-     or, if it is not specified, with <target directory>.
+Usage: $0 [--port 12345] [--target DIR [PREFIX]] [--share]
+ --port [port]
+     Builds docs and starts a web server serving docs on localhost:port. Default
+     port is 12345.
+ --target <target directory> [<serving prefix>]
+     Builds docs as static web pages in <target directory>. Replaces absolute
+     paths in the resulting HTML with <serving prefix>, or, if it is not
+     specified, with <target directory>.
+ --share
+     Binds jekyll to the machine's hostname, instead of localhost (useful for
+     review).
+ --help
+     This message.
 EOF
-  exit 0
-fi
+}
 
-if [[ "${1-}" == [0-9]* ]]; then
-  readonly PORT=$1
-  readonly TARGET=''
-else
-  readonly PORT=${1-12345}
-  readonly TARGET=${1-}
-fi
+HOST=localhost
+PORT=12345
+TARGET=
+SERVING_PREFIX=
+while [[ $# -gt 0 ]]
+do
+  key="$1"
+  case $key in
+    --port)
+      PORT="$2"
+      shift
+      ;;
+    --share)
+      HOST="$HOSTNAME"
+      ;;
+    --target)
+      TARGET="$2"
+      shift
+      SERVING_PREFIX="${2:-}"
+      build_static
+      exit 0
+      ;;
+    --help|help)
+      usage
+      exit 0
+      ;;
+    *)
+      usage
+      exit 1
+  esac
+  shift
+done
 
 readonly WORKING_DIR=$(mktemp -d)
-readonly SERVING_PREFIX=${2-$TARGET}
 
-function check {
+check() {
   which $1 > /dev/null || (echo "$1 not installed. Please install $1."; exit 1)
 }
 
-function build_and_serve {
+build_tree() {
   bazel build //site:jekyll-tree.tar
   rm -rf $WORKING_DIR/*
   tar -xf "$(bazel info bazel-genfiles)/site/jekyll-tree.tar" -C $WORKING_DIR
-
-  pkill -9 jekyll || true
-
-  if [ -z "$TARGET" ]; then
-    echo "Serving bazel.build site at port $PORT"
-    jekyll serve --detach --quiet --port $PORT --source $WORKING_DIR
-  else
-    TMP_TARGET=$(mktemp -d)
-    jekyll build --source $WORKING_DIR --destination "$TMP_TARGET"
-    REPLACEMENT=$(echo $SERVING_PREFIX | sed s/\\//\\\\\\//g)
-    find $TMP_TARGET -name '*.html' | xargs sed -i s/href=\\\"\\//href=\"$REPLACEMENT\\//g
-    find $TMP_TARGET -name '*.html' | xargs sed -i s/src=\\\"\\//src=\"$REPLACEMENT\\//g
-    cp -R $TMP_TARGET/* $TARGET
-    echo "Static pages copied to $TARGET"
-    echo "Should be served from $SERVING_PREFIX"
-  fi
 }
 
-function main {
+build_static() {
+  build_tree
+  TMP_TARGET=$(mktemp -d)
+  jekyll build --source $WORKING_DIR --destination "$TMP_TARGET"
+  REPLACEMENT=$(echo $SERVING_PREFIX | sed s/\\//\\\\\\//g)
+  find $TMP_TARGET -name '*.html' | xargs sed -i s/href=\\\"\\//href=\"$REPLACEMENT\\//g
+  find $TMP_TARGET -name '*.html' | xargs sed -i s/src=\\\"\\//src=\"$REPLACEMENT\\//g
+  cp -R $TMP_TARGET/* $TARGET
+  echo "Static pages copied to $TARGET"
+  echo "Should be served from $SERVING_PREFIX"
+}
+
+build_and_serve() {
+  build_tree
+  echo "Serving bazel.build site at $HOST:$PORT"
+  jekyll serve --host "$HOST" --detach --quiet --port "$PORT" --source "$WORKING_DIR"
+}
+
+main() {
   check jekyll
 
   old_version="Jekyll 0.11.2"
-  if expr match "$(jekyll --version)" "$old_version"; then
+  if expr match "$(jekyll --version)" "$old_version" > /dev/null; then
     # The ancient version that apt-get has.
     echo "ERROR: Running with an old version of Jekyll, update " \
       "to 2.5.3 with \`sudo gem install jekyll -v 2.5.3\`"
     exit 1
   fi
 
-  build_and_serve
+  kill_jekyll
 
-  echo "Type q to quit, r to rebuild docs and restart jekyll"
   while true; do
+    build_and_serve
 
+    echo "Type q to quit, r to rebuild docs and restart jekyll"
     read -n 1 -s user_input
     if [ "$user_input" == "q" ]; then
+      kill_jekyll
       echo "Quitting"
       exit 0
     elif [ "$user_input" == "r" ]; then
+      kill_jekyll
       echo "Rebuilding docs and restarting jekyll"
-      build_and_serve
-      echo "Rebuilt docs and restarted jekyll"
     fi
   done
 }
 
-function cleanup {
+kill_jekyll() {
+  pid="$(lsof "-tiTCP:$PORT" -sTCP:LISTEN)" || true
+  if [ ! -z "$pid" ]; then
+     kill "$pid"
+  fi
+  # I found I got bind errors sometimes if I didn't wait a second for the server to
+  # actually shut down.
+  sleep 2
+}
+
+cleanup() {
   rm -rf $WORKING_DIR
-  pkill -9 jekyll
+  kill_jekyll
 }
 trap cleanup EXIT