Extract docker-build logic into its own file.

To prepare for invoking it on ARM boards and GCE.

Test: build
Bug: 148642775 Clean up the crosvm build

Change-Id: Icaedd3340ca74a2f647e48a622a4edea73bc5ebf
Signed-off-by: Iliyan Malchev <malchev@google.com>
diff --git a/rebuild-docker.sh b/rebuild-docker.sh
new file mode 100755
index 0000000..ab9dc13
--- /dev/null
+++ b/rebuild-docker.sh
@@ -0,0 +1,140 @@
+#!/bin/bash -r
+
+function container_exists() {
+  [[ $(docker ps -a --filter "name=^/$1$" --format '{{.Names}}') == $1 ]] && echo $1;
+}
+
+# inputs
+# $1 = image name
+# $2 = container name
+# $3 = architecture (x86_64 or aarch64)
+# $4 = user name
+# $5 = user ID
+# $6 = persistent?
+# $7 = path to sources dir
+# $8 = path to working dir
+# $9 = path to output dir
+# $10 = reuse image/container? (0: no reuse; 1: reuse image; 2: reuse container)
+# $11 = build image (when reuse = 0)
+# $11 = path to Dockerfile
+# $12 = path to docker context dir
+# $13 = docker_flags_len
+# $14 = (docker_flags)
+# $15 = _prepare_source_len
+# $16 = (_prepare_source)
+function build_with_docker() {
+  set -o errexit
+  set -x
+
+  local -a _docker_target=( ${1} )
+  local _container_name=${2}
+  local _arch=${3}
+  local _docker_image=${1}_${_arch}
+  local _user=${4}
+  local _uid=${5}
+  local _persistent=${6}
+
+  if [[ ${_persistent} -eq 1 ]]; then
+    _docker_image=${1}_${_arch}_persistent
+  fi
+  local _docker_source=
+  if [ "${7}" != 'x' ]; then
+    _docker_source="-v ${7#x}:/source:rw"
+  fi
+  local _docker_working=
+  if [ "${8}" != 'x' ]; then
+    _docker_working="-v ${8#x}:/working:rw"
+  fi
+  local _docker_output=
+  if [ "${9}" != 'x' ]; then
+    _docker_output="-v ${9#x}:/output:rw"
+  fi
+  local _reuse=${10}
+  local _build_image=${11}
+  local _dockerfile=${12}
+  local _docker_context=${13}
+  shift 13
+  local -a _args=("$@")
+  local -i _docker_flags_len=${_args[0]}
+  local -a _docker_flags=("${_args[@]:1:$_docker_flags_len}")
+  local -i _prepare_source_len=${_args[(_docker_flags_len+1)]}
+  local -a _prepare_source=("${_args[@]:(_docker_flags_len+2):_prepare_source_len}")
+
+  local _build_or_retry=${_arch}_retry
+
+  if [[ ${_reuse} -ne 1 ]]; then
+    _build_or_retry=${_arch}_build
+    if [[ ${_persistent} -eq 1 ]]; then
+      _docker_target+=("${_docker_target[0]}_persistent")
+    fi
+    if [[ ${_build_image} -eq 1 ]]; then
+      if [[ ${_arch} == aarch64 ]]; then
+        export DOCKER_CLI_EXPERIMENTAL=enabled
+        docker buildx create --name docker_vmm_${_arch}_builder --platform linux/arm64 --use
+        for _target in ${_docker_target[@]}; do
+          docker buildx build \
+            --platform ${map_uname_to_docker_builder_arch[${_arch}]} \
+            --target ${_target} \
+            -f ${_dockerfile} \
+            -t ${_docker_image}:latest \
+            ${_docker_context} \
+            --build-arg USER=${_user} \
+            --build-arg UID=${_uid} --load
+        done
+        docker buildx rm docker_vmm_${_arch}_builder
+        unset DOCKER_CLI_EXPERIMENTAL
+      else
+        for _target in ${_docker_target[@]}; do
+          docker build \
+            -f ${_dockerfile} \
+            --target ${_target} \
+            -t ${_docker_image}:latest \
+            ${_docker_context} \
+            --build-arg USER=${_user} \
+            --build-arg UID=${_uid}
+        done
+      fi
+    fi
+    if [[ ${_persistent} -eq 1 ]]; then
+      if [[ -n "$(container_exists ${_container_name})" ]]; then
+        docker rm -f ${_container_name}
+      fi
+      docker run -d \
+        --privileged \
+        --name ${_container_name} \
+        -h ${_container_name} \
+        ${_docker_source} \
+        ${_docker_working} \
+        ${_docker_output} \
+        -v /sys/fs/cgroup:/sys/fs/cgroup:ro \
+        ${_docker_image}:latest
+    fi
+#  else
+#    # If we are reusing the docker image, then we cannot change the target
+#    # architecture (though we can change the persistence) of the container.
+#    echo TODO
+  fi
+
+  if [[ ${_persistent} -eq 1 ]]; then
+    if [[ "$(docker inspect --format='{{.State.Status}}' ${_container_name})" == "paused" ]]; then
+      docker unpause ${_container_name}
+    fi
+    docker exec -it \
+      --user ${_user} \
+      ${_docker_flags[@]} \
+      ${_container_name} \
+      /static/rebuild-internal.sh ${_prepare_source[@]} ${_build_or_retry}
+    docker pause ${_container_name}
+  else
+    docker run -it --rm \
+      --user ${_user} \
+      ${_docker_flags[@]} \
+      ${_docker_source} \
+      ${_docker_working} \
+      ${_docker_output} \
+      ${_docker_image}:latest \
+      /static/rebuild-internal.sh ${_prepare_source[@]} ${_build_or_retry}
+  fi
+}
+
+build_with_docker $@
diff --git a/rebuild.sh b/rebuild.sh
index 5378f3f..2e66863 100755
--- a/rebuild.sh
+++ b/rebuild.sh
@@ -63,6 +63,153 @@
   [[ $(docker ps -a --filter "name=^/$1$" --format '{{.Names}}') == $1 ]] && echo $1;
 }
 
+# inputs
+# $1 = FLAGS_docker_image
+# $2 = FLAGS_docker_container
+# $3 = FLAGS_docker_arch
+# $4 = FLAGS_docker_user
+# $5 = FLAGS_docker_uid
+# $6 = FLAGS_docker_persistent
+# $7 = FLAGS_docker_source
+# $8 = FLAGS_docker_working
+# $9 = FLAGS_docker_output
+# $10 = _reuse
+# $11 = docker_flags
+# $12 = _prepare_source
+# $13 = USE
+build_locally_using_docker() {
+  if [[ -z "${FLAGS_docker_image}" ]]; then
+    echo Option --docker_image must not be empty 1>&1
+    fail=1
+  fi
+  if [[ -z "${FLAGS_docker_container}" ]]; then
+    echo Options --docker_container must not be empty 1>&2
+    fail=1
+  fi
+  case "${FLAGS_docker_arch}" in
+    aarch64) ;;
+    x86_64) ;;
+    *) echo Invalid value ${FLAGS_docker_arch} for --docker_arch 1>&2
+      fail=1
+      ;;
+  esac
+  if [[ -z "${FLAGS_docker_user}" ]]; then
+    echo Options --docker_user must not be empty 1>&2
+    fail=1
+  fi
+  if [[ -z "${FLAGS_docker_uid}" ]]; then
+    echo Options --docker_uid must not be empty 1>&2
+    fail=1
+  fi
+  # Volume mapping are specified only when a container is created.  With
+  # --reuse, an already-created persistent container is reused, which implies
+  # that we cannot change the volume maps.  For non-persistent containers, we
+  # use docker run, which creates and runs the continer in one step; in that
+  # case, we must pass the same values for --docker_source and --docker_output
+  # that we passed when we ran the non-persistent continer the first time.
+  if [[ ${_reuse} -eq 1 && ${FLAGS_docker_persistent} -eq ${FLAGS_TRUE} ]]; then
+    if [ -n "${FLAGS_docker_source}" ]; then
+      echo Option --docker_source may not be specified with --reuse 1>&2
+      fail=1
+    fi
+    if [ -n "${FLAGS_docker_working}" ]; then
+      echo Option --docker_working may not be specified with --reuse 1>&2
+      fail=1
+    fi
+  fi
+  if [[ "${fail}" -ne 0 ]]; then
+    exit "${fail}"
+  fi
+  local _docker_source=
+  if [ -n "${FLAGS_docker_source}" ]; then
+    _docker_source="-v ${FLAGS_docker_source}:/source:rw"
+  fi
+  local _docker_working=
+  if [ -n "${FLAGS_docker_working}" ]; then
+    _docker_working="-v ${FLAGS_docker_working}:/working:rw"
+  fi
+  local _docker_output=${FLAGS_docker_output}
+  if [[ "${_docker_output}" == "${ANDROID_BUILD_TOP}/device/google/cuttlefish_vmm/$(uname -m)-linux-gnu" && \
+        "$(uname -m)" != ${FLAGS_docker_arch} ]]; then
+    _docker_output="${ANDROID_BUILD_TOP}/device/google/cuttlefish_vmm/${FLAGS_docker_arch}-linux-gnu"
+  fi
+  local _docker_image=${FLAGS_docker_image}_${FLAGS_docker_arch};
+  if [[ ${FLAGS_docker_persistent} -eq ${FLAGS_TRUE} ]]; then
+    _docker_image=${FLAGS_docker_image}_${FLAGS_docker_arch}_persistent;
+  fi
+  local _build_or_retry=${FLAGS_docker_arch}_retry
+  if [[ ${_reuse} -eq 0 ]]; then
+    _build_or_retry=${FLAGS_docker_arch}_build
+    local _docker_target=()
+    _docker_target+=("${FLAGS_docker_image}");
+    if [[ ${FLAGS_docker_persistent} -eq ${FLAGS_TRUE} ]]; then
+      _docker_target+=("${FLAGS_docker_image}_persistent");
+    fi
+    if [[ ${FLAGS_docker_build_image} -eq ${FLAGS_TRUE} ]]; then
+      if [[ ${FLAGS_docker_arch} == aarch64 ]]; then
+        export DOCKER_CLI_EXPERIMENTAL=enabled
+        docker buildx create --name docker_vmm_${FLAGS_docker_arch}_builder --platform linux/arm64 --use
+        for _target in ${_docker_target[@]}; do
+          docker buildx build \
+            --platform linux/arm64 \
+            --target ${_target} \
+            -f ${DIR}/Dockerfile \
+            -t ${_docker_image}:latest \
+            ${DIR} \
+            --build-arg USER=${FLAGS_docker_user} \
+            --build-arg UID=${FLAGS_docker_uid} --load
+        done
+        docker buildx rm docker_vmm_${FLAGS_docker_arch}_builder
+        unset DOCKER_CLI_EXPERIMENTAL
+      else
+        for _target in ${_docker_target[@]}; do
+          docker build \
+            -f ${DIR}/Dockerfile \
+            --target ${_target} \
+            -t ${_docker_image}:latest \
+            ${DIR} \
+            --build-arg USER=${FLAGS_docker_user} \
+            --build-arg UID=${FLAGS_docker_uid}
+        done
+      fi
+    fi
+    if [[ ${FLAGS_docker_persistent} -eq ${FLAGS_TRUE} ]]; then
+      if [[ -n "$(container_exists ${FLAGS_docker_container})" ]]; then
+        docker rm -f ${FLAGS_docker_container}
+      fi
+      docker run -d \
+        --privileged \
+        --name ${FLAGS_docker_container} \
+        -h ${FLAGS_docker_container} \
+        ${_docker_source} \
+        ${_docker_working} \
+        -v "${_docker_output}":/output:rw \
+        -v /sys/fs/cgroup:/sys/fs/cgroup:ro \
+        ${_docker_image}:latest
+    fi
+  fi
+  if [[ ${FLAGS_docker_persistent} -eq ${FLAGS_TRUE} ]]; then
+    if [[ "$(docker inspect --format='{{.State.Status}}' ${FLAGS_docker_container})" == "paused" ]]; then
+      docker unpause ${FLAGS_docker_container}
+    fi
+    docker exec -it \
+      --user ${FLAGS_docker_user} \
+      ${docker_flags[@]} \
+      ${FLAGS_docker_container} \
+      /static/rebuild-internal.sh ${_prepare_source[@]} ${_build_or_retry}
+    docker pause ${FLAGS_docker_container}
+  else
+    docker run -it --rm \
+      --user ${FLAGS_docker_user} \
+      ${docker_flags[@]} \
+      ${_docker_source} \
+      ${_docker_working} \
+      -v "${_docker_output}":/output:rw \
+      ${_docker_image}:latest \
+      /static/rebuild-internal.sh ${_prepare_source[@]} ${_build_or_retry}
+  fi
+}
+
 function build_on_gce() {
   if [[ -z "${FLAGS_gce_instance}" ]]; then
     echo Must specify instance 1>&2
@@ -163,139 +310,6 @@
     "${ANDROID_BUILD_TOP}/device/google/cuttlefish_vmm"
 }
 
-build_locally_using_docker() {
-  if [[ -z "${FLAGS_docker_image}" ]]; then
-    echo Option --docker_image must not be empty 1>&1
-    fail=1
-  fi
-  if [[ -z "${FLAGS_docker_container}" ]]; then
-    echo Options --docker_container must not be empty 1>&2
-    fail=1
-  fi
-  case "${FLAGS_docker_arch}" in
-    aarch64) ;;
-    x86_64) ;;
-    *) echo Invalid value ${FLAGS_docker_arch} for --docker_arch 1>&2
-      fail=1
-      ;;
-  esac
-  if [[ -z "${FLAGS_docker_user}" ]]; then
-    echo Options --docker_user must not be empty 1>&2
-    fail=1
-  fi
-  if [[ -z "${FLAGS_docker_uid}" ]]; then
-    echo Options --docker_uid must not be empty 1>&2
-    fail=1
-  fi
-  # Volume mapping are specified only when a container is created.  With
-  # --reuse, an already-created persistent container is reused, which implies
-  # that we cannot change the volume maps.  For non-persistent containers, we
-  # use docker run, which creates and runs the continer in one step; in that
-  # case, we must pass the same values for --docker_source and --docker_output
-  # that we passed when we ran the non-persistent continer the first time.
-  if [[ ${_reuse} -eq 1 && ${FLAGS_docker_persistent} -eq ${FLAGS_TRUE} ]]; then
-    if [ -n "${FLAGS_docker_source}" ]; then
-      echo Option --docker_source may not be specified with --reuse 1>&2
-      fail=1
-    fi
-    if [ -n "${FLAGS_docker_working}" ]; then
-      echo Option --docker_working may not be specified with --reuse 1>&2
-      fail=1
-    fi
-  fi
-  if [[ "${fail}" -ne 0 ]]; then
-    exit "${fail}"
-  fi
-  _docker_source=
-  if [ -n "${FLAGS_docker_source}" ]; then
-    _docker_source="-v ${FLAGS_docker_source}:/source:rw"
-  fi
-  _docker_working=
-  if [ -n "${FLAGS_docker_working}" ]; then
-    _docker_working="-v ${FLAGS_docker_working}:/working:rw"
-  fi
-  local _docker_output=${FLAGS_docker_output}
-  if [[ "${_docker_output}" == "${ANDROID_BUILD_TOP}/device/google/cuttlefish_vmm/$(uname -m)-linux-gnu" && \
-        "$(uname -m)" != ${FLAGS_docker_arch} ]]; then
-    _docker_output="${ANDROID_BUILD_TOP}/device/google/cuttlefish_vmm/${FLAGS_docker_arch}-linux-gnu"
-  fi
-  local _docker_image=${FLAGS_docker_image}_${FLAGS_docker_arch};
-  if [[ ${FLAGS_docker_persistent} -eq ${FLAGS_TRUE} ]]; then
-    _docker_image=${FLAGS_docker_image}_${FLAGS_docker_arch}_persistent;
-  fi
-  local _build_or_retry=${FLAGS_docker_arch}_retry
-  if [[ ${_reuse} -eq 0 ]]; then
-    _build_or_retry=${FLAGS_docker_arch}_build
-    local _docker_target=()
-    _docker_target+=("${FLAGS_docker_image}");
-    if [[ ${FLAGS_docker_persistent} -eq ${FLAGS_TRUE} ]]; then
-      _docker_target+=("${FLAGS_docker_image}_persistent");
-    fi
-    if [[ ${FLAGS_docker_build_image} -eq ${FLAGS_TRUE} ]]; then
-      if [[ ${FLAGS_docker_arch} == aarch64 ]]; then
-        export DOCKER_CLI_EXPERIMENTAL=enabled
-        docker buildx create --name docker_vmm_${FLAGS_docker_arch}_builder --platform linux/arm64 --use
-        for _target in ${_docker_target[@]}; do
-          docker buildx build \
-            --platform linux/arm64 \
-            --target ${_target} \
-            -f ${DIR}/Dockerfile \
-            -t ${_docker_image}:latest \
-            ${DIR} \
-            --build-arg USER=${FLAGS_docker_user} \
-            --build-arg UID=${FLAGS_docker_uid} --load
-        done
-        docker buildx rm docker_vmm_${FLAGS_docker_arch}_builder
-        unset DOCKER_CLI_EXPERIMENTAL
-      else
-        for _target in ${_docker_target[@]}; do
-          docker build \
-            -f ${DIR}/Dockerfile \
-            --target ${_target} \
-            -t ${_docker_image}:latest \
-            ${DIR} \
-            --build-arg USER=${FLAGS_docker_user} \
-            --build-arg UID=${FLAGS_docker_uid}
-        done
-      fi
-    fi
-    if [[ ${FLAGS_docker_persistent} -eq ${FLAGS_TRUE} ]]; then
-      if [[ -n "$(container_exists ${FLAGS_docker_container})" ]]; then
-        docker rm -f ${FLAGS_docker_container}
-      fi
-      docker run -d \
-        --privileged \
-        --name ${FLAGS_docker_container} \
-        -h ${FLAGS_docker_container} \
-        ${_docker_source} \
-        ${_docker_working} \
-        -v "${_docker_output}":/output:rw \
-        -v /sys/fs/cgroup:/sys/fs/cgroup:ro \
-        ${_docker_image}:latest
-    fi
-  fi
-  if [[ ${FLAGS_docker_persistent} -eq ${FLAGS_TRUE} ]]; then
-    if [[ "$(docker inspect --format='{{.State.Status}}' ${FLAGS_docker_container})" == "paused" ]]; then
-      docker unpause ${FLAGS_docker_container}
-    fi
-    docker exec -it \
-      --user ${FLAGS_docker_user} \
-      ${docker_flags[@]} \
-      ${FLAGS_docker_container} \
-      /static/rebuild-internal.sh ${_prepare_source[@]} ${_build_or_retry}
-    docker pause ${FLAGS_docker_container}
-  else
-    docker run -it --rm \
-      --user ${FLAGS_docker_user} \
-      ${docker_flags[@]} \
-      ${_docker_source} \
-      ${_docker_working} \
-      -v "${_docker_output}":/output:rw \
-      ${_docker_image}:latest \
-      /static/rebuild-internal.sh ${_prepare_source[@]} ${_build_or_retry}
-  fi
-}
-
 main() {
   set -o errexit
   set -x