op-replay-clipper (starpilot-gpu)
Installation
docker pull git.vae.me/zikeji/op-replay-clipper:starpilot-gpusha256:6cc2652f8a4afd367357b2d1706fdaf982d59fa3cba2e570db06d07be6cd7932Image layers
| ARG RELEASE |
| ARG LAUNCHPAD_BUILD_ARCH |
| LABEL org.opencontainers.image.ref.name=ubuntu |
| LABEL org.opencontainers.image.version=22.04 |
| ADD file:3bd10da0673e2e72cb06a1f64a9df49a36341df39b0f762e3d1b38ee4de296fa in / |
| CMD ["/bin/bash"] |
| ENV NVARCH=x86_64 |
| ENV NVIDIA_REQUIRE_CUDA=cuda>=12.4 brand=tesla,driver>=470,driver<471 brand=unknown,driver>=470,driver<471 brand=nvidia,driver>=470,driver<471 brand=nvidiartx,driver>=470,driver<471 brand=geforce,driver>=470,driver<471 brand=geforcertx,driver>=470,driver<471 brand=quadro,driver>=470,driver<471 brand=quadrortx,driver>=470,driver<471 brand=titan,driver>=470,driver<471 brand=titanrtx,driver>=470,driver<471 brand=tesla,driver>=525,driver<526 brand=unknown,driver>=525,driver<526 brand=nvidia,driver>=525,driver<526 brand=nvidiartx,driver>=525,driver<526 brand=geforce,driver>=525,driver<526 brand=geforcertx,driver>=525,driver<526 brand=quadro,driver>=525,driver<526 brand=quadrortx,driver>=525,driver<526 brand=titan,driver>=525,driver<526 brand=titanrtx,driver>=525,driver<526 brand=tesla,driver>=535,driver<536 brand=unknown,driver>=535,driver<536 brand=nvidia,driver>=535,driver<536 brand=nvidiartx,driver>=535,driver<536 brand=geforce,driver>=535,driver<536 brand=geforcertx,driver>=535,driver<536 brand=quadro,driver>=535,driver<536 brand=quadrortx,driver>=535,driver<536 brand=titan,driver>=535,driver<536 brand=titanrtx,driver>=535,driver<536 |
| ENV NV_CUDA_CUDART_VERSION=12.4.127-1 |
| ENV NV_CUDA_COMPAT_PACKAGE=cuda-compat-12-4 |
| ARG TARGETARCH |
| LABEL maintainer=NVIDIA CORPORATION <cudatools@nvidia.com> |
| RUN |1 TARGETARCH=amd64 /bin/sh -c apt-get update && apt-get install -y --no-install-recommends gnupg2 curl ca-certificates && curl -fsSLO https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/${NVARCH}/cuda-keyring_1.1-1_all.deb && dpkg -i cuda-keyring_1.1-1_all.deb && apt-get purge --autoremove -y curl && rm -rf /var/lib/apt/lists/* # buildkit |
| ENV CUDA_VERSION=12.4.1 |
| RUN |1 TARGETARCH=amd64 /bin/sh -c apt-get update && apt-get install -y --no-install-recommends cuda-cudart-12-4=${NV_CUDA_CUDART_VERSION} ${NV_CUDA_COMPAT_PACKAGE} && rm -rf /var/lib/apt/lists/* # buildkit |
| RUN |1 TARGETARCH=amd64 /bin/sh -c echo "/usr/local/nvidia/lib" >> /etc/ld.so.conf.d/nvidia.conf && echo "/usr/local/nvidia/lib64" >> /etc/ld.so.conf.d/nvidia.conf # buildkit |
| ENV PATH=/usr/local/nvidia/bin:/usr/local/cuda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin |
| ENV LD_LIBRARY_PATH=/usr/local/nvidia/lib:/usr/local/nvidia/lib64 |
| COPY NGC-DL-CONTAINER-LICENSE / # buildkit |
| ENV NVIDIA_VISIBLE_DEVICES=all |
| ENV NVIDIA_DRIVER_CAPABILITIES=compute,utility |
| ENV NV_CUDA_LIB_VERSION=12.4.1-1 |
| ENV NV_NVTX_VERSION=12.4.127-1 |
| ENV NV_LIBNPP_VERSION=12.2.5.30-1 |
| ENV NV_LIBNPP_PACKAGE=libnpp-12-4=12.2.5.30-1 |
| ENV NV_LIBCUSPARSE_VERSION=12.3.1.170-1 |
| ENV NV_LIBCUBLAS_PACKAGE_NAME=libcublas-12-4 |
| ENV NV_LIBCUBLAS_VERSION=12.4.5.8-1 |
| ENV NV_LIBCUBLAS_PACKAGE=libcublas-12-4=12.4.5.8-1 |
| ENV NV_LIBNCCL_PACKAGE_NAME=libnccl2 |
| ENV NV_LIBNCCL_PACKAGE_VERSION=2.21.5-1 |
| ENV NCCL_VERSION=2.21.5-1 |
| ENV NV_LIBNCCL_PACKAGE=libnccl2=2.21.5-1+cuda12.4 |
| ARG TARGETARCH |
| LABEL maintainer=NVIDIA CORPORATION <cudatools@nvidia.com> |
| RUN |1 TARGETARCH=amd64 /bin/sh -c apt-get update && apt-get install -y --no-install-recommends cuda-libraries-12-4=${NV_CUDA_LIB_VERSION} ${NV_LIBNPP_PACKAGE} cuda-nvtx-12-4=${NV_NVTX_VERSION} libcusparse-12-4=${NV_LIBCUSPARSE_VERSION} ${NV_LIBCUBLAS_PACKAGE} ${NV_LIBNCCL_PACKAGE} && rm -rf /var/lib/apt/lists/* # buildkit |
| RUN |1 TARGETARCH=amd64 /bin/sh -c apt-mark hold ${NV_LIBCUBLAS_PACKAGE_NAME} ${NV_LIBNCCL_PACKAGE_NAME} # buildkit |
| COPY entrypoint.d/ /opt/nvidia/entrypoint.d/ # buildkit |
| COPY nvidia_entrypoint.sh /opt/nvidia/ # buildkit |
| ENV NVIDIA_PRODUCT_NAME=CUDA |
| ENTRYPOINT ["/opt/nvidia/nvidia_entrypoint.sh"] |
| ENV NV_CUDA_LIB_VERSION=12.4.1-1 |
| ENV NV_CUDA_CUDART_DEV_VERSION=12.4.127-1 |
| ENV NV_NVML_DEV_VERSION=12.4.127-1 |
| ENV NV_LIBCUSPARSE_DEV_VERSION=12.3.1.170-1 |
| ENV NV_LIBNPP_DEV_VERSION=12.2.5.30-1 |
| ENV NV_LIBNPP_DEV_PACKAGE=libnpp-dev-12-4=12.2.5.30-1 |
| ENV NV_LIBCUBLAS_DEV_VERSION=12.4.5.8-1 |
| ENV NV_LIBCUBLAS_DEV_PACKAGE_NAME=libcublas-dev-12-4 |
| ENV NV_LIBCUBLAS_DEV_PACKAGE=libcublas-dev-12-4=12.4.5.8-1 |
| ENV NV_CUDA_NSIGHT_COMPUTE_VERSION=12.4.1-1 |
| ENV NV_CUDA_NSIGHT_COMPUTE_DEV_PACKAGE=cuda-nsight-compute-12-4=12.4.1-1 |
| ENV NV_NVPROF_VERSION=12.4.127-1 |
| ENV NV_NVPROF_DEV_PACKAGE=cuda-nvprof-12-4=12.4.127-1 |
| ENV NV_LIBNCCL_DEV_PACKAGE_NAME=libnccl-dev |
| ENV NV_LIBNCCL_DEV_PACKAGE_VERSION=2.21.5-1 |
| ENV NCCL_VERSION=2.21.5-1 |
| ENV NV_LIBNCCL_DEV_PACKAGE=libnccl-dev=2.21.5-1+cuda12.4 |
| ARG TARGETARCH |
| LABEL maintainer=NVIDIA CORPORATION <cudatools@nvidia.com> |
| RUN |1 TARGETARCH=amd64 /bin/sh -c apt-get update && apt-get install -y --no-install-recommends cuda-cudart-dev-12-4=${NV_CUDA_CUDART_DEV_VERSION} cuda-command-line-tools-12-4=${NV_CUDA_LIB_VERSION} cuda-minimal-build-12-4=${NV_CUDA_LIB_VERSION} cuda-libraries-dev-12-4=${NV_CUDA_LIB_VERSION} cuda-nvml-dev-12-4=${NV_NVML_DEV_VERSION} ${NV_NVPROF_DEV_PACKAGE} ${NV_LIBNPP_DEV_PACKAGE} libcusparse-dev-12-4=${NV_LIBCUSPARSE_DEV_VERSION} ${NV_LIBCUBLAS_DEV_PACKAGE} ${NV_LIBNCCL_DEV_PACKAGE} ${NV_CUDA_NSIGHT_COMPUTE_DEV_PACKAGE} && rm -rf /var/lib/apt/lists/* # buildkit |
| RUN |1 TARGETARCH=amd64 /bin/sh -c apt-mark hold ${NV_LIBCUBLAS_DEV_PACKAGE_NAME} ${NV_LIBNCCL_DEV_PACKAGE_NAME} # buildkit |
| ENV LIBRARY_PATH=/usr/local/cuda/lib64/stubs |
| ENV NV_CUDNN_VERSION=9.1.0.70-1 |
| ENV NV_CUDNN_PACKAGE_NAME=libcudnn9-cuda-12 |
| ENV NV_CUDNN_PACKAGE=libcudnn9-cuda-12=9.1.0.70-1 |
| ENV NV_CUDNN_PACKAGE_DEV=libcudnn9-dev-cuda-12=9.1.0.70-1 |
| ARG TARGETARCH |
| LABEL maintainer=NVIDIA CORPORATION <cudatools@nvidia.com> |
| LABEL com.nvidia.cudnn.version=9.1.0.70-1 |
| RUN |1 TARGETARCH=amd64 /bin/sh -c apt-get update && apt-get install -y --no-install-recommends ${NV_CUDNN_PACKAGE} ${NV_CUDNN_PACKAGE_DEV} && apt-mark hold ${NV_CUDNN_PACKAGE_NAME} && rm -rf /var/lib/apt/lists/* # buildkit |
| ENV DEBIAN_FRONTEND=noninteractive |
| ENV PYTHONUNBUFFERED=1 |
| ENV LD_LIBRARY_PATH=/usr/local/nvidia/lib:/usr/local/nvidia/lib64:/usr/lib/x86_64-linux-gnu:/usr/local/nvidia/lib64:/usr/local/nvidia/bin |
| ENV NVIDIA_DRIVER_CAPABILITIES=all |
| RUN /bin/sh -c set -eux; apt-get update -qq && apt-get install -qqy --no-install-recommends curl; rm -rf /var/lib/apt/lists/*; TINI_VERSION=v0.19.0; TINI_ARCH="$(dpkg --print-architecture)"; curl -sSL -o /sbin/tini "https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-${TINI_ARCH}"; chmod +x /sbin/tini # buildkit |
| ENTRYPOINT ["/sbin/tini" "--"] |
| RUN /bin/sh -c apt-get update -qq && apt-get install -qqy build-essential cmake curl ffmpeg findutils g++ gcc git libavcodec-dev libcairo2-dev libfontconfig1 libgirepository1.0-dev libgl1 libglx-mesa0 libglib2.0-0 libopencv-dev libsm6 libsndfile1 libssl-dev libunistring-dev libxext6 libxrender1 sox unzip wget zip zstd && rm -rf /var/lib/apt/lists/* # buildkit |
| ENV PATH=/root/.pyenv/shims:/root/.pyenv/bin:/usr/local/nvidia/bin:/usr/local/cuda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin |
| RUN /bin/sh -c apt-get update -qq && apt-get install -qqy --no-install-recommends make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev xz-utils tk-dev libffi-dev liblzma-dev git ca-certificates && rm -rf /var/lib/apt/lists/* # buildkit |
| RUN /bin/sh -c curl -s -S -L https://raw.githubusercontent.com/pyenv/pyenv-installer/master/bin/pyenv-installer | bash && git clone https://github.com/momo-lab/pyenv-install-latest.git "$(pyenv root)"/plugins/pyenv-install-latest && export PYTHON_CONFIGURE_OPTS='--enable-optimizations --with-lto' && export PYTHON_CFLAGS='-O3' && pyenv install-latest "3.12" && pyenv global $(pyenv install-latest --print "3.12") && pip install "wheel<1" # buildkit |
| RUN /bin/sh -c rm -rf /usr/bin/python3 && ln -s `realpath \`pyenv which python\`` /usr/bin/python3 && chmod +x /usr/bin/python3 # buildkit |
| RUN /bin/sh -c find / -type f -name "*python*.so" -printf "%h\n" | sort -u > /etc/ld.so.conf.d/cog.conf && ldconfig # buildkit |
| ENV OPENPILOT_BRANCH=StarPilot OPENPILOT_REPO_URL=https://github.com/firestar5683/StarPilot.git UV_BREAK_SYSTEM_PACKAGES=true |
| COPY /uv /uvx /usr/local/bin/ # buildkit |
| ENV UV_SYSTEM_PYTHON=true |
| ENV CFLAGS=-O3 -funroll-loops -fno-strict-aliasing -flto -S |
| RUN /bin/sh -c uv pip install --no-cache cog # buildkit |
| ENV CFLAGS= |
| COPY .cog/tmp/build20260616070349.991559/requirements.txt /tmp/requirements.txt # buildkit |
| ENV CFLAGS=-O3 -funroll-loops -fno-strict-aliasing -flto -S |
| RUN /bin/sh -c uv run pip install --cache-dir /root/.cache/pip -r /tmp/requirements.txt # buildkit |
| ENV CFLAGS= |
| RUN /bin/sh -c echo IyEvdXNyL2Jpbi9lbnYgYmFzaAoKc2V0IC1ldW8gcGlwZWZhaWwKCiMgU2hhcmVkIGJvb3RzdHJhcCBmb3IgRG9ja2VyL0NvZyBpbWFnZXMgdGhhdCBuZWVkIGEgd29ya2luZyBvcGVucGlsb3QgY2xpcCBlbnZpcm9ubWVudC4KIyBDQUNIRV9CVVNURVI6IDIwMjYtMDQtMDMtZmFjZWZ1c2lvbi1yZWJ1aWxkLXYzCgpBUFBfUk9PVD0iJHtBUFBfUk9PVDotJChwd2QpfSIKT1BFTlBJTE9UX1JPT1Q9IiR7T1BFTlBJTE9UX1JPT1Q6LS9ob21lL2JhdG1hbi9vcGVucGlsb3R9IgpPUEVOUElMT1RfUkVQT19VUkw9IiR7T1BFTlBJTE9UX1JFUE9fVVJMOi1odHRwczovL2dpdGh1Yi5jb20vY29tbWFhaS9vcGVucGlsb3QuZ2l0fSIKT1BFTlBJTE9UX0JSQU5DSD0iJHtPUEVOUElMT1RfQlJBTkNIOi1tYXN0ZXJ9IgpPUEVOUElMT1RfQ0xPTkVfREVQVEg9IiR7T1BFTlBJTE9UX0NMT05FX0RFUFRIOi0xfSIKRkFDRUZVU0lPTl9ST09UPSIke0ZBQ0VGVVNJT05fUk9PVDotJHtBUFBfUk9PVH0vLmNhY2hlL2ZhY2VmdXNpb259IgpGQUNFRlVTSU9OX1JFUE9fVVJMPSIke0ZBQ0VGVVNJT05fUkVQT19VUkw6LWh0dHBzOi8vZ2l0aHViLmNvbS9mYWNlZnVzaW9uL2ZhY2VmdXNpb24uZ2l0fSIKRkFDRUZVU0lPTl9DT01NSVQ9IiR7RkFDRUZVU0lPTl9DT01NSVQ6LTUxOTM2MGJjZDY1MDY3OTI3NTAyNGFhM2VkMTBlOGQ2NzM3MThiYjN9IgpGQUNFRlVTSU9OX1BZVEhPTl9WRVJTSU9OPSIke0ZBQ0VGVVNJT05fUFlUSE9OX1ZFUlNJT046LTMuMTJ9IgpGQUNFRlVTSU9OX1BSRVdBUk1fTU9ERUxTPSIke0ZBQ0VGVVNJT05fUFJFV0FSTV9NT0RFTFM6LTF9IgpGQUNFRlVTSU9OX1BSRVdBUk1fUkVUUklFUz0iJHtGQUNFRlVTSU9OX1BSRVdBUk1fUkVUUklFUzotM30iCkZBQ0VGVVNJT05fUFJFRkVUQ0hfRkFOXzY4XzU9IiR7RkFDRUZVU0lPTl9QUkVGRVRDSF9GQU5fNjhfNTotMX0iCkZBQ0VGVVNJT05fUFJVTkVfVkVOVj0iJHtGQUNFRlVTSU9OX1BSVU5FX1ZFTlY6LTF9IgpGQUNFRlVTSU9OX0hBUkRMSU5LX0RFRFVQRT0iJHtGQUNFRlVTSU9OX0hBUkRMSU5LX0RFRFVQRTotMX0iCkZBQ0VGVVNJT05fUFJVTkVfVU5VU0VEX1BBQ0tBR0VTPSIke0ZBQ0VGVVNJT05fUFJVTkVfVU5VU0VEX1BBQ0tBR0VTOi0xfSIKUkZfREVUUl9QUkVXQVJNX1dFSUdIVFM9IiR7UkZfREVUUl9QUkVXQVJNX1dFSUdIVFM6LTF9IgpSRl9ERVRSX1BSRVdBUk1fTU9ERUxfSURTPSIke1JGX0RFVFJfUFJFV0FSTV9NT0RFTF9JRFM6LXJmZGV0ci1zZWctcHJldmlld30iCmV4cG9ydCBSRl9ERVRSX1BSRVdBUk1fV0VJR0hUUyBSRl9ERVRSX1BSRVdBUk1fTU9ERUxfSURTCk9QRU5QSUxPVF9CVUlMRF9VSV9BU1NFVFM9IiR7T1BFTlBJTE9UX0JVSUxEX1VJX0FTU0VUUzotMX0iCk9QRU5QSUxPVF9JTlNUQUxMX1hfUlVOVElNRV9QQUNLQUdFUz0iJHtPUEVOUElMT1RfSU5TVEFMTF9YX1JVTlRJTUVfUEFDS0FHRVM6LTB9IgpPUEVOUElMT1RfTlZJRElBX0dMX1BBQ0tBR0U9IiR7T1BFTlBJTE9UX05WSURJQV9HTF9QQUNLQUdFLWxpYm52aWRpYS1nbC01ODAtc2VydmVyfSIKRkFDRUZVU0lPTl9PTk5YUlVOVElNRT0iJHtGQUNFRlVTSU9OX09OTlhSVU5USU1FOi1jdWRhfSIKU0NPTlNfSk9CUz0iJHtTQ09OU19KT0JTOi0kKGNvbW1hbmQgLXYgbnByb2MgPi9kZXYvbnVsbCAyPiYxICYmIG5wcm9jIHx8IGVjaG8gOCl9IgpCVUlMRF9UTVBESVI9IiR7QlVJTERfVE1QRElSOi0vdmFyL3RtcC9vcC1jbGlwcGVyLWJ1aWxkfSIKZXhwb3J0IERFQklBTl9GUk9OVEVORD0iJHtERUJJQU5fRlJPTlRFTkQ6LW5vbmludGVyYWN0aXZlfSIKCkFQVF9QQUNLQUdFUz0oCiAgYnVpbGQtZXNzZW50aWFsCiAgY21ha2UKICBqcQogIGZmbXBlZwogIGZha2V0aW1lCiAgZWF0bXlkYXRhCiAgaHRvcAogIGJjCiAgbmV0LXRvb2xzCiAgc3VkbwogIHdnZXQKICBjdXJsCiAgY2FwbnByb3RvCiAgZ2l0LWxmcwogIHR6ZGF0YQogIHpzdGQKICBnaXQKKQoKVUlfUlVOVElNRV9BUFRfUEFDS0FHRVM9KAogIHhzZXJ2ZXIteG9yZy1jb3JlCiAgbWVzYS11dGlscwogIHhzZXJ2ZXIteG9yZy12aWRlby1udmlkaWEtNTI1CikKClVJX0FQVF9QQUNLQUdFUz0oCiAgbGlieHJhbmRyLWRldgogIGxpYnhpbmVyYW1hLWRldgogIGxpYnhjdXJzb3ItZGV2CiAgbGlieGktZGV2CiAgbGlieGV4dC1kZXYKICBsaWJlZ2wxLW1lc2EtZGV2CiAgeG9yZy1kZXYKKQoKVUlfR1BVX1JVTlRJTUVfQVBUX1BBQ0tBR0VTPSgKICAiJHtPUEVOUElMT1RfTlZJRElBX0dMX1BBQ0tBR0V9IgopCgpsb2dfc3RlcCgpIHsKICBwcmludGYgJ1xuPT0+ICVzXG4nICIkMSIKfQoKY29uZmlndXJlX2J1aWxkX3RlbXBkaXIoKSB7CiAgbG9nX3N0ZXAgIkNvbmZpZ3VyaW5nIGJ1aWxkIHRlbXAgZGlyZWN0b3J5IgogIG1rZGlyIC1wICIke0JVSUxEX1RNUERJUn0iCiAgY2htb2QgMTc3NyAiJHtCVUlMRF9UTVBESVJ9IgogIGV4cG9ydCBUTVBESVI9IiR7QlVJTERfVE1QRElSfSIKICBleHBvcnQgVE1QPSIke0JVSUxEX1RNUERJUn0iCiAgZXhwb3J0IFRFTVA9IiR7QlVJTERfVE1QRElSfSIKICBleHBvcnQgWERHX0NBQ0hFX0hPTUU9IiR7QlVJTERfVE1QRElSfS94ZGctY2FjaGUiCiAgZXhwb3J0IFVWX0NBQ0hFX0RJUj0iJHtCVUlMRF9UTVBESVJ9L3V2LWNhY2hlIgogIGV4cG9ydCBQSVBfQ0FDSEVfRElSPSIke0JVSUxEX1RNUERJUn0vcGlwLWNhY2hlIgogIGV4cG9ydCBQSVBfTk9fQ0FDSEVfRElSPTEKICBleHBvcnQgVVZfTk9fQ0FDSEU9MQogIG1rZGlyIC1wICIke1hER19DQUNIRV9IT01FfSIgIiR7VVZfQ0FDSEVfRElSfSIgIiR7UElQX0NBQ0hFX0RJUn0iCn0KCnJlZGlyZWN0X3N5c3RlbV90bXAoKSB7CiAgbG9nX3N0ZXAgIlJlZGlyZWN0aW5nIC90bXAgdG8gYnVpbGQgdGVtcCBkaXJlY3RvcnkiCiAgcm0gLXJmIC90bXAvKgogIHJtZGlyIC90bXAKICBsbiAtcyAiJHtCVUlMRF9UTVBESVJ9IiAvdG1wCn0KCmluc3RhbGxfc3lzdGVtX3BhY2thZ2VzKCkgewogIGxvZ19zdGVwICJJbnN0YWxsaW5nIHN5c3RlbSBwYWNrYWdlcyIKICBhcHQtZ2V0IHVwZGF0ZSAteQogIGFwdC1nZXQgaW5zdGFsbCAteSAiJHtBUFRfUEFDS0FHRVNbQF19IgogIGlmIFtbICIke09QRU5QSUxPVF9CVUlMRF9VSV9BU1NFVFN9IiA9PSAiMSIgXV07IHRoZW4KICAgIGFwdC1nZXQgaW5zdGFsbCAteSAiJHtVSV9BUFRfUEFDS0FHRVNbQF19IgogICAgaWYgW1sgLW4gIiR7T1BFTlBJTE9UX05WSURJQV9HTF9QQUNLQUdFfSIgXV07IHRoZW4KICAgICAgYXB0LWdldCBpbnN0YWxsIC15ICIke1VJX0dQVV9SVU5USU1FX0FQVF9QQUNLQUdFU1tAXX0iCiAgICBmaQogICAgaWYgW1sgIiR7T1BFTlBJTE9UX0lOU1RBTExfWF9SVU5USU1FX1BBQ0tBR0VTfSIgPT0gIjEiIF1dOyB0aGVuCiAgICAgIGFwdC1nZXQgaW5zdGFsbCAteSAiJHtVSV9SVU5USU1FX0FQVF9QQUNLQUdFU1tAXX0iCiAgICBmaQogIGZpCn0KCnN5bmNfcHl0aG9uX252aWRpYV9ydW50aW1lX2xpYnMoKSB7CiAgbG9nX3N0ZXAgIkxpbmtpbmcgUHl0aG9uLXByb3ZpZGVkIE5WSURJQSBydW50aW1lIGxpYnJhcmllcyBpbnRvIHN5c3RlbSBsaWJyYXJ5IHBhdGgiCiAgcHl0aG9uIC0gPDwnUFknCmZyb20gX19mdXR1cmVfXyBpbXBvcnQgYW5ub3RhdGlvbnMKCmltcG9ydCBwYXRobGliCmltcG9ydCBzaXRlCgpzeXN0ZW1fbGliX2RpciA9IHBhdGhsaWIuUGF0aCgiL3Vzci9saWIveDg2XzY0LWxpbnV4LWdudSIpCmlmIG5vdCBzeXN0ZW1fbGliX2Rpci5leGlzdHMoKToKICAgIHJhaXNlIFN5c3RlbUV4aXQoMCkKCmZvciByb290IGluIHNpdGUuZ2V0c2l0ZXBhY2thZ2VzKCk6CiAgICBudmlkaWFfcm9vdCA9IHBhdGhsaWIuUGF0aChyb290KSAvICJudmlkaWEiCiAgICBpZiBub3QgbnZpZGlhX3Jvb3QuZXhpc3RzKCk6CiAgICAgICAgY29udGludWUKICAgIGZvciBsaWJfZGlyIGluIHNvcnRlZChwYXRoIGZvciBwYXRoIGluIG52aWRpYV9yb290Lml0ZXJkaXIoKSBpZiAocGF0aCAvICJsaWIiKS5leGlzdHMoKSk6CiAgICAgICAgZm9yIGxpYl9maWxlIGluIHNvcnRlZCgobGliX2RpciAvICJsaWIiKS5nbG9iKCJsaWIqLnNvKiIpKToKICAgICAgICAgICAgaWYgbGliX2ZpbGUuaXNfZGlyKCk6CiAgICAgICAgICAgICAgICBjb250aW51ZQogICAgICAgICAgICB0YXJnZXQgPSBzeXN0ZW1fbGliX2RpciAvIGxpYl9maWxlLm5hbWUKICAgICAgICAgICAgaWYgdGFyZ2V0LmV4aXN0cygpIG9yIHRhcmdldC5pc19zeW1saW5rKCk6CiAgICAgICAgICAgICAgICB0YXJnZXQudW5saW5rKCkKICAgICAgICAgICAgdGFyZ2V0LnN5bWxpbmtfdG8obGliX2ZpbGUpCiAgICAgICAgICAgIHByaW50KGYibGlua2VkIHt0YXJnZXR9IC0+IHtsaWJfZmlsZX0iLCBmbHVzaD1UcnVlKQpQWQp9Cgpjb25maWd1cmVfZ2l0X2xmcygpIHsKICBsb2dfc3RlcCAiQ2hlY2tpbmcgZ2l0LWxmcyBDTEkiCiAgZ2l0IGxmcyB2ZXJzaW9uCn0KCmNsb25lX2ZhY2VmdXNpb25fY2hlY2tvdXQoKSB7CiAgbG9nX3N0ZXAgIkNsb25pbmcgRmFjZUZ1c2lvbiBpbnRvICR7RkFDRUZVU0lPTl9ST09UfSIKICBybSAtcmYgIiR7RkFDRUZVU0lPTl9ST09UfSIKICBta2RpciAtcCAiJChkaXJuYW1lICIke0ZBQ0VGVVNJT05fUk9PVH0iKSIKICBnaXQgY2xvbmUgLS1maWx0ZXI9YmxvYjpub25lICIke0ZBQ0VGVVNJT05fUkVQT19VUkx9IiAiJHtGQUNFRlVTSU9OX1JPT1R9IgogIGlmIFtbIC1uICIke0ZBQ0VGVVNJT05fQ09NTUlUfSIgXV07IHRoZW4KICAgIGNkICIke0ZBQ0VGVVNJT05fUk9PVH0iCiAgICBnaXQgY2hlY2tvdXQgIiR7RkFDRUZVU0lPTl9DT01NSVR9IgogIGZpCn0KCmNsb25lX29wZW5waWxvdF9jaGVja291dCgpIHsKICBsb2dfc3RlcCAiQ2xvbmluZyBvcGVucGlsb3QgaW50byAke09QRU5QSUxPVF9ST09UfSIKICBybSAtcmYgIiR7T1BFTlBJTE9UX1JPT1R9IgogIGdpdCBjbG9uZSBcCiAgICAtLWJyYW5jaCAiJHtPUEVOUElMT1RfQlJBTkNIfSIgXAogICAgLS1kZXB0aCAiJHtPUEVOUElMT1RfQ0xPTkVfREVQVEh9IiBcCiAgICAtLWZpbHRlcj1ibG9iOm5vbmUgXAogICAgLS1yZWN1cnNlLXN1Ym1vZHVsZXMgXAogICAgLS1zaGFsbG93LXN1Ym1vZHVsZXMgXAogICAgLS1zaW5nbGUtYnJhbmNoIFwKICAgICIke09QRU5QSUxPVF9SRVBPX1VSTH0iIFwKICAgICIke09QRU5QSUxPVF9ST09UfSIKfQoKaW5zdGFsbF9vcGVucGlsb3RfZGVwZW5kZW5jaWVzKCkgewogIGxvZ19zdGVwICJJbnN0YWxsaW5nIG9wZW5waWxvdCBkZXBlbmRlbmNpZXMiCiAgY2QgIiR7T1BFTlBJTE9UX1JPT1R9IgoKICBpZiBbWyAteCAuL3Rvb2xzL3NldHVwX2RlcGVuZGVuY2llcy5zaCBdXTsgdGhlbgogICAgLi90b29scy9zZXR1cF9kZXBlbmRlbmNpZXMuc2gKICAgIHJldHVybgogIGZpCgogIGlmIFtbIC14IC4vdG9vbHMvdWJ1bnR1X3NldHVwLnNoIF1dOyB0aGVuCiAgICBJTlNUQUxMX0VYVFJBX1BBQ0tBR0VTPXllcyAuL3Rvb2xzL3VidW50dV9zZXR1cC5zaAogICAgLi90b29scy9pbnN0YWxsX3B5dGhvbl9kZXBlbmRlbmNpZXMuc2gKICAgIHJldHVybgogIGZpCgogIGVjaG8gIk5vIHN1cHBvcnRlZCBvcGVucGlsb3QgZGVwZW5kZW5jeSBzZXR1cCBzY3JpcHRzIGZvdW5kIiA+JjIKICBleGl0IDEKfQoKZW5zdXJlX3V2X29uX3BhdGgoKSB7CiAgaWYgW1sgISAteCAvcm9vdC8ubG9jYWwvYmluL3V2IF1dOyB0aGVuCiAgICBjdXJsIC1Mc1NmIGh0dHBzOi8vYXN0cmFsLnNoL3V2L2luc3RhbGwuc2ggfCBzaAogIGZpCiAgbG4gLXNmIC9yb290Ly5sb2NhbC9iaW4vdXYgL3Vzci9sb2NhbC9iaW4vdXYKICBleHBvcnQgUEFUSD0iL3Jvb3QvLmxvY2FsL2Jpbjoke1BBVEh9Igp9CgpwcmV3YXJtX3JmX2RldHJfd2VpZ2h0cygpIHsKICBpZiBbWyAiJHtSRl9ERVRSX1BSRVdBUk1fV0VJR0hUU30iICE9ICIxIiBdXTsgdGhlbgogICAgbG9nX3N0ZXAgIlNraXBwaW5nIFJGLURFVFIgd2VpZ2h0IHByZXdhcm0iCiAgICByZXR1cm4KICBmaQoKICBsb2dfc3RlcCAiUHJld2FybWluZyBSRi1ERVRSIHdlaWdodHMiCiAgbG9jYWwgd2VpZ2h0c19kaXI9IiR7UkZfREVUUl9XRUlHSFRTX0RJUjotfSIKICBpZiBbWyAteiAiJHt3ZWlnaHRzX2Rpcn0iIF1dOyB0aGVuCiAgICBpZiBbWyAiJHtBUFBfUk9PVH0iID09ICIvIiBdXTsgdGhlbgogICAgICB3ZWlnaHRzX2Rpcj0iL3NyYy8uY2FjaGUvcmZkZXRyIgogICAgZWxzZQogICAgICB3ZWlnaHRzX2Rpcj0iJHtBUFBfUk9PVH0vLmNhY2hlL3JmZGV0ciIKICAgIGZpCiAgZmkKICBta2RpciAtcCAiJHt3ZWlnaHRzX2Rpcn0iCiAgY2QgIiR7QVBQX1JPT1R9IgogIFJGX0RFVFJfV0VJR0hUU19ESVI9IiR7d2VpZ2h0c19kaXJ9IiBEUklWRVJfRkFDRV9CRU5DSE1BUktfUkZfREVUUl9ERVZJQ0U9Y3B1IHB5dGhvbiAtIDw8J1BZJwpmcm9tIF9fZnV0dXJlX18gaW1wb3J0IGFubm90YXRpb25zCgppbXBvcnQgb3MKZnJvbSBwYXRobGliIGltcG9ydCBQYXRoCgpmcm9tIHJmZGV0ciBpbXBvcnQgKAogICAgUkZERVRSU2VnMlhMYXJnZSwKICAgIFJGREVUUlNlZ0xhcmdlLAogICAgUkZERVRSU2VnTWVkaXVtLAogICAgUkZERVRSU2VnTmFubywKICAgIFJGREVUUlNlZ1ByZXZpZXcsCiAgICBSRkRFVFJTZWdTbWFsbCwKICAgIFJGREVUUlNlZ1hMYXJnZSwKKQoKbW9kZWxfaWRzID0gW21vZGVsX2lkLnN0cmlwKCkgZm9yIG1vZGVsX2lkIGluIG9zLmVudmlyb24uZ2V0KCJSRl9ERVRSX1BSRVdBUk1fTU9ERUxfSURTIiwgIiIpLnNwbGl0KCIsIikgaWYgbW9kZWxfaWQuc3RyaXAoKV0KaWYgbm90IG1vZGVsX2lkczoKICAgIHJhaXNlIFN5c3RlbUV4aXQoIlJGX0RFVFJfUFJFV0FSTV9NT0RFTF9JRFMgaXMgZW1wdHkiKQoKbW9kZWxfY2xhc3NlcyA9IHsKICAgICJyZmRldHItc2VnLXByZXZpZXciOiBSRkRFVFJTZWdQcmV2aWV3LAogICAgInJmZGV0ci1zZWctbmFubyI6IFJGREVUUlNlZ05hbm8sCiAgICAicmZkZXRyLXNlZy1zbWFsbCI6IFJGREVUUlNlZ1NtYWxsLAogICAgInJmZGV0ci1zZWctbWVkaXVtIjogUkZERVRSU2VnTWVkaXVtLAogICAgInJmZGV0ci1zZWctbGFyZ2UiOiBSRkRFVFJTZWdMYXJnZSwKICAgICJyZmRldHItc2VnLXhsYXJnZSI6IFJGREVUUlNlZ1hMYXJnZSwKICAgICJyZmRldHItc2VnLTJ4bGFyZ2UiOiBSRkRFVFJTZWcyWExhcmdlLAogICAgInJmZGV0ci1zZWcteHhsYXJnZSI6IFJGREVUUlNlZzJYTGFyZ2UsCn0Kd2VpZ2h0X2ZpbGVuYW1lcyA9IHsKICAgICJyZmRldHItc2VnLXByZXZpZXciOiAicmYtZGV0ci1zZWctcHJldmlldy5wdCIsCiAgICAicmZkZXRyLXNlZy1uYW5vIjogInJmLWRldHItc2VnLW5hbm8ucHQiLAogICAgInJmZGV0ci1zZWctc21hbGwiOiAicmYtZGV0ci1zZWctc21hbGwucHQiLAogICAgInJmZGV0ci1zZWctbWVkaXVtIjogInJmLWRldHItc2VnLW1lZGl1bS5wdCIsCiAgICAicmZkZXRyLXNlZy1sYXJnZSI6ICJyZi1kZXRyLXNlZy1sYXJnZS5wdCIsCiAgICAicmZkZXRyLXNlZy14bGFyZ2UiOiAicmYtZGV0ci1zZWcteGxhcmdlLnB0IiwKICAgICJyZmRldHItc2VnLTJ4bGFyZ2UiOiAicmYtZGV0ci1zZWcteHhsYXJnZS5wdCIsCiAgICAicmZkZXRyLXNlZy14eGxhcmdlIjogInJmLWRldHItc2VnLXh4bGFyZ2UucHQiLAp9Cgp3ZWlnaHRzX2RpciA9IFBhdGgob3MuZW52aXJvblsiUkZfREVUUl9XRUlHSFRTX0RJUiJdKS5leHBhbmR1c2VyKCkucmVzb2x2ZSgpCndlaWdodHNfZGlyLm1rZGlyKHBhcmVudHM9VHJ1ZSwgZXhpc3Rfb2s9VHJ1ZSkKCmZvciBtb2RlbF9pZCBpbiBtb2RlbF9pZHM6CiAgICB0cnk6CiAgICAgICAgbW9kZWxfY2xhc3MgPSBtb2RlbF9jbGFzc2VzW21vZGVsX2lkXQogICAgICAgIHdlaWdodF9maWxlbmFtZSA9IHdlaWdodF9maWxlbmFtZXNbbW9kZWxfaWRdCiAgICBleGNlcHQgS2V5RXJyb3IgYXMgZXhjOgogICAgICAgIHJhaXNlIFN5c3RlbUV4aXQoZiJVbnN1cHBvcnRlZCBSRi1ERVRSIHNlZ21lbnRhdGlvbiBtb2RlbCBpZDoge21vZGVsX2lkfSIpIGZyb20gZXhjCiAgICBtb2RlbF9jbGFzcyhwcmV0cmFpbl93ZWlnaHRzPXN0cigod2VpZ2h0c19kaXIgLyB3ZWlnaHRfZmlsZW5hbWUpLnJlc29sdmUoKSksIGRldmljZT0iY3B1IikKICAgIHdlaWdodHNfcGF0aCA9IHdlaWdodHNfZGlyIC8gd2VpZ2h0X2ZpbGVuYW1lCiAgICBpZiBub3Qgd2VpZ2h0c19wYXRoLmV4aXN0cygpOgogICAgICAgIHJhaXNlIFN5c3RlbUV4aXQoZiJSRi1ERVRSIHdlaWdodHMgd2VyZSBub3QgbWF0ZXJpYWxpemVkIGZvciB7bW9kZWxfaWR9OiB7d2VpZ2h0c19wYXRofSIpCiAgICBwcmludChmIndhcm1lZCB7d2VpZ2h0c19wYXRofSIsIGZsdXNoPVRydWUpClBZCn0KCmluc3RhbGxfZmFjZWZ1c2lvbl9ydW50aW1lKCkgewogIGxvZ19zdGVwICJJbnN0YWxsaW5nIEZhY2VGdXNpb24gQ1VEQSBydW50aW1lIgogIGNkICIke0ZBQ0VGVVNJT05fUk9PVH0iCiAgdXYgcHl0aG9uIGluc3RhbGwgIiR7RkFDRUZVU0lPTl9QWVRIT05fVkVSU0lPTn0iCiAgdXYgdmVudiAtLXB5dGhvbiAiJHtGQUNFRlVTSU9OX1BZVEhPTl9WRVJTSU9OfSIgLS1zZWVkIC52ZW52CiAgLiAudmVudi9iaW4vYWN0aXZhdGUKICBweXRob24gLW0gcGlwIGluc3RhbGwgLS11cGdyYWRlIHBpcCAic2V0dXB0b29sczw4MiIgd2hlZWwKICBweXRob24gaW5zdGFsbC5weSAtLW9ubnhydW50aW1lICIke0ZBQ0VGVVNJT05fT05OWFJVTlRJTUV9IiAtLXNraXAtY29uZGEKfQoKZG93bmxvYWRfZmFjZWZ1c2lvbl9hc3NldCgpIHsKICBsb2NhbCBvdXRwdXRfcGF0aD0iJDEiCiAgc2hpZnQKICBsb2NhbCBvdXRwdXRfdG1wPSIke291dHB1dF9wYXRofS50bXAiCgogIHJtIC1mICIke291dHB1dF90bXB9IgogIGZvciBhc3NldF91cmwgaW4gIiRAIjsgZG8KICAgIGlmIGN1cmwgXAogICAgICAtLWZhaWwgXAogICAgICAtLWxvY2F0aW9uIFwKICAgICAgLS1zaWxlbnQgXAogICAgICAtLXNob3ctZXJyb3IgXAogICAgICAtLXJldHJ5IDUgXAogICAgICAtLXJldHJ5LWRlbGF5IDIgXAogICAgICAtLXJldHJ5LWFsbC1lcnJvcnMgXAogICAgICAtLWNvbm5lY3QtdGltZW91dCAxMCBcCiAgICAgIC0tbWF4LXRpbWUgMTgwIFwKICAgICAgLS1vdXRwdXQgIiR7b3V0cHV0X3RtcH0iIFwKICAgICAgIiR7YXNzZXRfdXJsfSI7IHRoZW4KICAgICAgbXYgIiR7b3V0cHV0X3RtcH0iICIke291dHB1dF9wYXRofSIKICAgICAgcmV0dXJuIDAKICAgIGZpCiAgICBybSAtZiAiJHtvdXRwdXRfdG1wfSIKICBkb25lCiAgcmV0dXJuIDEKfQoKdmFsaWRhdGVfZmFjZWZ1c2lvbl9zb3VyY2UoKSB7CiAgbG9jYWwgc291cmNlX3BhdGg9IiQxIgoKICBGQUNFRlVTSU9OX1NPVVJDRV9QQVRIPSIke3NvdXJjZV9wYXRofSIgcHl0aG9uIC0gPDwnUFknCmZyb20gX19mdXR1cmVfXyBpbXBvcnQgYW5ub3RhdGlvbnMKCmltcG9ydCBvcwppbXBvcnQgc3lzCmZyb20gcGF0aGxpYiBpbXBvcnQgUGF0aAoKcm9vdCA9IFBhdGguY3dkKCkKaWYgc3RyKHJvb3QpIG5vdCBpbiBzeXMucGF0aDoKICAgIHN5cy5wYXRoLmluc2VydCgwLCBzdHIocm9vdCkpCgpmcm9tIGZhY2VmdXNpb24uaGFzaF9oZWxwZXIgaW1wb3J0IHZhbGlkYXRlX2hhc2gKCgpzb3VyY2VfcGF0aCA9IG9zLmVudmlyb25bIkZBQ0VGVVNJT05fU09VUkNFX1BBVEgiXQppZiBub3QgdmFsaWRhdGVfaGFzaChzb3VyY2VfcGF0aCk6CiAgICByYWlzZSBTeXN0ZW1FeGl0KGYiaW52YWxpZCBGYWNlRnVzaW9uIHNvdXJjZToge3NvdXJjZV9wYXRofSIpCnByaW50KGYidmFsaWRhdGVkIHtzb3VyY2VfcGF0aH0iLCBmbHVzaD1UcnVlKQpQWQp9CgpwcmVmZXRjaF9mYWNlZnVzaW9uX2Zhbl82OF81KCkgewogIGlmIFtbICIke0ZBQ0VGVVNJT05fUFJFRkVUQ0hfRkFOXzY4XzV9IiAhPSAiMSIgXV07IHRoZW4KICAgIGxvZ19zdGVwICJTa2lwcGluZyBGYWNlRnVzaW9uIGZhbl82OF81IHByZWZldGNoIgogICAgcmV0dXJuCiAgZmkKCiAgbG9nX3N0ZXAgIlByZWZldGNoaW5nIEZhY2VGdXNpb24gZmFuXzY4XzUgYXNzZXQiCiAgY2QgIiR7RkFDRUZVU0lPTl9ST09UfSIKICAuIC52ZW52L2Jpbi9hY3RpdmF0ZQoKICBsb2NhbCBtb2RlbF9kaXI9IiR7RkFDRUZVU0lPTl9ST09UfS8uYXNzZXRzL21vZGVscyIKICBsb2NhbCBoYXNoX3BhdGg9IiR7bW9kZWxfZGlyfS9mYW5fNjhfNS5oYXNoIgogIGxvY2FsIHNvdXJjZV9wYXRoPSIke21vZGVsX2Rpcn0vZmFuXzY4XzUub25ueCIKICBsb2NhbCBnaXRodWJfYmFzZT0iaHR0cHM6Ly9naXRodWIuY29tL2ZhY2VmdXNpb24vZmFjZWZ1c2lvbi1hc3NldHMvcmVsZWFzZXMvZG93bmxvYWQvbW9kZWxzLTMuMC4wIgogIGxvY2FsIGh1Z2dpbmdmYWNlX2Jhc2U9Imh0dHBzOi8vaHVnZ2luZ2ZhY2UuY28vZmFjZWZ1c2lvbi9tb2RlbHMtMy4wLjAvcmVzb2x2ZS9tYWluIgogIGxvY2FsIG1heF9hdHRlbXB0cwogIG1heF9hdHRlbXB0cz0iJCgoJHtGQUNFRlVTSU9OX1BSRVdBUk1fUkVUUklFU30gPiAwID8gJHtGQUNFRlVTSU9OX1BSRVdBUk1fUkVUUklFU30gOiAxKSkiCgogIG1rZGlyIC1wICIke21vZGVsX2Rpcn0iCgogIGZvciBhdHRlbXB0IGluICQoc2VxIDEgIiR7bWF4X2F0dGVtcHRzfSIpOyBkbwogICAgaWYgZG93bmxvYWRfZmFjZWZ1c2lvbl9hc3NldCBcCiAgICAgICIke2hhc2hfcGF0aH0iIFwKICAgICAgIiR7Z2l0aHViX2Jhc2V9L2Zhbl82OF81Lmhhc2giIFwKICAgICAgIiR7aHVnZ2luZ2ZhY2VfYmFzZX0vZmFuXzY4XzUuaGFzaCIgJiYgXAogICAgICBkb3dubG9hZF9mYWNlZnVzaW9uX2Fzc2V0IFwKICAgICAgICAiJHtzb3VyY2VfcGF0aH0iIFwKICAgICAgICAiJHtnaXRodWJfYmFzZX0vZmFuXzY4XzUub25ueCIgXAogICAgICAgICIke2h1Z2dpbmdmYWNlX2Jhc2V9L2Zhbl82OF81Lm9ubngiICYmIFwKICAgICAgdmFsaWRhdGVfZmFjZWZ1c2lvbl9zb3VyY2UgIiR7c291cmNlX3BhdGh9IjsgdGhlbgogICAgICByZXR1cm4KICAgIGZpCgogICAgaWYgW1sgIiR7YXR0ZW1wdH0iID09ICIke21heF9hdHRlbXB0c30iIF1dOyB0aGVuCiAgICAgIGVjaG8gIkZhaWxlZCB0byBwcmVmZXRjaCBGYWNlRnVzaW9uIGZhbl82OF81IGFmdGVyICR7bWF4X2F0dGVtcHRzfSBhdHRlbXB0cyIgPiYyCiAgICAgIGV4aXQgMQogICAgZmkKICAgIHJtIC1mICIke2hhc2hfcGF0aH0iICIke3NvdXJjZV9wYXRofSIKICAgIHNsZWVwICIke2F0dGVtcHR9IgogIGRvbmUKfQoKcHJld2FybV9mYWNlZnVzaW9uX21vZGVscygpIHsKICBpZiBbWyAiJHtGQUNFRlVTSU9OX1BSRVdBUk1fTU9ERUxTfSIgIT0gIjEiIF1dOyB0aGVuCiAgICBsb2dfc3RlcCAiU2tpcHBpbmcgRmFjZUZ1c2lvbiBtb2RlbCBwcmV3YXJtIgogICAgcmV0dXJuCiAgZmkKICBwcmVmZXRjaF9mYWNlZnVzaW9uX2Zhbl82OF81CiAgbG9nX3N0ZXAgIlByZXdhcm1pbmcgRmFjZUZ1c2lvbiBtb2RlbCBhc3NldHMiCiAgY2QgIiR7RkFDRUZVU0lPTl9ST09UfSIKICAuIC52ZW52L2Jpbi9hY3RpdmF0ZQogIEZBQ0VGVVNJT05fUFJFV0FSTV9SRVRSSUVTPSIke0ZBQ0VGVVNJT05fUFJFV0FSTV9SRVRSSUVTfSIgcHl0aG9uIC0gPDwnUFknCmZyb20gX19mdXR1cmVfXyBpbXBvcnQgYW5ub3RhdGlvbnMKCmltcG9ydCBvcwppbXBvcnQgdGltZQppbXBvcnQgc3lzCmZyb20gcGF0aGxpYiBpbXBvcnQgUGF0aAoKcm9vdCA9IFBhdGguY3dkKCkKaWYgc3RyKHJvb3QpIG5vdCBpbiBzeXMucGF0aDoKICAgIHN5cy5wYXRoLmluc2VydCgwLCBzdHIocm9vdCkpCgpmcm9tIGZhY2VmdXNpb24gaW1wb3J0IHN0YXRlX21hbmFnZXIKZnJvbSBmYWNlZnVzaW9uIGltcG9ydCBmYWNlX2NsYXNzaWZpZXIsIGZhY2VfZGV0ZWN0b3IsIGZhY2VfbGFuZG1hcmtlciwgZmFjZV9tYXNrZXIsIGZhY2VfcmVjb2duaXplcgpmcm9tIGZhY2VmdXNpb24ucHJvY2Vzc29ycy5tb2R1bGVzLmZhY2Vfc3dhcHBlciBpbXBvcnQgY29yZSBhcyBmYWNlX3N3YXBwZXIKCnN0YXRlX21hbmFnZXIuaW5pdF9pdGVtKCJleGVjdXRpb25fZGV2aWNlX2lkcyIsIFswXSkKc3RhdGVfbWFuYWdlci5pbml0X2l0ZW0oImV4ZWN1dGlvbl9wcm92aWRlcnMiLCBbImNwdSJdKQpzdGF0ZV9tYW5hZ2VyLmluaXRfaXRlbSgiZG93bmxvYWRfcHJvdmlkZXJzIiwgWyJnaXRodWIiLCAiaHVnZ2luZ2ZhY2UiXSkKc3RhdGVfbWFuYWdlci5pbml0X2l0ZW0oImZhY2VfZGV0ZWN0b3JfbW9kZWwiLCAieXVuZXQiKQpzdGF0ZV9tYW5hZ2VyLmluaXRfaXRlbSgiZmFjZV9kZXRlY3Rvcl9zaXplIiwgIjY0MHg2NDAiKQpzdGF0ZV9tYW5hZ2VyLmluaXRfaXRlbSgiZmFjZV9kZXRlY3Rvcl9tYXJnaW4iLCBbMCwgMCwgMCwgMF0pCnN0YXRlX21hbmFnZXIuaW5pdF9pdGVtKCJmYWNlX2RldGVjdG9yX3Njb3JlIiwgMC4zNSkKc3RhdGVfbWFuYWdlci5pbml0X2l0ZW0oImZhY2VfZGV0ZWN0b3JfYW5nbGVzIiwgWzBdKQpzdGF0ZV9tYW5hZ2VyLmluaXRfaXRlbSgiZmFjZV9sYW5kbWFya2VyX21vZGVsIiwgIjJkZmFuNCIpCnN0YXRlX21hbmFnZXIuaW5pdF9pdGVtKCJmYWNlX29jY2x1ZGVyX21vZGVsIiwgInhzZWdfMSIpCnN0YXRlX21hbmFnZXIuaW5pdF9pdGVtKCJmYWNlX3BhcnNlcl9tb2RlbCIsICJiaXNlbmV0X3Jlc25ldF8zNCIpCnN0YXRlX21hbmFnZXIuaW5pdF9pdGVtKCJmYWNlX3N3YXBwZXJfbW9kZWwiLCAiaHlwZXJzd2FwXzFiXzI1NiIpCnN0YXRlX21hbmFnZXIuaW5pdF9pdGVtKCJmYWNlX3N3YXBwZXJfcGl4ZWxfYm9vc3QiLCAiMjU2eDI1NiIpCnN0YXRlX21hbmFnZXIuaW5pdF9pdGVtKCJmYWNlX3N3YXBwZXJfd2VpZ2h0IiwgMS4wKQoKbWF4X2F0dGVtcHRzID0gbWF4KDEsIGludChvcy5lbnZpcm9uLmdldCgiRkFDRUZVU0lPTl9QUkVXQVJNX1JFVFJJRVMiLCAiMyIpKSkKY2hlY2tzID0gWwogICAgKCJmYWNlX2RldGVjdG9yIiwgZmFjZV9kZXRlY3Rvci5wcmVfY2hlY2spLAogICAgKCJmYWNlX2xhbmRtYXJrZXIiLCBmYWNlX2xhbmRtYXJrZXIucHJlX2NoZWNrKSwKICAgICgiZmFjZV9yZWNvZ25pemVyIiwgZmFjZV9yZWNvZ25pemVyLnByZV9jaGVjayksCiAgICAoImZhY2VfY2xhc3NpZmllciIsIGZhY2VfY2xhc3NpZmllci5wcmVfY2hlY2spLAogICAgKCJmYWNlX21hc2tlciIsIGZhY2VfbWFza2VyLnByZV9jaGVjayksCiAgICAoImZhY2Vfc3dhcHBlciIsIGZhY2Vfc3dhcHBlci5wcmVfY2hlY2spLApdCmZvciBsYWJlbCwgZm4gaW4gY2hlY2tzOgogICAgZm9yIGF0dGVtcHQgaW4gcmFuZ2UoMSwgbWF4X2F0dGVtcHRzICsgMSk6CiAgICAgICAgb2sgPSBmbigpCiAgICAgICAgcHJpbnQoZiJ7bGFiZWx9IHByZV9jaGVjaz17b2t9IGF0dGVtcHQ9e2F0dGVtcHR9L3ttYXhfYXR0ZW1wdHN9IiwgZmx1c2g9VHJ1ZSkKICAgICAgICBpZiBvazoKICAgICAgICAgICAgYnJlYWsKICAgICAgICBpZiBhdHRlbXB0ID09IG1heF9hdHRlbXB0czoKICAgICAgICAgICAgcmFpc2UgU3lzdGVtRXhpdChmIkZhaWxlZCB0byBwcmV3YXJtIHtsYWJlbH0gYWZ0ZXIge21heF9hdHRlbXB0c30gYXR0ZW1wdHMiKQogICAgICAgIHRpbWUuc2xlZXAobWluKGF0dGVtcHQsIDUpKQpQWQp9CgpkZWR1cGVfcHl0aG9uX2Vudl9hZ2FpbnN0X21haW5fc2l0ZV9wYWNrYWdlcygpIHsKICBsb2NhbCBlbnZfcm9vdD0iJDEiCiAgbG9jYWwgbGFiZWw9IiQyIgoKICBpZiBbWyAiJHtGQUNFRlVTSU9OX0hBUkRMSU5LX0RFRFVQRX0iICE9ICIxIiBdXTsgdGhlbgogICAgbG9nX3N0ZXAgIlNraXBwaW5nICR7bGFiZWx9IGhhcmRsaW5rIGRlZHVwZSIKICAgIHJldHVybgogIGZpCgogIGxvZ19zdGVwICJIYXJkbGlua2luZyBkdXBsaWNhdGUgJHtsYWJlbH0gZmlsZXMiCiAgcHl0aG9uMyAtICIke2Vudl9yb290fSIgIiR7bGFiZWx9IiA8PCdQWScKZnJvbSBfX2Z1dHVyZV9fIGltcG9ydCBhbm5vdGF0aW9ucwoKaW1wb3J0IGhhc2hsaWIKaW1wb3J0IG9zCmltcG9ydCBzaXRlCmltcG9ydCBzeXMKZnJvbSBwYXRobGliIGltcG9ydCBQYXRoCgoKZGVmIHNoYTI1NnN1bShwYXRoOiBQYXRoKSAtPiBzdHI6CiAgICBkaWdlc3QgPSBoYXNobGliLnNoYTI1NigpCiAgICB3aXRoIHBhdGgub3BlbigicmIiKSBhcyBmaDoKICAgICAgICBmb3IgY2h1bmsgaW4gaXRlcihsYW1iZGE6IGZoLnJlYWQoMTAyNCAqIDEwMjQpLCBiIiIpOgogICAgICAgICAgICBkaWdlc3QudXBkYXRlKGNodW5rKQogICAgcmV0dXJuIGRpZ2VzdC5oZXhkaWdlc3QoKQoKCmVudl9yb290ID0gUGF0aChzeXMuYXJndlsxXSkuZXhwYW5kdXNlcigpLnJlc29sdmUoKQpsYWJlbCA9IHN5cy5hcmd2WzJdCnZlbnZfc2l0ZV9wYWNrYWdlcyA9IG5leHQoZW52X3Jvb3QuZ2xvYigiLnZlbnYvbGliL3B5dGhvbiovc2l0ZS1wYWNrYWdlcyIpLCBOb25lKQppZiB2ZW52X3NpdGVfcGFja2FnZXMgaXMgTm9uZToKICAgIHByaW50KGYie2xhYmVsfSBzaXRlLXBhY2thZ2VzIGRpcmVjdG9yeSBub3QgZm91bmQ7IHNraXBwaW5nIGRlZHVwZSIsIGZsdXNoPVRydWUpCiAgICByYWlzZSBTeXN0ZW1FeGl0KDApCgptYWluX3NpdGVfcGFja2FnZXMgPSBOb25lCmZvciBjYW5kaWRhdGUgaW4gbWFwKFBhdGgsIHNpdGUuZ2V0c2l0ZXBhY2thZ2VzKCkpOgogICAgaWYgY2FuZGlkYXRlLm5hbWUgPT0gInNpdGUtcGFja2FnZXMiIGFuZCBjYW5kaWRhdGUuZXhpc3RzKCk6CiAgICAgICAgbWFpbl9zaXRlX3BhY2thZ2VzID0gY2FuZGlkYXRlLnJlc29sdmUoKQogICAgICAgIGJyZWFrCgppZiBtYWluX3NpdGVfcGFja2FnZXMgaXMgTm9uZToKICAgIHByaW50KCJNYWluIHNpdGUtcGFja2FnZXMgZGlyZWN0b3J5IG5vdCBmb3VuZDsgc2tpcHBpbmcgZGVkdXBlIiwgZmx1c2g9VHJ1ZSkKICAgIHJhaXNlIFN5c3RlbUV4aXQoMCkKCmxpbmtlZF9maWxlcyA9IDAKbGlua2VkX2J5dGVzID0gMApmb3IgZmZfcGF0aCBpbiBzb3J0ZWQodmVudl9zaXRlX3BhY2thZ2VzLnJnbG9iKCIqIikpOgogICAgaWYgbm90IGZmX3BhdGguaXNfZmlsZSgpIG9yIGZmX3BhdGguaXNfc3ltbGluaygpOgogICAgICAgIGNvbnRpbnVlCiAgICByZWxhdGl2ZSA9IGZmX3BhdGgucmVsYXRpdmVfdG8odmVudl9zaXRlX3BhY2thZ2VzKQogICAgbWFpbl9wYXRoID0gbWFpbl9zaXRlX3BhY2thZ2VzIC8gcmVsYXRpdmUKICAgIGlmIG5vdCBtYWluX3BhdGguZXhpc3RzKCkgb3Igbm90IG1haW5fcGF0aC5pc19maWxlKCkgb3IgbWFpbl9wYXRoLmlzX3N5bWxpbmsoKToKICAgICAgICBjb250aW51ZQogICAgZmZfc3RhdCA9IGZmX3BhdGguc3RhdCgpCiAgICBtYWluX3N0YXQgPSBtYWluX3BhdGguc3RhdCgpCiAgICBpZiBmZl9zdGF0LnN0X3NpemUgPT0gMCBvciBmZl9zdGF0LnN0X3NpemUgIT0gbWFpbl9zdGF0LnN0X3NpemU6CiAgICAgICAgY29udGludWUKICAgIGlmIGZmX3N0YXQuc3RfaW5vID09IG1haW5fc3RhdC5zdF9pbm8gYW5kIGZmX3N0YXQuc3RfZGV2ID09IG1haW5fc3RhdC5zdF9kZXY6CiAgICAgICAgY29udGludWUKICAgIGlmIHNoYTI1NnN1bShmZl9wYXRoKSAhPSBzaGEyNTZzdW0obWFpbl9wYXRoKToKICAgICAgICBjb250aW51ZQogICAgZmZfcGF0aC51bmxpbmsoKQogICAgb3MubGluayhtYWluX3BhdGgsIGZmX3BhdGgpCiAgICBsaW5rZWRfZmlsZXMgKz0gMQogICAgbGlua2VkX2J5dGVzICs9IGZmX3N0YXQuc3Rfc2l6ZQoKcHJpbnQoCiAgICBmIkhhcmRsaW5rZWQge2xpbmtlZF9maWxlc30gZHVwbGljYXRlIHtsYWJlbH0gZmlsZXMgIgogICAgZiIoe2xpbmtlZF9ieXRlcyAvICgxMDI0ICogMTAyNCk6LjFmfSBNaUIgc2hhcmVkKSIsCiAgICBmbHVzaD1UcnVlLAopClBZCn0KCmRlZHVwZV9mYWNlZnVzaW9uX3ZlbnZfZmlsZXMoKSB7CiAgZGVkdXBlX3B5dGhvbl9lbnZfYWdhaW5zdF9tYWluX3NpdGVfcGFja2FnZXMgIiR7RkFDRUZVU0lPTl9ST09UfSIgIkZhY2VGdXNpb24gdmlydHVhbGVudiIKfQoKcHJ1bmVfZmFjZWZ1c2lvbl91bnVzZWRfcnVudGltZV9wYWNrYWdlcygpIHsKICBpZiBbWyAiJHtGQUNFRlVTSU9OX1BSVU5FX1VOVVNFRF9QQUNLQUdFU30iICE9ICIxIiBdXTsgdGhlbgogICAgbG9nX3N0ZXAgIlNraXBwaW5nIEZhY2VGdXNpb24gdW51c2VkIHBhY2thZ2UgcHJ1bmluZyIKICAgIHJldHVybgogIGZpCgogIGxvZ19zdGVwICJQcnVuaW5nIEZhY2VGdXNpb24gd2ViIFVJIHBhY2thZ2VzIG5vdCB1c2VkIGJ5IGhvc3RlZCBjbGlwIHBhdGhzIgogIGNkICIke0ZBQ0VGVVNJT05fUk9PVH0iCiAgLiAudmVudi9iaW4vYWN0aXZhdGUKICBweXRob24gLW0gcGlwIHVuaW5zdGFsbCAteSBcCiAgICBncmFkaW8gXAogICAgZ3JhZGlvX2NsaWVudCBcCiAgICBncmFkaW9fcmFuZ2VzbGlkZXIgXAogICAgcGFuZGFzIFwKICAgIGZhc3RhcGkgXAogICAgc3RhcmxldHRlIFwKICAgIHV2aWNvcm4gXAogICAgd2Vic29ja2V0cyBcCiAgICBvcmpzb24gfHwgdHJ1ZQp9CgpkZWR1cGVfb3BlbnBpbG90X3ZlbnZfZmlsZXMoKSB7CiAgZGVkdXBlX3B5dGhvbl9lbnZfYWdhaW5zdF9tYWluX3NpdGVfcGFja2FnZXMgIiR7T1BFTlBJTE9UX1JPT1R9IiAib3BlbnBpbG90IHZpcnR1YWxlbnYiCn0KCmRlYWN0aXZhdGVfZmFjZWZ1c2lvbl92ZW52KCkgewogIGlmIFtbIC1uICIke1ZJUlRVQUxfRU5WOi19IiBdXTsgdGhlbgogICAgbG9nX3N0ZXAgIkRlYWN0aXZhdGluZyBGYWNlRnVzaW9uIHZpcnR1YWxlbnYgYmVmb3JlIG9wZW5waWxvdCBib290c3RyYXAiCiAgICBkZWFjdGl2YXRlIHx8IHRydWUKICBmaQp9CgpwcnVuZV9mYWNlZnVzaW9uX3ZlbnYoKSB7CiAgaWYgW1sgIiR7RkFDRUZVU0lPTl9QUlVORV9WRU5WfSIgIT0gIjEiIF1dOyB0aGVuCiAgICBsb2dfc3RlcCAiU2tpcHBpbmcgRmFjZUZ1c2lvbiB2aXJ0dWFsZW52IHBydW5pbmciCiAgICByZXR1cm4KICBmaQoKICBsb2dfc3RlcCAiUHJ1bmluZyBGYWNlRnVzaW9uIHZpcnR1YWxlbnYgYm9vdHN0cmFwIHRvb2xpbmciCiAgbG9jYWwgZmFjZWZ1c2lvbl92ZW52PSIke0ZBQ0VGVVNJT05fUk9PVH0vLnZlbnYiCiAgaWYgW1sgISAtZCAiJHtmYWNlZnVzaW9uX3ZlbnZ9IiBdXTsgdGhlbgogICAgcmV0dXJuCiAgZmkKCiAgcm0gLXJmICIke2ZhY2VmdXNpb25fdmVudn0vaW5jbHVkZSIgIiR7ZmFjZWZ1c2lvbl92ZW52fS9zaGFyZSIKICBmaW5kICIke2ZhY2VmdXNpb25fdmVudn0iIC10eXBlIGQgLW5hbWUgJ19fcHljYWNoZV9fJyAtcHJ1bmUgLWV4ZWMgcm0gLXJmIHt9ICsKICBmaW5kICIke2ZhY2VmdXNpb25fdmVudn0iIC10eXBlIGYgXCggLW5hbWUgJyoucHljJyAtbyAtbmFtZSAnKi5weW8nIFwpIC1kZWxldGUKCiAgcHl0aG9uMyAtICIke2ZhY2VmdXNpb25fdmVudn0iIDw8J1BZJwpmcm9tIF9fZnV0dXJlX18gaW1wb3J0IGFubm90YXRpb25zCgppbXBvcnQgc2h1dGlsCmltcG9ydCBzeXMKZnJvbSBwYXRobGliIGltcG9ydCBQYXRoCgp2ZW52X3Jvb3QgPSBQYXRoKHN5cy5hcmd2WzFdKS5leHBhbmR1c2VyKCkucmVzb2x2ZSgpCnNpdGVfcGFja2FnZXMgPSBuZXh0KHZlbnZfcm9vdC5nbG9iKCJsaWIvcHl0aG9uKi9zaXRlLXBhY2thZ2VzIiksIE5vbmUpCmlmIHNpdGVfcGFja2FnZXMgaXMgTm9uZToKICAgIHJhaXNlIFN5c3RlbUV4aXQoMCkKCmZvciBwYXR0ZXJuIGluICgKICAgICJwaXAiLAogICAgInBpcC0qIiwKICAgICJzZXR1cHRvb2xzIiwKICAgICJzZXR1cHRvb2xzLSoiLAogICAgIndoZWVsIiwKICAgICJ3aGVlbC0qIiwKICAgICJwa2dfcmVzb3VyY2VzIiwKKToKICAgIGZvciBwYXRoIGluIHNpdGVfcGFja2FnZXMuZ2xvYihwYXR0ZXJuKToKICAgICAgICBpZiBwYXRoLmlzX2RpcigpOgogICAgICAgICAgICBzaHV0aWwucm10cmVlKHBhdGgsIGlnbm9yZV9lcnJvcnM9VHJ1ZSkKICAgICAgICBlbGlmIHBhdGguZXhpc3RzKCk6CiAgICAgICAgICAgIHBhdGgudW5saW5rKCkKCmZvciBwYXRoIGluIHNpdGVfcGFja2FnZXMuZ2xvYigiZGlzdHV0aWxzLXByZWNlZGVuY2UucHRoIik6CiAgICBwYXRoLnVubGluaygpClBZCn0KCnBydW5lX2ZhY2VmdXNpb25fY2hlY2tvdXQoKSB7CiAgbG9nX3N0ZXAgIlBydW5pbmcgRmFjZUZ1c2lvbiBjaGVja291dCIKICBjZCAiJHtGQUNFRlVTSU9OX1JPT1R9IgogIHJtIC1yZiAuZ2l0IC5naXRodWIgdGVzdHMKfQoKcHJ1bmVfb3BlbnBpbG90X3ZlbnZfYXJ0aWZhY3RzKCkgewogIGxvZ19zdGVwICJQcnVuaW5nIG9wZW5waWxvdCB2aXJ0dWFsZW52IGJ5dGVjb2RlIGNhY2hlcyIKICBsb2NhbCBvcGVucGlsb3RfdmVudj0iJHtPUEVOUElMT1RfUk9PVH0vLnZlbnYiCiAgaWYgW1sgISAtZCAiJHtvcGVucGlsb3RfdmVudn0iIF1dOyB0aGVuCiAgICByZXR1cm4KICBmaQogIGZpbmQgIiR7b3BlbnBpbG90X3ZlbnZ9IiAtdHlwZSBkIC1uYW1lICdfX3B5Y2FjaGVfXycgLXBydW5lIC1leGVjIHJtIC1yZiB7fSArCiAgZmluZCAiJHtvcGVucGlsb3RfdmVudn0iIC10eXBlIGYgXCggLW5hbWUgJyoucHljJyAtbyAtbmFtZSAnKi5weW8nIFwpIC1kZWxldGUKfQoKY2xlYW5fdHJhbnNpZW50X3BhY2thZ2VfY2FjaGVzKCkgewogIGxvZ19zdGVwICJDbGVhbmluZyB0cmFuc2llbnQgcGFja2FnZSBjYWNoZXMiCiAgcm0gLXJmIC9yb290Ly5jYWNoZS91diAvcm9vdC8uY2FjaGUvcGlwCiAgcm0gLXJmICIke1VWX0NBQ0hFX0RJUn0iICIke1BJUF9DQUNIRV9ESVJ9IgogIG1rZGlyIC1wICIke1VWX0NBQ0hFX0RJUn0iICIke1BJUF9DQUNIRV9ESVJ9Igp9CgpmaXhfdmVuZG9yZWRfdG9vbF9wZXJtaXNzaW9ucygpIHsKICBpZiBbWyAhIC1kICIke09QRU5QSUxPVF9ST09UfS8udmVudi9saWIiIF1dOyB0aGVuCiAgICByZXR1cm4KICBmaQoKICBsb2dfc3RlcCAiRml4aW5nIHZlbmRvcmVkIHRvb2wgcGVybWlzc2lvbnMiCiAgZmluZCAiJHtPUEVOUElMT1RfUk9PVH0vLnZlbnYvbGliIiAtdHlwZSBmIFwKICAgIFwoIC1uYW1lICdhcm0tbm9uZS1lYWJpLSonIC1vIC1uYW1lICdjYXBucCcgLW8gLW5hbWUgJ2NhcG5wYyonIC1vIC1uYW1lICdmZm1wZWcnIC1vIC1uYW1lICdmZnByb2JlJyBcKSBcCiAgICAtZXhlYyBjaG1vZCAreCB7fSArIHx8IHRydWUKfQoKYnVpbGRfb3BlbnBpbG90X2NsaXBfZGVwZW5kZW5jaWVzKCkgewogIGxvZ19zdGVwICJCdWlsZGluZyBuYXRpdmUgb3BlbnBpbG90IGNsaXAgZGVwZW5kZW5jaWVzIgogIGNkICIke09QRU5QSUxPVF9ST09UfSIKICB1diBydW4gLS1uby1zeW5jIHNjb25zIC1qIiR7U0NPTlNfSk9CU30iIFwKICAgIG1zZ3FfcmVwby9tc2dxL2lwY19weXguc28gXAogICAgbXNncV9yZXBvL21zZ3EvdmlzaW9uaXBjL3Zpc2lvbmlwY19weXguc28gXAogICAgY29tbW9uL3BhcmFtc19weXguc28gXAogICAgc2VsZmRyaXZlL2NvbnRyb2xzL2xpYi9sb25naXR1ZGluYWxfbXBjX2xpYi9jX2dlbmVyYXRlZF9jb2RlL2FjYWRvc19vY3Bfc29sdmVyX3B5eC5zbyBcCiAgICBzZWxmZHJpdmUvY29udHJvbHMvbGliL2xhdGVyYWxfbXBjX2xpYi9jX2dlbmVyYXRlZF9jb2RlL2FjYWRvc19vY3Bfc29sdmVyX3B5eC5zbwp9CgppbnN0YWxsX2FjY2VsZXJhdGVkX2xpbnV4X3B5cmF5KCkgewogIGlmIFtbICEgLXggIiR7T1BFTlBJTE9UX1JPT1R9Ly52ZW52L2Jpbi9weXRob24iIF1dOyB0aGVuCiAgICByZXR1cm4KICBmaQogIGxvZ19zdGVwICJJbnN0YWxsaW5nIGFjY2VsZXJhdGVkIExpbnV4IHB5cmF5IHdoZWVsIgogIHB5dGhvbjMgLSAiJHtPUEVOUElMT1RfUk9PVH0vLnZlbnYvYmluL3B5dGhvbiIgPDwnUFknCmZyb20gX19mdXR1cmVfXyBpbXBvcnQgYW5ub3RhdGlvbnMKCmltcG9ydCBvcwppbXBvcnQgc2h1dGlsCmltcG9ydCBzdWJwcm9jZXNzCmltcG9ydCBzeXMKaW1wb3J0IHN5c2NvbmZpZwppbXBvcnQgdGVtcGZpbGUKZnJvbSBwYXRobGliIGltcG9ydCBQYXRoCgpweXRob25fYmluID0gc3lzLmFyZ3ZbMV0KbWluX2NtYWtlX3ZlcnNpb24gPSAoMywgMjUpCnJheWxpYl9yZXBvID0gImh0dHBzOi8vZ2l0aHViLmNvbS9jb21tYWFpL3JheWxpYi5naXQiCnB5cmF5X3JlcG8gPSAiaHR0cHM6Ly9naXRodWIuY29tL2NvbW1hYWkvcmF5bGliLXB5dGhvbi1jZmZpLmdpdCIKcmF5Z3VpX3VybCA9ICgKICAgICJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vcmF5c2FuNS9yYXlndWkvIgogICAgIjc2YjM2YjU5N2VkYjcwZmZhZjk2ZjA0NjA3NmFkYzIwZDY3ZTc4Mjcvc3JjL3JheWd1aS5oIgopCgoKZGVmIHJ1bihjbWQ6IGxpc3Rbc3RyXSwgKiwgY3dkOiBQYXRoIHwgTm9uZSA9IE5vbmUsIGVudjogZGljdFtzdHIsIHN0cl0gfCBOb25lID0gTm9uZSkgLT4gTm9uZToKICAgIHByaW50KGYiKyB7JyAnLmpvaW4oY21kKX0iLCBmbHVzaD1UcnVlKQogICAgc3VicHJvY2Vzcy5ydW4oY21kLCBjd2Q9c3RyKGN3ZCkgaWYgY3dkIGVsc2UgTm9uZSwgZW52PWVudiwgY2hlY2s9VHJ1ZSkKCgpkZWYgY2FwdHVyZShjbWQ6IGxpc3Rbc3RyXSwgKiwgY3dkOiBQYXRoIHwgTm9uZSA9IE5vbmUpIC0+IHN0cjoKICAgIGNvbXBsZXRlZCA9IHN1YnByb2Nlc3MucnVuKAogICAgICAgIGNtZCwKICAgICAgICBjd2Q9c3RyKGN3ZCkgaWYgY3dkIGVsc2UgTm9uZSwKICAgICAgICBjaGVjaz1UcnVlLAogICAgICAgIHRleHQ9VHJ1ZSwKICAgICAgICBjYXB0dXJlX291dHB1dD1UcnVlLAogICAgKQogICAgcmV0dXJuIGNvbXBsZXRlZC5zdGRvdXQuc3RyaXAoKQoKCmRlZiBlbnN1cmVfcGlwKHB5dGhvbl9iaW46IHN0cikgLT4gTm9uZToKICAgIHRyeToKICAgICAgICBydW4oW3B5dGhvbl9iaW4sICItbSIsICJwaXAiLCAiLS12ZXJzaW9uIl0pCiAgICBleGNlcHQgc3VicHJvY2Vzcy5DYWxsZWRQcm9jZXNzRXJyb3I6CiAgICAgICAgcnVuKFtweXRob25fYmluLCAiLW0iLCAiZW5zdXJlcGlwIiwgIi0tdXBncmFkZSJdKQogICAgICAgIHJ1bihbcHl0aG9uX2JpbiwgIi1tIiwgInBpcCIsICJpbnN0YWxsIiwgIi0tdXBncmFkZSIsICJwaXAiLCAid2hlZWwiLCAic2V0dXB0b29sczw4MiJdKQoKCmRlZiBwYXJzZV9jbWFrZV92ZXJzaW9uKG91dHB1dDogc3RyKSAtPiB0dXBsZVtpbnQsIC4uLl06CiAgICBmaXJzdF9saW5lID0gb3V0cHV0LnNwbGl0bGluZXMoKVswXSBpZiBvdXRwdXQuc3BsaXRsaW5lcygpIGVsc2UgIiIKICAgIHBhcnRzID0gZmlyc3RfbGluZS5zdHJpcCgpLnNwbGl0KCkKICAgIHZlcnNpb25fdGV4dCA9IHBhcnRzWy0xXSBpZiBwYXJ0cyBlbHNlICIwIgogICAgdmVyc2lvbl9wYXJ0cyA9IFtdCiAgICBmb3IgcGFydCBpbiB2ZXJzaW9uX3RleHQuc3BsaXQoIi4iKToKICAgICAgICB0cnk6CiAgICAgICAgICAgIHZlcnNpb25fcGFydHMuYXBwZW5kKGludChwYXJ0KSkKICAgICAgICBleGNlcHQgVmFsdWVFcnJvcjoKICAgICAgICAgICAgYnJlYWsKICAgIHJldHVybiB0dXBsZSh2ZXJzaW9uX3BhcnRzKQoKCmRlZiBjbWFrZV9pc19tb2Rlcm4oY21kOiBsaXN0W3N0cl0pIC0+IGJvb2w6CiAgICB0cnk6CiAgICAgICAgdmVyc2lvbiA9IHBhcnNlX2NtYWtlX3ZlcnNpb24oY2FwdHVyZShbKmNtZCwgIi0tdmVyc2lvbiJdKSkKICAgIGV4Y2VwdCAoc3VicHJvY2Vzcy5DYWxsZWRQcm9jZXNzRXJyb3IsIEZpbGVOb3RGb3VuZEVycm9yKToKICAgICAgICByZXR1cm4gRmFsc2UKICAgIHJldHVybiB2ZXJzaW9uID49IG1pbl9jbWFrZV92ZXJzaW9uCgoKZGVmIGVuc3VyZV9tb2Rlcm5fY21ha2UoKSAtPiBsaXN0W3N0cl06CiAgICBlbnZfY21ha2UgPSBvcy5lbnZpcm9uLmdldCgiQ01BS0UiKQogICAgaWYgZW52X2NtYWtlOgogICAgICAgIGNtZCA9IFtlbnZfY21ha2VdCiAgICAgICAgaWYgY21ha2VfaXNfbW9kZXJuKGNtZCk6CiAgICAgICAgICAgIHJldHVybiBjbWQKCiAgICBjbWQgPSBbImNtYWtlIl0KICAgIGlmIGNtYWtlX2lzX21vZGVybihjbWQpOgogICAgICAgIHJldHVybiBjbWQKCiAgICBlbnN1cmVfcGlwKHN5cy5leGVjdXRhYmxlKQogICAgcnVuKFtzeXMuZXhlY3V0YWJsZSwgIi1tIiwgInBpcCIsICJpbnN0YWxsIiwgIi0tdXBncmFkZSIsICJjbWFrZT49My4yNSw8NCJdKQogICAgcGFja2FnZWRfY21ha2UgPSBQYXRoKHN5c2NvbmZpZy5nZXRfcGF0aCgic2NyaXB0cyIpKSAvICJjbWFrZSIKICAgIGNtZCA9IFtzdHIocGFja2FnZWRfY21ha2UpXQogICAgaWYgY21ha2VfaXNfbW9kZXJuKGNtZCk6CiAgICAgICAgcmV0dXJuIGNtZAoKICAgIHJlc29sdmVkID0gc2h1dGlsLndoaWNoKCJjbWFrZSIpCiAgICBpZiByZXNvbHZlZCBhbmQgY21ha2VfaXNfbW9kZXJuKFtyZXNvbHZlZF0pOgogICAgICAgIHJldHVybiBbcmVzb2x2ZWRdCgogICAgcmFpc2UgUnVudGltZUVycm9yKCJDb3VsZCBub3QgZmluZCBvciBpbnN0YWxsIENNYWtlID49IDMuMjUiKQoKCmRlZiB2ZXJpZnlfaW5zdGFsbGVkX3B5cmF5KHB5dGhvbl9iaW46IHN0cikgLT4gTm9uZToKICAgIGNoZWNrID0gKAogICAgICAgICJmcm9tIHBhdGhsaWIgaW1wb3J0IFBhdGhcbiIKICAgICAgICAiaW1wb3J0IHN1YnByb2Nlc3NcbiIKICAgICAgICAiaW1wb3J0IHJheWxpYlxuIgogICAgICAgICJiYXNlID0gUGF0aChyYXlsaWIuX19maWxlX18pLnJlc29sdmUoKS5wYXJlbnRcbiIKICAgICAgICAiYnVpbGQgPSAoYmFzZSAvICdidWlsZC5weScpLnJlYWRfdGV4dCgpXG4iCiAgICAgICAgInNvID0gbmV4dChiYXNlLmdsb2IoJ19yYXlsaWJfY2ZmaSouc28nKSlcbiIKICAgICAgICAidmVyc2lvbiA9IChiYXNlIC8gJ3ZlcnNpb24ucHknKS5yZWFkX3RleHQoKS5zdHJpcCgpXG4iCiAgICAgICAgImJpbmFyeV9zdHJpbmdzID0gc3VicHJvY2Vzcy5ydW4oWydzdHJpbmdzJywgc3RyKHNvKV0sIGNoZWNrPVRydWUsIGNhcHR1cmVfb3V0cHV0PVRydWUsIHRleHQ9VHJ1ZSkuc3Rkb3V0XG4iCiAgICAgICAgInByaW50KHZlcnNpb24pXG4iCiAgICAgICAgImFzc2VydCBcIm9zLnBhdGguam9pbihnZXRfdGhlX2xpYl9wYXRoKCksICdsaWJyYXlsaWIuYScpXCIgaW4gYnVpbGRcbiIKICAgICAgICAiYXNzZXJ0IFwiJy1sRUdMJ1wiIGluIGJ1aWxkXG4iCiAgICAgICAgImFzc2VydCAnR0xGVyBmb3JjZWQgbnVsbCBjb25uZWN0JyBpbiBiaW5hcnlfc3RyaW5nc1xuIgogICAgKQogICAgcnVuKFtweXRob25fYmluLCAiLWMiLCBjaGVja10pCgoKZGVmIHJlcGxhY2Vfb25jZSh0ZXh0OiBzdHIsIG5lZWRsZTogc3RyLCByZXBsYWNlbWVudDogc3RyLCAqLCBsYWJlbDogc3RyKSAtPiBzdHI6CiAgICBpZiByZXBsYWNlbWVudCBpbiB0ZXh0OgogICAgICAgIHJldHVybiB0ZXh0CiAgICBpZiBuZWVkbGUgbm90IGluIHRleHQ6CiAgICAgICAgcmFpc2UgUnVudGltZUVycm9yKGYiQ291bGQgbm90IGZpbmQge2xhYmVsfSBwYXRjaCBhbmNob3IiKQogICAgcmV0dXJuIHRleHQucmVwbGFjZShuZWVkbGUsIHJlcGxhY2VtZW50LCAxKQoKCmRlZiBwYXRjaF9jaGVja291dChyYXlsaWJfZGlyOiBQYXRoKSAtPiBOb25lOgogICAgaW50ZXJuYWwgPSByYXlsaWJfZGlyIC8gInNyYy9leHRlcm5hbC9nbGZ3L3NyYy9pbnRlcm5hbC5oIgogICAgdGV4dCA9IGludGVybmFsLnJlYWRfdGV4dCgpCiAgICB0ZXh0ID0gcmVwbGFjZV9vbmNlKAogICAgICAgIHRleHQsCiAgICAgICAgIiNkZWZpbmUgRUdMX1dJTkRPV19CSVQgMHgwMDA0XG4iLAogICAgICAgICIjZGVmaW5lIEVHTF9QQlVGRkVSX0JJVCAweDAwMDFcbiNkZWZpbmUgRUdMX1dJTkRPV19CSVQgMHgwMDA0XG4iLAogICAgICAgIGxhYmVsPSJFR0xfUEJVRkZFUl9CSVQiLAogICAgKQogICAgdGV4dCA9IHJlcGxhY2Vfb25jZSgKICAgICAgICB0ZXh0LAogICAgICAgICIjZGVmaW5lIEVHTF9OQVRJVkVfVklTVUFMX0lEIDB4MzAyZVxuIiwKICAgICAgICAiI2RlZmluZSBFR0xfTkFUSVZFX1ZJU1VBTF9JRCAweDMwMmVcbiNkZWZpbmUgRUdMX1dJRFRIIDB4MzA1N1xuI2RlZmluZSBFR0xfSEVJR0hUIDB4MzA1NlxuIiwKICAgICAgICBsYWJlbD0iRUdMIHBidWZmZXIgZGltZW5zaW9ucyIsCiAgICApCiAgICB0ZXh0ID0gcmVwbGFjZV9vbmNlKAogICAgICAgIHRleHQsCiAgICAgICAgInR5cGVkZWYgRUdMU3VyZmFjZSAoQVBJRU5UUlkgKiBQRk5fZWdsQ3JlYXRlV2luZG93U3VyZmFjZSkoRUdMRGlzcGxheSxFR0xDb25maWcsRUdMTmF0aXZlV2luZG93VHlwZSxjb25zdCBFR0xpbnQqKTtcbiIsCiAgICAgICAgInR5cGVkZWYgRUdMU3VyZmFjZSAoQVBJRU5UUlkgKiBQRk5fZWdsQ3JlYXRlV2luZG93U3VyZmFjZSkoRUdMRGlzcGxheSxFR0xDb25maWcsRUdMTmF0aXZlV2luZG93VHlwZSxjb25zdCBFR0xpbnQqKTtcbiIKICAgICAgICAidHlwZWRlZiBFR0xTdXJmYWNlIChBUElFTlRSWSAqIFBGTl9lZ2xDcmVhdGVQYnVmZmVyU3VyZmFjZSkoRUdMRGlzcGxheSxFR0xDb25maWcsY29uc3QgRUdMaW50Kik7XG4iLAogICAgICAgIGxhYmVsPSJQRk5fZWdsQ3JlYXRlUGJ1ZmZlclN1cmZhY2UgdHlwZWRlZiIsCiAgICApCiAgICB0ZXh0ID0gcmVwbGFjZV9vbmNlKAogICAgICAgIHRleHQsCiAgICAgICAgIiNkZWZpbmUgZWdsQ3JlYXRlV2luZG93U3VyZmFjZSBfZ2xmdy5lZ2wuQ3JlYXRlV2luZG93U3VyZmFjZVxuIiwKICAgICAgICAiI2RlZmluZSBlZ2xDcmVhdGVXaW5kb3dTdXJmYWNlIF9nbGZ3LmVnbC5DcmVhdGVXaW5kb3dTdXJmYWNlXG4iCiAgICAgICAgIiNkZWZpbmUgZWdsQ3JlYXRlUGJ1ZmZlclN1cmZhY2UgX2dsZncuZWdsLkNyZWF0ZVBidWZmZXJTdXJmYWNlXG4iLAogICAgICAgIGxhYmVsPSJlZ2xDcmVhdGVQYnVmZmVyU3VyZmFjZSBtYWNybyIsCiAgICApCiAgICB0ZXh0ID0gcmVwbGFjZV9vbmNlKAogICAgICAgIHRleHQsCiAgICAgICAgIiAgICAgICAgUEZOX2VnbENyZWF0ZVdpbmRvd1N1cmZhY2UgIENyZWF0ZVdpbmRvd1N1cmZhY2U7XG4iLAogICAgICAgICIgICAgICAgIFBGTl9lZ2xDcmVhdGVXaW5kb3dTdXJmYWNlICBDcmVhdGVXaW5kb3dTdXJmYWNlO1xuIgogICAgICAgICIgICAgICAgIFBGTl9lZ2xDcmVhdGVQYnVmZmVyU3VyZmFjZSBDcmVhdGVQYnVmZmVyU3VyZmFjZTtcbiIsCiAgICAgICAgbGFiZWw9IkNyZWF0ZVBidWZmZXJTdXJmYWNlIGZpZWxkIiwKICAgICkKICAgIGludGVybmFsLndyaXRlX3RleHQodGV4dCkKCiAgICBwbGF0Zm9ybV9jID0gcmF5bGliX2RpciAvICJzcmMvZXh0ZXJuYWwvZ2xmdy9zcmMvcGxhdGZvcm0uYyIKICAgIHRleHQgPSBwbGF0Zm9ybV9jLnJlYWRfdGV4dCgpCiAgICB0ZXh0ID0gcmVwbGFjZV9vbmNlKAogICAgICAgIHRleHQsCiAgICAgICAgIiNpZiBkZWZpbmVkKF9HTEZXX1gxMSlcbiAgICB7IEdMRldfUExBVEZPUk1fWDExLCBfZ2xmd0Nvbm5lY3RYMTEgfSxcbiNlbmRpZlxufTtcbiIsCiAgICAgICAgIiNpZiBkZWZpbmVkKF9HTEZXX1gxMSlcbiAgICB7IEdMRldfUExBVEZPUk1fWDExLCBfZ2xmd0Nvbm5lY3RYMTEgfSxcbiNlbmRpZlxuIgogICAgICAgICIgICAgeyBHTEZXX1BMQVRGT1JNX05VTEwsIF9nbGZ3Q29ubmVjdE51bGwgfSxcbn07XG4iLAogICAgICAgIGxhYmVsPSJudWxsIHBsYXRmb3JtIHNlbGVjdG9yIiwKICAgICkKICAgIHRleHQgPSByZXBsYWNlX29uY2UoCiAgICAgICAgdGV4dCwKICAgICAgICAiICAgIGNvbnN0IHNpemVfdCBjb3VudCA9IHNpemVvZihzdXBwb3J0ZWRQbGF0Zm9ybXMpIC8gc2l6ZW9mKHN1cHBvcnRlZFBsYXRmb3Jtc1swXSk7XG4gICAgc2l6ZV90IGk7XG5cbiIsCiAgICAgICAgIiAgICBjb25zdCBzaXplX3QgY291bnQgPSBzaXplb2Yoc3VwcG9ydGVkUGxhdGZvcm1zKSAvIHNpemVvZihzdXBwb3J0ZWRQbGF0Zm9ybXNbMF0pO1xuICAgIHNpemVfdCBpO1xuXG4iCiAgICAgICAgIiAgICBpZiAoZ2V0ZW52KFwiT1BFTlBJTE9UX1VJX05VTExfRUdMXCIpKVxuICAgIHtcbiIKICAgICAgICAiICAgICAgICBmcHJpbnRmKHN0ZGVyciwgXCJHTEZXIGZvcmNlZCBudWxsIGNvbm5lY3RcXG5cIik7XG4iCiAgICAgICAgIiAgICAgICAgcmV0dXJuIF9nbGZ3Q29ubmVjdE51bGwoR0xGV19QTEFURk9STV9OVUxMLCBwbGF0Zm9ybSk7XG4iCiAgICAgICAgIiAgICB9XG5cbiIsCiAgICAgICAgbGFiZWw9Im51bGwgcGxhdGZvcm0gZW52IG92ZXJyaWRlIiwKICAgICkKICAgIHBsYXRmb3JtX2Mud3JpdGVfdGV4dCh0ZXh0KQoKICAgIHJjb3JlID0gcmF5bGliX2RpciAvICJzcmMvcGxhdGZvcm1zL3Jjb3JlX2Rlc2t0b3BfZ2xmdy5jIgogICAgdGV4dCA9IHJjb3JlLnJlYWRfdGV4dCgpCiAgICB0ZXh0ID0gcmVwbGFjZV9vbmNlKAogICAgICAgIHRleHQsCiAgICAgICAgIiNpZiBkZWZpbmVkKF9fQVBQTEVfXylcbiAgICBnbGZ3SW5pdEhpbnQoR0xGV19DT0NPQV9DSERJUl9SRVNPVVJDRVMsIEdMRldfRkFMU0UpO1xuI2VuZGlmXG4gICAgLy8gSW5pdGlhbGl6ZSBHTEZXIGludGVybmFsIGdsb2JhbCBzdGF0ZVxuIiwKICAgICAgICAiI2lmIGRlZmluZWQoX19BUFBMRV9fKVxuICAgIGdsZndJbml0SGludChHTEZXX0NPQ09BX0NIRElSX1JFU09VUkNFUywgR0xGV19GQUxTRSk7XG4jZW5kaWZcbiIKICAgICAgICAiICAgIGlmIChnZXRlbnYoXCJPUEVOUElMT1RfVUlfTlVMTF9FR0xcIikpIGdsZndJbml0SGludChHTEZXX1BMQVRGT1JNLCBHTEZXX1BMQVRGT1JNX05VTEwpO1xuIgogICAgICAgICIgICAgLy8gSW5pdGlhbGl6ZSBHTEZXIGludGVybmFsIGdsb2JhbCBzdGF0ZVxuIiwKICAgICAgICBsYWJlbD0iZ2xmd0luaXQgbnVsbCBoaW50IiwKICAgICkKICAgIHRleHQgPSByZXBsYWNlX29uY2UoCiAgICAgICAgdGV4dCwKICAgICAgICAiICAgIGdsZndEZWZhdWx0V2luZG93SGludHMoKTsgICAgICAgICAgICAgICAgICAgICAgIC8vIFNldCBkZWZhdWx0IHdpbmRvd3MgaGludHNcbiIsCiAgICAgICAgIiAgICBnbGZ3RGVmYXVsdFdpbmRvd0hpbnRzKCk7ICAgICAgICAgICAgICAgICAgICAgICAvLyBTZXQgZGVmYXVsdCB3aW5kb3dzIGhpbnRzXG4iCiAgICAgICAgIiAgICBpZiAoZ2V0ZW52KFwiT1BFTlBJTE9UX1VJX05VTExfRUdMXCIpKSBnbGZ3V2luZG93SGludChHTEZXX0NPTlRFWFRfQ1JFQVRJT05fQVBJLCBHTEZXX0VHTF9DT05URVhUX0FQSSk7XG4iLAogICAgICAgIGxhYmVsPSJnbGZ3IEVHTCBoaW50IiwKICAgICkKICAgIHJjb3JlLndyaXRlX3RleHQodGV4dCkKCiAgICBlZ2wgPSByYXlsaWJfZGlyIC8gInNyYy9leHRlcm5hbC9nbGZ3L3NyYy9lZ2xfY29udGV4dC5jIgogICAgdGV4dCA9IGVnbC5yZWFkX3RleHQoKQogICAgdGV4dCA9IHJlcGxhY2Vfb25jZSgKICAgICAgICB0ZXh0LAogICAgICAgICIgICAgX2dsZncuZWdsLkNyZWF0ZVdpbmRvd1N1cmZhY2UgPSAoUEZOX2VnbENyZWF0ZVdpbmRvd1N1cmZhY2UpXG4gICAgICAgIF9nbGZ3UGxhdGZvcm1HZXRNb2R1bGVTeW1ib2woX2dsZncuZWdsLmhhbmRsZSwgXCJlZ2xDcmVhdGVXaW5kb3dTdXJmYWNlXCIpO1xuIiwKICAgICAgICAiICAgIF9nbGZ3LmVnbC5DcmVhdGVXaW5kb3dTdXJmYWNlID0gKFBGTl9lZ2xDcmVhdGVXaW5kb3dTdXJmYWNlKVxuIgogICAgICAgICIgICAgICAgIF9nbGZ3UGxhdGZvcm1HZXRNb2R1bGVTeW1ib2woX2dsZncuZWdsLmhhbmRsZSwgXCJlZ2xDcmVhdGVXaW5kb3dTdXJmYWNlXCIpO1xuIgogICAgICAgICIgICAgX2dsZncuZWdsLkNyZWF0ZVBidWZmZXJTdXJmYWNlID0gKFBGTl9lZ2xDcmVhdGVQYnVmZmVyU3VyZmFjZSlcbiIKICAgICAgICAiICAgICAgICBfZ2xmd1BsYXRmb3JtR2V0TW9kdWxlU3ltYm9sKF9nbGZ3LmVnbC5oYW5kbGUsIFwiZWdsQ3JlYXRlUGJ1ZmZlclN1cmZhY2VcIik7XG4iLAogICAgICAgIGxhYmVsPSJlZ2xDcmVhdGVQYnVmZmVyU3VyZmFjZSBsb2FkZXIiLAogICAgKQogICAgdGV4dCA9IHJlcGxhY2Vfb25jZSgKICAgICAgICB0ZXh0LAogICAgICAgICIgICAgICAgICFfZ2xmdy5lZ2wuQ3JlYXRlV2luZG93U3VyZmFjZSB8fFxuIiwKICAgICAgICAiICAgICAgICAhX2dsZncuZWdsLkNyZWF0ZVdpbmRvd1N1cmZhY2UgfHxcbiIKICAgICAgICAiICAgICAgICAhX2dsZncuZWdsLkNyZWF0ZVBidWZmZXJTdXJmYWNlIHx8XG4iLAogICAgICAgIGxhYmVsPSJDcmVhdGVQYnVmZmVyU3VyZmFjZSByZXF1aXJlZCBjaGVjayIsCiAgICApCiAgICB0ZXh0ID0gcmVwbGFjZV9vbmNlKAogICAgICAgIHRleHQsCiAgICAgICAgIiAgICAgICAgLy8gT25seSBjb25zaWRlciB3aW5kb3cgRUdMQ29uZmlnc1xuICAgICAgICBpZiAoIShnZXRFR0xDb25maWdBdHRyaWIobiwgRUdMX1NVUkZBQ0VfVFlQRSkgJiBFR0xfV0lORE9XX0JJVCkpXG4gICAgICAgICAgICBjb250aW51ZTtcbiIsCiAgICAgICAgIiAgICAgICAgLy8gT25seSBjb25zaWRlciBzdXJmYWNlLWNhcGFibGUgY29uZmlnc1xuIgogICAgICAgICIgICAgICAgIGlmIChfZ2xmdy5wbGF0Zm9ybS5wbGF0Zm9ybUlEID09IEdMRldfUExBVEZPUk1fTlVMTClcbiIKICAgICAgICAiICAgICAgICB7XG4iCiAgICAgICAgIiAgICAgICAgICAgIGlmICghKGdldEVHTENvbmZpZ0F0dHJpYihuLCBFR0xfU1VSRkFDRV9UWVBFKSAmIEVHTF9QQlVGRkVSX0JJVCkpXG4iCiAgICAgICAgIiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiIKICAgICAgICAiICAgICAgICB9XG4iCiAgICAgICAgIiAgICAgICAgZWxzZVxuIgogICAgICAgICIgICAgICAgIHtcbiIKICAgICAgICAiICAgICAgICAgICAgaWYgKCEoZ2V0RUdMQ29uZmlnQXR0cmliKG4sIEVHTF9TVVJGQUNFX1RZUEUpICYgRUdMX1dJTkRPV19CSVQpKVxuIgogICAgICAgICIgICAgICAgICAgICAgICAgY29udGludWU7XG4iCiAgICAgICAgIiAgICAgICAgfVxuIiwKICAgICAgICBsYWJlbD0ibnVsbCBFR0wgY29uZmlnIGZpbHRlcmluZyIsCiAgICApCiAgICB0ZXh0ID0gcmVwbGFjZV9vbmNlKAogICAgICAgIHRleHQsCiAgICAgICAgIiAgICBuYXRpdmUgPSBfZ2xmdy5wbGF0Zm9ybS5nZXRFR0xOYXRpdmVXaW5kb3cod2luZG93KTtcbiIKICAgICAgICAiICAgIC8vIEhBQ0s6IEFOR0xFIGRvZXMgbm90IGltcGxlbWVudCBlZ2xDcmVhdGVQbGF0Zm9ybVdpbmRvd1N1cmZhY2VFWFRcbiIKICAgICAgICAiICAgIC8vICAgICAgIGRlc3BpdGUgcmVwb3J0aW5nIEVHTF9FWFRfcGxhdGZvcm1fYmFzZVxuIgogICAgICAgICIgICAgaWYgKF9nbGZ3LmVnbC5wbGF0Zm9ybSAmJiBfZ2xmdy5lZ2wucGxhdGZvcm0gIT0gRUdMX1BMQVRGT1JNX0FOR0xFX0FOR0xFKVxuIgogICAgICAgICIgICAge1xuIgogICAgICAgICIgICAgICAgIHdpbmRvdy0+Y29udGV4dC5lZ2wuc3VyZmFjZSA9XG4iCiAgICAgICAgIiAgICAgICAgICAgIGVnbENyZWF0ZVBsYXRmb3JtV2luZG93U3VyZmFjZUVYVChfZ2xmdy5lZ2wuZGlzcGxheSwgY29uZmlnLCBuYXRpdmUsIGF0dHJpYnMpO1xuIgogICAgICAgICIgICAgfVxuIgogICAgICAgICIgICAgZWxzZVxuIgogICAgICAgICIgICAge1xuIgogICAgICAgICIgICAgICAgIHdpbmRvdy0+Y29udGV4dC5lZ2wuc3VyZmFjZSA9XG4iCiAgICAgICAgIiAgICAgICAgICAgIGVnbENyZWF0ZVdpbmRvd1N1cmZhY2UoX2dsZncuZWdsLmRpc3BsYXksIGNvbmZpZywgbmF0aXZlLCBhdHRyaWJzKTtcbiIKICAgICAgICAiICAgIH1cbiIsCiAgICAgICAgIiAgICBpZiAoX2dsZncucGxhdGZvcm0ucGxhdGZvcm1JRCA9PSBHTEZXX1BMQVRGT1JNX05VTEwpXG4iCiAgICAgICAgIiAgICB7XG4iCiAgICAgICAgIiAgICAgICAgY29uc3QgRUdMaW50IHBidWZmZXJBdHRyaWJzW10gPSB7XG4iCiAgICAgICAgIiAgICAgICAgICAgIEVHTF9XSURUSCwgd2luZG93LT5udWxsLndpZHRoID4gMCA/IHdpbmRvdy0+bnVsbC53aWR0aCA6IDEsXG4iCiAgICAgICAgIiAgICAgICAgICAgIEVHTF9IRUlHSFQsIHdpbmRvdy0+bnVsbC5oZWlnaHQgPiAwID8gd2luZG93LT5udWxsLmhlaWdodCA6IDEsXG4iCiAgICAgICAgIiAgICAgICAgICAgIEVHTF9OT05FXG4iCiAgICAgICAgIiAgICAgICAgfTtcbiIKICAgICAgICAiICAgICAgICB3aW5kb3ctPmNvbnRleHQuZWdsLnN1cmZhY2UgPVxuIgogICAgICAgICIgICAgICAgICAgICBlZ2xDcmVhdGVQYnVmZmVyU3VyZmFjZShfZ2xmdy5lZ2wuZGlzcGxheSwgY29uZmlnLCBwYnVmZmVyQXR0cmlicyk7XG4iCiAgICAgICAgIiAgICB9XG4iCiAgICAgICAgIiAgICBlbHNlXG4iCiAgICAgICAgIiAgICB7XG4iCiAgICAgICAgIiAgICAgICAgbmF0aXZlID0gX2dsZncucGxhdGZvcm0uZ2V0RUdMTmF0aXZlV2luZG93KHdpbmRvdyk7XG4iCiAgICAgICAgIiAgICAgICAgLy8gSEFDSzogQU5HTEUgZG9lcyBub3QgaW1wbGVtZW50IGVnbENyZWF0ZVBsYXRmb3JtV2luZG93U3VyZmFjZUVYVFxuIgogICAgICAgICIgICAgICAgIC8vICAgICAgIGRlc3BpdGUgcmVwb3J0aW5nIEVHTF9FWFRfcGxhdGZvcm1fYmFzZVxuIgogICAgICAgICIgICAgICAgIGlmIChfZ2xmdy5lZ2wucGxhdGZvcm0gJiYgX2dsZncuZWdsLnBsYXRmb3JtICE9IEVHTF9QTEFURk9STV9BTkdMRV9BTkdMRSlcbiIKICAgICAgICAiICAgICAgICB7XG4iCiAgICAgICAgIiAgICAgICAgICAgIHdpbmRvdy0+Y29udGV4dC5lZ2wuc3VyZmFjZSA9XG4iCiAgICAgICAgIiAgICAgICAgICAgICAgICBlZ2xDcmVhdGVQbGF0Zm9ybVdpbmRvd1N1cmZhY2VFWFQoX2dsZncuZWdsLmRpc3BsYXksIGNvbmZpZywgbmF0aXZlLCBhdHRyaWJzKTtcbiIKICAgICAgICAiICAgICAgICB9XG4iCiAgICAgICAgIiAgICAgICAgZWxzZVxuIgogICAgICAgICIgICAgICAgIHtcbiIKICAgICAgICAiICAgICAgICAgICAgd2luZG93LT5jb250ZXh0LmVnbC5zdXJmYWNlID1cbiIKICAgICAgICAiICAgICAgICAgICAgICAgIGVnbENyZWF0ZVdpbmRvd1N1cmZhY2UoX2dsZncuZWdsLmRpc3BsYXksIGNvbmZpZywgbmF0aXZlLCBhdHRyaWJzKTtcbiIKICAgICAgICAiICAgICAgICB9XG4iCiAgICAgICAgIiAgICB9XG4iLAogICAgICAgIGxhYmVsPSJudWxsIHBidWZmZXIgc3VyZmFjZSBjcmVhdGlvbiIsCiAgICApCiAgICBlZ2wud3JpdGVfdGV4dCh0ZXh0KQoKCmRlZiBwYXRjaF9weXJheV9jaGVja291dChweXJheV9kaXI6IFBhdGgpIC0+IE5vbmU6CiAgICBidWlsZF9weSA9IHB5cmF5X2RpciAvICJyYXlsaWIvYnVpbGQucHkiCiAgICB0ZXh0ID0gYnVpbGRfcHkucmVhZF90ZXh0KCkKICAgIHRleHQgPSByZXBsYWNlX29uY2UoCiAgICAgICAgdGV4dCwKICAgICAgICAiICAgICAgICBleHRyYV9saW5rX2FyZ3MgPSBnZXRfbGliX2ZsYWdzKCkgKyBbICctbG0nLCAnLWxwdGhyZWFkJywgJy1sR0wnLFxuIgogICAgICAgICIgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJy1scnQnLCAnLWxtJywgJy1sZGwnLCAnLWxwdGhyZWFkJywgJy1sYXRvbWljJ11cbiIsCiAgICAgICAgIiAgICAgICAgZXh0cmFfbGlua19hcmdzID0gW29zLnBhdGguam9pbihnZXRfdGhlX2xpYl9wYXRoKCksICdsaWJyYXlsaWIuYScpLCAnLWxtJywgJy1scHRocmVhZCcsICctbEdMJyxcbiIKICAgICAgICAiICAgICAgICAgICAgICAgICAgICAgICAgICAgJy1sRUdMJywgJy1scnQnLCAnLWxtJywgJy1sZGwnLCAnLWxwdGhyZWFkJywgJy1sYXRvbWljJ11cbiIsCiAgICAgICAgbGFiZWw9ImRpcmVjdCBzdGF0aWMgcmF5bGliIGxpbmsiLAogICAgKQogICAgYnVpbGRfcHkud3JpdGVfdGV4dCh0ZXh0KQoKCndpdGggdGVtcGZpbGUuVGVtcG9yYXJ5RGlyZWN0b3J5KHByZWZpeD0icHlyYXktbnVsbC1lZ2wtIikgYXMgdG1wOgogICAgdG1wZGlyID0gUGF0aCh0bXApCiAgICByYXlsaWJfZGlyID0gdG1wZGlyIC8gInJheWxpYiIKICAgIHB5cmF5X2RpciA9IHRtcGRpciAvICJyYXlsaWItcHl0aG9uLWNmZmkiCiAgICBzdGFnZV9kaXIgPSB0bXBkaXIgLyAic3RhZ2UiCiAgICBpbmNsdWRlX2RpciA9IHN0YWdlX2RpciAvICJpbmNsdWRlIgogICAgZ2xmd19pbmNsdWRlX2RpciA9IGluY2x1ZGVfZGlyIC8gIkdMRlciCiAgICBsaWJfZGlyID0gc3RhZ2VfZGlyIC8gImxpYiIKICAgIGdsZndfaW5jbHVkZV9kaXIubWtkaXIocGFyZW50cz1UcnVlLCBleGlzdF9vaz1UcnVlKQogICAgbGliX2Rpci5ta2RpcihwYXJlbnRzPVRydWUsIGV4aXN0X29rPVRydWUpCiAgICBjbWFrZV9jbWQgPSBlbnN1cmVfbW9kZXJuX2NtYWtlKCkKCiAgICBydW4oWyJnaXQiLCAiY2xvbmUiLCAiLS1kZXB0aD0xIiwgcmF5bGliX3JlcG8sIHN0cihyYXlsaWJfZGlyKV0pCiAgICBwYXRjaF9jaGVja291dChyYXlsaWJfZGlyKQogICAgcnVuKAogICAgICAgIFsKICAgICAgICAgICAgKmNtYWtlX2NtZCwKICAgICAgICAgICAgIi1TIiwKICAgICAgICAgICAgc3RyKHJheWxpYl9kaXIpLAogICAgICAgICAgICAiLUIiLAogICAgICAgICAgICBzdHIocmF5bGliX2RpciAvICJidWlsZCIpLAogICAgICAgICAgICAiLURQTEFURk9STT1EZXNrdG9wIiwKICAgICAgICAgICAgIi1ER0xGV19CVUlMRF9OVUxMPU9OIiwKICAgICAgICAgICAgIi1ER0xGV19CVUlMRF9XQVlMQU5EPU9GRiIsCiAgICAgICAgICAgICItREdMRldfQlVJTERfWDExPU9OIiwKICAgICAgICAgICAgIi1EQlVJTERfU0hBUkVEX0xJQlM9T0ZGIiwKICAgICAgICAgICAgIi1EQ01BS0VfQlVJTERfVFlQRT1SZWxlYXNlIiwKICAgICAgICAgICAgIi1EV0lUSF9QSUM9T04iLAogICAgICAgICAgICAiLURCVUlMRF9FWEFNUExFUz1PRkYiLAogICAgICAgICAgICAiLURCVUlMRF9HQU1FUz1PRkYiLAogICAgICAgIF0KICAgICkKICAgIGpvYnMgPSBjYXB0dXJlKFsiYmFzaCIsICItbGMiLCAibnByb2MgfHwgZWNobyA4Il0pCiAgICBydW4oWypjbWFrZV9jbWQsICItLWJ1aWxkIiwgc3RyKHJheWxpYl9kaXIgLyAiYnVpbGQiKSwgIi1qIiwgam9ic10pCgogICAgc2h1dGlsLmNvcHkyKHJheWxpYl9kaXIgLyAiYnVpbGQvcmF5bGliL2xpYnJheWxpYi5hIiwgbGliX2RpciAvICJsaWJyYXlsaWIuYSIpCiAgICBmb3IgaGVhZGVyIGluICgicmF5bGliLmgiLCAicmxnbC5oIiwgInJheW1hdGguaCIpOgogICAgICAgIHNodXRpbC5jb3B5MihyYXlsaWJfZGlyIC8gInNyYyIgLyBoZWFkZXIsIGluY2x1ZGVfZGlyIC8gaGVhZGVyKQogICAgc2h1dGlsLmNvcHkyKHJheWxpYl9kaXIgLyAic3JjL2V4dGVybmFsL2dsZncvaW5jbHVkZS9HTEZXL2dsZnczLmgiLCBnbGZ3X2luY2x1ZGVfZGlyIC8gImdsZnczLmgiKQogICAgcnVuKFsiY3VybCIsICItZnNTTG8iLCBzdHIoaW5jbHVkZV9kaXIgLyAicmF5Z3VpLmgiKSwgcmF5Z3VpX3VybF0pCgogICAgcnVuKFsiZ2l0IiwgImNsb25lIiwgIi0tZGVwdGg9MSIsIHB5cmF5X3JlcG8sIHN0cihweXJheV9kaXIpXSkKICAgIHBhdGNoX3B5cmF5X2NoZWNrb3V0KHB5cmF5X2RpcikKICAgIGVudiA9IGRpY3Qob3MuZW52aXJvbikKICAgIGVudlsiUkFZTElCX1BMQVRGT1JNIl0gPSAiRGVza3RvcCIKICAgIGVudlsiUkFZTElCX0lOQ0xVREVfUEFUSCJdID0gc3RyKGluY2x1ZGVfZGlyKQogICAgZW52WyJSQVlMSUJfTElCX1BBVEgiXSA9IHN0cihsaWJfZGlyKQogICAgZW5zdXJlX3BpcChweXRob25fYmluKQogICAgcnVuKFtweXRob25fYmluLCAiLW0iLCAicGlwIiwgIndoZWVsIiwgIi4iLCAiLXciLCAiZGlzdCJdLCBjd2Q9cHlyYXlfZGlyLCBlbnY9ZW52KQogICAgd2hlZWxzID0gc29ydGVkKChweXJheV9kaXIgLyAiZGlzdCIpLmdsb2IoIioud2hsIikpCiAgICBydW4oW3B5dGhvbl9iaW4sICItbSIsICJwaXAiLCAiaW5zdGFsbCIsICItLWZvcmNlLXJlaW5zdGFsbCIsICItLW5vLWRlcHMiLCAqbWFwKHN0ciwgd2hlZWxzKV0pCiAgICBydW4oW3B5dGhvbl9iaW4sICItbSIsICJwaXAiLCAiaW5zdGFsbCIsICJjZmZpPj0xLjE3LjEiXSkKICAgIHZlcmlmeV9pbnN0YWxsZWRfcHlyYXkocHl0aG9uX2JpbikKUFkKfQoKcGF0Y2hfZm9udF9wcm9jZXNzX3JheWxpYjYoKSB7CiAgbG9jYWwgcHJvY2Vzc19weT0iJHtPUEVOUElMT1RfUk9PVH0vc2VsZmRyaXZlL2Fzc2V0cy9mb250cy9wcm9jZXNzLnB5IgogIGlmIFtbICEgLWYgIiR7cHJvY2Vzc19weX0iIF1dOyB0aGVuCiAgICByZXR1cm4KICBmaQoKICBpZiAhIGdyZXAgLXEgJ2xvYWRfZm9udF9kYXRhKCcgIiR7cHJvY2Vzc19weX0iOyB0aGVuCiAgICByZXR1cm4KICBmaQogIGlmIGdyZXAgLXEgJ2FjdHVhbF9nbHlwaF9jb3VudCcgIiR7cHJvY2Vzc19weX0iOyB0aGVuCiAgICByZXR1cm4KICBmaQoKICBsb2dfc3RlcCAiUGF0Y2hpbmcgcHJvY2Vzcy5weSBmb3IgcmF5bGliIDYuMCBsb2FkX2ZvbnRfZGF0YSBBUEkiCiAgcHl0aG9uMyAtICIke3Byb2Nlc3NfcHl9IiA8PCdQWScKZnJvbSBfX2Z1dHVyZV9fIGltcG9ydCBhbm5vdGF0aW9ucwppbXBvcnQgc3lzCmZyb20gcGF0aGxpYiBpbXBvcnQgUGF0aAoKcGF0aCA9IFBhdGgoc3lzLmFyZ3ZbMV0pCnRleHQgPSBwYXRoLnJlYWRfdGV4dCgpCgpvbGQgPSAoCiAgICAiICBnbHlwaHMgPSBybC5sb2FkX2ZvbnRfZGF0YShybC5mZmkuY2FzdChcInVuc2lnbmVkIGNoYXIgKlwiLCBmaWxlX2J1ZiksICIKICAgICJsZW4oZGF0YSksIGZvbnRfc2l6ZSwgY3BfcHRyLCBsZW4oY29kZXBvaW50cyksIHJsLkZvbnRUeXBlLkZPTlRfREVGQVVMVClcbiIKICAgICIgIGlmIGdseXBocyA9PSBybC5mZmkuTlVMTDpcbiIKICAgICIgICAgcmFpc2UgUnVudGltZUVycm9yKFwicmF5bGliIGZhaWxlZCB0byBsb2FkIGZvbnQgZGF0YVwiKVxuIgogICAgIlxuIgogICAgIiAgcmVjdHNfcHRyID0gcmwuZmZpLm5ldyhcIlJlY3RhbmdsZSAqKlwiKVxuIgogICAgIiAgaW1hZ2UgPSBybC5nZW5faW1hZ2VfZm9udF9hdGxhcyhnbHlwaHMsIHJlY3RzX3B0ciwgbGVuKGNvZGVwb2ludHMpLCAiCiAgICAiZm9udF9zaXplLCBHTFlQSF9QQURESU5HLCAwKVxuIgogICAgIiAgaWYgaW1hZ2Uud2lkdGggPT0gMCBvciBpbWFnZS5oZWlnaHQgPT0gMDpcbiIKICAgICIgICAgcmFpc2UgUnVudGltZUVycm9yKFwicmF5bGliIHJldHVybmVkIGFuIGVtcHR5IGF0bGFzXCIpXG4iCiAgICAiXG4iCiAgICAiICByZWN0cyA9IHJlY3RzX3B0clswXVxuIgogICAgIiAgYXRsYXNfbmFtZSA9IGZcIntmb250X3BhdGguc3RlbX0ucG5nXCJcbiIKICAgICIgIGF0bGFzX3BhdGggPSBGT05UX0RJUiAvIGF0bGFzX25hbWVcbiIKICAgICIgIGVudHJpZXMsIGxpbmVfaGVpZ2h0LCBiYXNlID0gX2dseXBoX21ldHJpY3MoZ2x5cGhzLCByZWN0cywgY29kZXBvaW50cylcbiIKKQoKbmV3ID0gKAogICAgIiAgZ2x5cGhfY291bnRfcHRyID0gcmwuZmZpLm5ldyhcImludCAqXCIsIDApXG4iCiAgICAiICBnbHlwaHMgPSBybC5sb2FkX2ZvbnRfZGF0YShybC5mZmkuY2FzdChcInVuc2lnbmVkIGNoYXIgKlwiLCBmaWxlX2J1ZiksICIKICAgICJsZW4oZGF0YSksIGZvbnRfc2l6ZSwgY3BfcHRyLCBsZW4oY29kZXBvaW50cyksIHJsLkZvbnRUeXBlLkZPTlRfREVGQVVMVCwgZ2x5cGhfY291bnRfcHRyKVxuIgogICAgIiAgaWYgZ2x5cGhzID09IHJsLmZmaS5OVUxMOlxuIgogICAgIiAgICByYWlzZSBSdW50aW1lRXJyb3IoXCJyYXlsaWIgZmFpbGVkIHRvIGxvYWQgZm9udCBkYXRhXCIpXG4iCiAgICAiXG4iCiAgICAiICBhY3R1YWxfZ2x5cGhfY291bnQgPSBnbHlwaF9jb3VudF9wdHJbMF1cbiIKICAgICIgIHJlY3RzX3B0ciA9IHJsLmZmaS5uZXcoXCJSZWN0YW5nbGUgKipcIilcbiIKICAgICIgIGltYWdlID0gcmwuZ2VuX2ltYWdlX2ZvbnRfYXRsYXMoZ2x5cGhzLCByZWN0c19wdHIsIGFjdHVhbF9nbHlwaF9jb3VudCwgIgogICAgImZvbnRfc2l6ZSwgR0xZUEhfUEFERElORywgMClcbiIKICAgICIgIGlmIGltYWdlLndpZHRoID09IDAgb3IgaW1hZ2UuaGVpZ2h0ID09IDA6XG4iCiAgICAiICAgIHJhaXNlIFJ1bnRpbWVFcnJvcihcInJheWxpYiByZXR1cm5lZCBhbiBlbXB0eSBhdGxhc1wiKVxuIgogICAgIlxuIgogICAgIiAgcmVjdHMgPSByZWN0c19wdHJbMF1cbiIKICAgICIgIGF0bGFzX25hbWUgPSBmXCJ7Zm9udF9wYXRoLnN0ZW19LnBuZ1wiXG4iCiAgICAiICBhdGxhc19wYXRoID0gRk9OVF9ESVIgLyBhdGxhc19uYW1lXG4iCiAgICAiICBmb3VuZF9jb2RlcG9pbnRzID0gdHVwbGUoaW50KGdseXBoc1tpXS52YWx1ZSkgZm9yIGkgaW4gcmFuZ2UoYWN0dWFsX2dseXBoX2NvdW50KSlcbiIKICAgICIgIGVudHJpZXMsIGxpbmVfaGVpZ2h0LCBiYXNlID0gX2dseXBoX21ldHJpY3MoZ2x5cGhzLCByZWN0cywgZm91bmRfY29kZXBvaW50cylcbiIKKQoKaWYgb2xkIG5vdCBpbiB0ZXh0OgogICAgcHJpbnQoInBhdGNoIGFuY2hvciBub3QgZm91bmQgaW4gcHJvY2Vzcy5weTsgc2tpcHBpbmciLCBmbHVzaD1UcnVlKQogICAgcmFpc2UgU3lzdGVtRXhpdCgwKQoKdGV4dCA9IHRleHQucmVwbGFjZShvbGQsIG5ldywgMSkKcGF0aC53cml0ZV90ZXh0KHRleHQpCnByaW50KGYicGF0Y2hlZCB7cGF0aH0iLCBmbHVzaD1UcnVlKQpQWQp9CgpnZW5lcmF0ZV91aV9mb250cygpIHsKICBsb2dfc3RlcCAiR2VuZXJhdGluZyBVSSBmb250IGF0bGFzZXMiCiAgY2QgIiR7T1BFTlBJTE9UX1JPT1R9IgogIHBhdGNoX2ZvbnRfcHJvY2Vzc19yYXlsaWI2CiAgdXYgcnVuIC0tbm8tc3luYyBweXRob24gc2VsZmRyaXZlL2Fzc2V0cy9mb250cy9wcm9jZXNzLnB5Cn0KCnJlY29yZF9jaGVja291dF9jb21taXQoKSB7CiAgbG9nX3N0ZXAgIlJlY29yZGluZyBvcGVucGlsb3QgY29tbWl0IgogIGNkICIke09QRU5QSUxPVF9ST09UfSIKICBnaXQgcmV2LXBhcnNlIEhFQUQgPiAiJHtPUEVOUElMT1RfUk9PVH0vQ09NTUlUIgp9CgpwcnVuZV9vcGVucGlsb3RfY2hlY2tvdXQoKSB7CiAgbG9nX3N0ZXAgIlBydW5pbmcgb3BlbnBpbG90IGNoZWNrb3V0IgogIGNkICIke09QRU5QSUxPVF9ST09UfSIKICBybSAtcmYgLmdpdAogIGZpbmQgLiAtdHlwZSBkIC1uYW1lICdfX3B5Y2FjaGVfXycgLXBydW5lIC1leGVjIHJtIC1yZiB7fSArCiAgZmluZCAuIC10eXBlIGYgXCggLW5hbWUgJyoucHljJyAtbyAtbmFtZSAnKi5weW8nIFwpIC1kZWxldGUKICBybSAtcmYgc2VsZmRyaXZlL2Fzc2V0cy9mb250cy8qLnR0ZiBzZWxmZHJpdmUvYXNzZXRzL2ZvbnRzLyoub3RmCn0KCnBydW5lX29wZW5waWxvdF9idWlsZF9hcnRpZmFjdHMoKSB7CiAgbG9nX3N0ZXAgIlBydW5pbmcgb3BlbnBpbG90IGJ1aWxkIGludGVybWVkaWF0ZXMiCiAgY2QgIiR7T1BFTlBJTE9UX1JPT1R9IgogIGZpbmQgLiAtdHlwZSBmIC1uYW1lICcqLm8nIC1kZWxldGUKICBmaW5kIC4gLXR5cGUgZiAtbmFtZSAnKi5vcycgLWRlbGV0ZQogIGZpbmQgLiAtdHlwZSBmIC1uYW1lICcqLmQnIC1kZWxldGUKICBybSAtcmYgLnNjb25zd3JhcAp9CgpzdHJpcF9kZWJ1Z19zeW1ib2xzKCkgewogIGxvZ19zdGVwICJTdHJpcHBpbmcgZGVidWcgc3ltYm9scyBmcm9tIHNoYXJlZCBsaWJyYXJpZXMiCiAgY2QgIiR7T1BFTlBJTE9UX1JPT1R9IgogIGZpbmQgLiAtdHlwZSBmIC1uYW1lICcqLnNvJyAtbm90IC1wYXRoICcuLy52ZW52LyonIC1leGVjIHN0cmlwIC0tc3RyaXAtdW5uZWVkZWQge30gKyAyPi9kZXYvbnVsbCB8fCB0cnVlCiAgZmluZCAiJHtGQUNFRlVTSU9OX1JPT1R9IiAtdHlwZSBmIC1uYW1lICcqLnNvJyAtbm90IC1wYXRoICcqLy52ZW52LyonIC1leGVjIHN0cmlwIC0tc3RyaXAtdW5uZWVkZWQge30gKyAyPi9kZXYvbnVsbCB8fCB0cnVlCn0KCnJlbW92ZV9idWlsZF9wYWNrYWdlcygpIHsKICBsb2dfc3RlcCAiUmVtb3ZpbmcgYnVpbGQtb25seSBzeXN0ZW0gcGFja2FnZXMiCiAgYXB0LWdldCBwdXJnZSAteSBcCiAgICBidWlsZC1lc3NlbnRpYWwgY21ha2UgXAogICAgbGlieHJhbmRyLWRldiBsaWJ4aW5lcmFtYS1kZXYgbGlieGN1cnNvci1kZXYgbGlieGktZGV2IGxpYnhleHQtZGV2IFwKICAgIGxpYmVnbDEtbWVzYS1kZXYgeG9yZy1kZXYgeHNlcnZlci14b3JnLWRldiBcCiAgICBsaWJkcm0tZGV2IGxpYmdsdm5kLWNvcmUtZGV2IGxpYmdsdm5kLWRldiBsaWJnbHgtZGV2IGxpYmdsLWRldiBcCiAgICBsaWJlZ2wtZGV2IGxpYmdsZXMtZGV2IGxpYm9wZW5nbC1kZXYgXAogICAgbGliZG14LWRldiBsaWJmb250ZW5jLWRldiBsaWJmcy1kZXYgbGlieGF3Ny1kZXYgbGlieGNvbXBvc2l0ZS1kZXYgXAogICAgbGlieGRhbWFnZS1kZXYgbGlieGZpeGVzLWRldiBsaWJ4Zm9udC1kZXYgbGlieGtiZmlsZS1kZXYgbGlieG11LWRldiBcCiAgICBsaWJ4cG0tZGV2IGxpYnhyYW5kci1kZXYgbGlieHJlcy1kZXYgbGlieHRzdC1kZXYgbGlieHYtZGV2IFwKICAgIGxpYnh2bWMtZGV2IGxpYnh4Zjg2ZGdhLWRldiBsaWJ4eGY4NnZtLWRldiBsaWJ4dC1kZXYgbGlieGluZXJhbWEtZGV2IFwKICAgIG1lc2EtY29tbW9uLWRldiBcCiAgICAyPi9kZXYvbnVsbCB8fCB0cnVlCiAgYXB0LWdldCBhdXRvcmVtb3ZlIC15IDI+L2Rldi9udWxsIHx8IHRydWUKfQoKY2xlYW5faW1hZ2VfYXJ0aWZhY3RzKCkgewogIGxvZ19zdGVwICJDbGVhbmluZyBib290c3RyYXAgY2FjaGVzIgogIHJtIC1yZiAvdG1wLyoKICBybSAtcmYgIiR7QlVJTERfVE1QRElSfSIvKgogIHJtIC1yZiAvcm9vdC8uY2FjaGUKICBybSAtcmYgL3Jvb3QvLmxvY2FsL2JpbgogIHJtIC1yZiAvcm9vdC8ubG9jYWwvc2hhcmUvdXYvY2FjaGUKICBybSAtcmYgL3Jvb3QvLmxvY2FsL3NoYXJlL3V2L2FyY2hpdmUKICBybSAtcmYgL3Zhci9saWIvYXB0L2xpc3RzLyoKICBybSAtcmYgL3RtcC8qCn0KCm1haW4oKSB7CiAgaW5zdGFsbF9zeXN0ZW1fcGFja2FnZXMKICBzeW5jX3B5dGhvbl9udmlkaWFfcnVudGltZV9saWJzCiAgY29uZmlndXJlX2J1aWxkX3RlbXBkaXIKICByZWRpcmVjdF9zeXN0ZW1fdG1wCiAgY29uZmlndXJlX2dpdF9sZnMKICBlbnN1cmVfdXZfb25fcGF0aAogIHByZXdhcm1fcmZfZGV0cl93ZWlnaHRzCiAgY2xvbmVfZmFjZWZ1c2lvbl9jaGVja291dAogIGluc3RhbGxfZmFjZWZ1c2lvbl9ydW50aW1lCiAgcHJld2FybV9mYWNlZnVzaW9uX21vZGVscwogIGRlZHVwZV9mYWNlZnVzaW9uX3ZlbnZfZmlsZXMKICBwcnVuZV9mYWNlZnVzaW9uX3VudXNlZF9ydW50aW1lX3BhY2thZ2VzCiAgcHJ1bmVfZmFjZWZ1c2lvbl92ZW52CiAgZGVhY3RpdmF0ZV9mYWNlZnVzaW9uX3ZlbnYKICBwcnVuZV9mYWNlZnVzaW9uX2NoZWNrb3V0CiAgY2xlYW5fdHJhbnNpZW50X3BhY2thZ2VfY2FjaGVzCiAgY2xvbmVfb3BlbnBpbG90X2NoZWNrb3V0CiAgaW5zdGFsbF9vcGVucGlsb3RfZGVwZW5kZW5jaWVzCiAgZml4X3ZlbmRvcmVkX3Rvb2xfcGVybWlzc2lvbnMKICBidWlsZF9vcGVucGlsb3RfY2xpcF9kZXBlbmRlbmNpZXMKICBkZWR1cGVfb3BlbnBpbG90X3ZlbnZfZmlsZXMKICBwcnVuZV9vcGVucGlsb3RfdmVudl9hcnRpZmFjdHMKICBpZiBbWyAiJHtPUEVOUElMT1RfQlVJTERfVUlfQVNTRVRTfSIgPT0gIjEiIF1dOyB0aGVuCiAgICBpbnN0YWxsX2FjY2VsZXJhdGVkX2xpbnV4X3B5cmF5CiAgICBnZW5lcmF0ZV91aV9mb250cwogIGZpCiAgcmVjb3JkX2NoZWNrb3V0X2NvbW1pdAogIHBydW5lX29wZW5waWxvdF9jaGVja291dAogIHBydW5lX29wZW5waWxvdF9idWlsZF9hcnRpZmFjdHMKICBzdHJpcF9kZWJ1Z19zeW1ib2xzCiAgcmVtb3ZlX2J1aWxkX3BhY2thZ2VzCiAgY2xlYW5faW1hZ2VfYXJ0aWZhY3RzCn0KCm1haW4gIiRAIgo= | base64 -d > bootstrap_image_env.sh && bash bootstrap_image_env.sh # buildkit |
| WORKDIR /src |
| EXPOSE map[5000/tcp:{}] |
| ENV COG_PREDICT_TYPE_STUB=cog_predictor.py:Predictor |
| CMD ["python" "-m" "cog.server.http"] |
| COPY . /src # buildkit |
| RUN /bin/sh -c cp /src/cog-starpilot-ghcr.yaml /src/cog.yaml # buildkit |
Labels
| Key | Value |
|---|---|
| com.nvidia.cudnn.version | 9.1.0.70-1 |
| maintainer | NVIDIA CORPORATION <cudatools@nvidia.com> |
| org.opencontainers.image.created | 2025-07-09T18:38:49.933Z |
| org.opencontainers.image.description | |
| org.opencontainers.image.licenses | |
| org.opencontainers.image.ref.name | ubuntu |
| org.opencontainers.image.revision | ad40a08da114637a031125d4546de17e34892f17 |
| org.opencontainers.image.source | https://github.com/replicate/cog-base-images |
| org.opencontainers.image.title | cog-base-images |
| org.opencontainers.image.url | https://github.com/replicate/cog-base-images |
| org.opencontainers.image.version | cuda12.4-python3.12-X64 |
Details
2026-06-16 03:59:49 -04:00
Versions (4)
View all
Container
0
OCI / Docker
linux/amd64
14 GiB
starpilot-cpu
2026-06-29
sunnypilot-gpu
2026-06-29
sunnypilot-cpu
2026-06-29
starpilot-gpu
2026-06-16