#!/bin/bash

# SPDX-FileCopyrightText: Copyright The Lima Authors
# SPDX-License-Identifier: Apache-2.0

# # `hack/codesign/debugserver`
#
# This script wraps the LLDB `debugserver` to `codesign` the target executable.
# This is needed for [Delve](https://github.com/go-delve/delve) to work properly
# on macOS with the virtualization framework.
#
# ## How to use this script with Delve
#
# ### Use `DELVE_DEBUGSERVER_PATH` environment variable
#
# Override `debugserver` by setting the `DELVE_DEBUGSERVER_PATH` environment variable.
# Ref: [Environment variables - Using Delve](https://github.com/go-delve/delve/blob/master/Documentation/usage/README.md#environment-variables)
#
# e.g. in `.vscode/launch.json`:
# ```jsonc
# {
#     "version": "0.2.0",
#     "configurations": [
#         {
#             "name": "hostagent for input instance",
#             "type": "go",
#             "request": "launch",
#             "mode": "debug",
#             // Use integratedTerminal to stop using ctrl+C
#             "console": "integratedTerminal",
#             "program": "${workspaceFolder}/cmd/limactl",
#             "buildFlags": [
#                 "-ldflags=-X github.com/lima-vm/lima/pkg/version.Version=2.0.0-alpha.0",
#             ],
#             "env": {
#                 "CGO_ENABLED": "1",
#                 "DELVE_DEBUGSERVER_PATH": "${workspaceFolder}/hack/codesign/debugserver",
#                 "LIMA_SSH_PORT_FORWARDER": "true",
#             },
#             "cwd": "${userHome}/.lima/${input:targetInstance}",
#             "args": [
#                 "--debug",
#                 "hostagent",
#                 "--pidfile", "ha.pid",
#                 "--socket", "ha.sock",
#                 "--guestagent", "${workspaceFolder}/_output/share/lima/lima-guestagent.Linux-aarch64",
#                 "${input:targetInstance}"
#             ],
# 		},
#     ],
#     "inputs": [
#         {
#             "id": "targetInstance",
#             "type": "promptString",
#             "description": "Input target instance parameter for `limactl` command",
#         }
#     ]
# }
# ```
#
# ### Override `debugserver` in the PATH
#
# You can also override the `debugserver` in the PATH environment variable.
#
# e.g. in `.vscode/launch.json`:
# ```diff
#              "env": {
#                  "CGO_ENABLED": "1",
# -                "DELVE_DEBUGSERVER_PATH": "${workspaceFolder}/hack/codesign/debugserver",
# +                "PATH": "${workspaceFolder}/hack/codesign:${env:PATH}",
#              },
# ```

set -eu -o pipefail

script_dir="$(dirname "$0")"

# Codesign the target executable if vz.entitlements exists
entitlements="${script_dir}/../../vz.entitlements"
if [ -f "${entitlements}" ]; then
	prev_arg=
	for arg in "$@"; do
		# find the target executable in the args next to "--"
		if [ "${prev_arg}" = "--" ]; then
			codesign --entitlements "${entitlements}" --force -s - -v "${arg}" || {
				echo "error: codesign failed" >&2
				exit 1
			}
			break
		fi
		prev_arg="${arg}"
	done
fi

# Simulate how Delve locates debugserver
# https://github.com/go-delve/delve/blob/65a6830eb7f0b882e0c52df0ef9585945ed55470/pkg/proc/gdbserial/gdbserver.go#L103-L129
# 1. PATH (in this script, excluding the directory of this script to avoid recursion)
candidate_paths="$(echo "${PATH}" | tr ':' '\n' | grep --fixed-strings --invert-match --line-regexp "${script_dir}" | paste -sd: -)"
# 2. CommandLineTools LLDB path
CLT_path="/Library/Developer/CommandLineTools"
candidate_paths="${candidate_paths}:${CLT_path}/Library/PrivateFrameworks/LLDB.framework/Versions/A/Resources/"
# 3. Xcode LLDB path (if Xcode is installed)
if developer_dir=$(xcode-select --print-path 2>/dev/null) && [ "${developer_dir}" != "${CLT_path}" ]; then
	# Xcode is installed
	candidate_paths="${candidate_paths}:${developer_dir}/../SharedFrameworks/LLDB.framework/Versions/A/Resources/"
fi
# Find debugserver in the candidate paths
debugserver=$(PATH="${candidate_paths}" command -v debugserver) || {
	echo "error: debugserver not found" >&2
	exit 1
}
# Execute debugserver with the original arguments
exec "${debugserver}" "$@"
