mirror of
https://github.com/jimeh/.vscode.d.git
synced 2026-02-19 11:26:39 +00:00
chore(siren): various changes to vsix downloading
This commit is contained in:
643
siren
643
siren
@@ -9,6 +9,10 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|||||||
SETUP_EDITOR=""
|
SETUP_EDITOR=""
|
||||||
declare -A STATIC_SYMLINKS=()
|
declare -A STATIC_SYMLINKS=()
|
||||||
|
|
||||||
|
# When true, try downloading extensions from OpenVSX first, with a fallback to
|
||||||
|
# VS Marketplace. This is forced to true for the Kiro editor.
|
||||||
|
PREFER_OPENVSX="${PREFER_OPENVSX:-false}"
|
||||||
|
|
||||||
# Define settings as a function, allowing them to run after all other functions
|
# Define settings as a function, allowing them to run after all other functions
|
||||||
# have been defined, using them as needed.
|
# have been defined, using them as needed.
|
||||||
define_settings() {
|
define_settings() {
|
||||||
@@ -83,6 +87,79 @@ EOF
|
|||||||
# Functions
|
# Functions
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
|
|
||||||
|
info() {
|
||||||
|
echo "$1" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
debug() {
|
||||||
|
[[ -n "${DEBUG}" ]] && echo "DEBUG: $1" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
warn() {
|
||||||
|
echo "WARN: $1" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
error() {
|
||||||
|
echo "ERROR: $1" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
fatal() {
|
||||||
|
error "$1" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Determine current platform for OpenVSX downloads.
|
||||||
|
#
|
||||||
|
# Returns: Platform string compatible with OpenVSX via `STDOUT`.
|
||||||
|
get_current_platform() {
|
||||||
|
local os_name
|
||||||
|
local arch_name
|
||||||
|
local platform=""
|
||||||
|
|
||||||
|
# Detect OS
|
||||||
|
case "$(uname -s)" in
|
||||||
|
"Darwin")
|
||||||
|
os_name="darwin"
|
||||||
|
;;
|
||||||
|
"Linux")
|
||||||
|
# Check if running on Alpine Linux
|
||||||
|
if [[ -f /etc/alpine-release ]]; then
|
||||||
|
os_name="alpine"
|
||||||
|
else
|
||||||
|
os_name="linux"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
"CYGWIN"* | "MINGW"* | "MSYS"*)
|
||||||
|
os_name="win32"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
os_name="linux" # Default fallback
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Detect architecture
|
||||||
|
case "$(uname -m)" in
|
||||||
|
"x86_64" | "amd64")
|
||||||
|
arch_name="x64"
|
||||||
|
;;
|
||||||
|
"arm64" | "aarch64")
|
||||||
|
arch_name="arm64"
|
||||||
|
;;
|
||||||
|
"armv7l" | "armv6l")
|
||||||
|
arch_name="armhf"
|
||||||
|
;;
|
||||||
|
"i386" | "i686")
|
||||||
|
arch_name="x86"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
arch_name="x64" # Default fallback
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
platform="${os_name}-${arch_name}"
|
||||||
|
echo "${platform}"
|
||||||
|
}
|
||||||
|
|
||||||
# Determine editor config directory.
|
# Determine editor config directory.
|
||||||
#
|
#
|
||||||
# Returns: Editor config directory path via `STDOUT`.
|
# Returns: Editor config directory path via `STDOUT`.
|
||||||
@@ -106,8 +183,7 @@ editor_config_dir() {
|
|||||||
echo "${HOME}/Library/Application Support/Kiro/User"
|
echo "${HOME}/Library/Application Support/Kiro/User"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "Error: Invalid editor '${SETUP_EDITOR}' for macOS"
|
fatal "Invalid editor '${SETUP_EDITOR}' for macOS"
|
||||||
exit 1
|
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
@@ -129,14 +205,12 @@ editor_config_dir() {
|
|||||||
echo "${HOME}/.config/Kiro/User"
|
echo "${HOME}/.config/Kiro/User"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "Error: Invalid editor '${SETUP_EDITOR}' for Linux"
|
fatal "Invalid editor '${SETUP_EDITOR}' for Linux"
|
||||||
exit 1
|
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "Error: Unsupported operating system"
|
fatal "Unsupported operating system"
|
||||||
exit 1
|
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
@@ -157,8 +231,7 @@ harper_config_dir() {
|
|||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "Error: Unsupported operating system"
|
fatal "Unsupported operating system"
|
||||||
exit 1
|
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
@@ -197,17 +270,17 @@ backup_and_link() {
|
|||||||
real_target="$(resolve_symlink "$target")"
|
real_target="$(resolve_symlink "$target")"
|
||||||
real_source="$(resolve_symlink "$source")"
|
real_source="$(resolve_symlink "$source")"
|
||||||
if [[ "${real_target}" == "${real_source}" ]]; then
|
if [[ "${real_target}" == "${real_source}" ]]; then
|
||||||
echo "Skipping ${target} - already linked to ${source}"
|
info "Skipping ${target} - already linked to ${source}"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Backing up existing ${target} to ${target}.bak"
|
info "Backing up existing ${target} to ${target}.bak"
|
||||||
mv "${target}" "${target}.bak"
|
mv "${target}" "${target}.bak"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Create symlink.
|
# Create symlink.
|
||||||
echo "Creating symlink for ${source} to ${target}"
|
info "Creating symlink for ${source} to ${target}"
|
||||||
ln -s "${source}" "${target}"
|
ln -s "${source}" "${target}"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,19 +305,6 @@ symlink_static_config() {
|
|||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
# Public function: Create static symlinks only.
|
|
||||||
do_static_config() {
|
|
||||||
symlink_static_config
|
|
||||||
echo "Static symlink setup complete!"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Public function: Create all symlinks (editor-specific + static).
|
|
||||||
do_config() {
|
|
||||||
symlink_editor_config
|
|
||||||
symlink_static_config
|
|
||||||
echo "Symlink setup complete!"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Find the editor CLI command.
|
# Find the editor CLI command.
|
||||||
#
|
#
|
||||||
# Returns: Editor command path via `STDOUT`.
|
# Returns: Editor command path via `STDOUT`.
|
||||||
@@ -294,8 +354,7 @@ find_editor_cmd() {
|
|||||||
)
|
)
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "Error: Invalid editor '${SETUP_EDITOR}'"
|
fatal "Invalid editor '${SETUP_EDITOR}'"
|
||||||
exit 1
|
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
@@ -308,32 +367,12 @@ find_editor_cmd() {
|
|||||||
done
|
done
|
||||||
|
|
||||||
if [[ -z "${editor_cmd}" ]]; then
|
if [[ -z "${editor_cmd}" ]]; then
|
||||||
echo "Error: ${SETUP_EDITOR} command not found" >&2
|
fatal "${SETUP_EDITOR} command not found"
|
||||||
exit 1
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "${editor_cmd}"
|
echo "${editor_cmd}"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Dump installed extensions to `extensions.lock`.
|
|
||||||
do_dump_extensions() {
|
|
||||||
local editor_cmd
|
|
||||||
editor_cmd="$(find_editor_cmd)"
|
|
||||||
local current_date
|
|
||||||
current_date="$(date)"
|
|
||||||
local extensions_lock
|
|
||||||
extensions_lock="$(get_extensions_lock)"
|
|
||||||
|
|
||||||
{
|
|
||||||
echo "# ${SETUP_EDITOR} Extensions"
|
|
||||||
echo "# Generated on ${current_date}"
|
|
||||||
echo
|
|
||||||
"${editor_cmd}" --list-extensions --show-versions 2> /dev/null
|
|
||||||
} > "${extensions_lock}"
|
|
||||||
|
|
||||||
echo "Extensions list dumped to ${extensions_lock}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Validate extension line format.
|
# Validate extension line format.
|
||||||
validate_extension_line() {
|
validate_extension_line() {
|
||||||
local line="$1"
|
local line="$1"
|
||||||
@@ -344,7 +383,7 @@ validate_extension_line() {
|
|||||||
local at_count
|
local at_count
|
||||||
at_count=$(echo "${line}" | grep -o "@" | wc -l)
|
at_count=$(echo "${line}" | grep -o "@" | wc -l)
|
||||||
if [[ ${at_count} -ne 1 ]]; then
|
if [[ ${at_count} -ne 1 ]]; then
|
||||||
echo "Warning: Invalid format '${line}' - must contain exactly one '@'"
|
warn "Invalid format '${line}' - must contain exactly one '@'"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -354,26 +393,26 @@ validate_extension_line() {
|
|||||||
|
|
||||||
# Validate extension part (should be `<publisher>.<extension>`).
|
# Validate extension part (should be `<publisher>.<extension>`).
|
||||||
if [[ ! "${extension}" =~ ^[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+$ ]]; then
|
if [[ ! "${extension}" =~ ^[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+$ ]]; then
|
||||||
echo "Warning: Invalid extension format '${extension}' - must be" \
|
warn "Invalid extension format '${extension}' - must be" \
|
||||||
"'publisher.extension'"
|
"'publisher.extension'"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Validate version is not empty and contains valid characters.
|
# Validate version is not empty and contains valid characters.
|
||||||
if [[ -z "${version}" ]]; then
|
if [[ -z "${version}" ]]; then
|
||||||
echo "Warning: Empty version for extension '${extension}'"
|
warn "Empty version for extension '${extension}'"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ ! "${version}" =~ ^[a-zA-Z0-9._-]+$ ]]; then
|
if [[ ! "${version}" =~ ^[a-zA-Z0-9._-]+$ ]]; then
|
||||||
echo "Warning: Invalid version format '${version}' for extension" \
|
warn "Invalid version format '${version}' for extension" \
|
||||||
"'${extension}'"
|
"'${extension}'"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check for leading/trailing whitespace.
|
# Check for leading/trailing whitespace.
|
||||||
if [[ "${line}" != "${line// /}" ]]; then
|
if [[ "${line}" != "${line// /}" ]]; then
|
||||||
echo "Warning: Extension line contains spaces: '${line}'"
|
warn "Extension line contains spaces: '${line}'"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -420,9 +459,39 @@ get_installed_version() {
|
|||||||
query_latest_version() {
|
query_latest_version() {
|
||||||
local extension="$1"
|
local extension="$1"
|
||||||
|
|
||||||
if query_marketplace_latest_version "${extension}"; then
|
debug "Querying latest version of ${extension}"
|
||||||
return 0
|
|
||||||
elif query_openvsx_latest_version "${extension}"; then
|
(
|
||||||
|
[[ "${PREFER_OPENVSX}" == "true" ]] &&
|
||||||
|
query_openvsx_latest_version "${extension}"
|
||||||
|
) ||
|
||||||
|
query_marketplace_latest_version "${extension}" ||
|
||||||
|
(
|
||||||
|
[[ "${PREFER_OPENVSX}" != "true" ]] &&
|
||||||
|
query_openvsx_latest_version "${extension}"
|
||||||
|
) ||
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Query extension metadata from OpenVSX registry.
|
||||||
|
#
|
||||||
|
# Returns: JSON metadata via `STDOUT` on success.
|
||||||
|
query_openvsx_metadata() {
|
||||||
|
local extension="$1"
|
||||||
|
local version="$2"
|
||||||
|
local publisher_id="${extension%%.*}"
|
||||||
|
local extension_id="${extension#*.}"
|
||||||
|
local openvsx_api_url=""
|
||||||
|
|
||||||
|
if [[ "${version}" == "latest" ]]; then
|
||||||
|
openvsx_api_url="https://open-vsx.org/api/${publisher_id}/${extension_id}"
|
||||||
|
else
|
||||||
|
openvsx_api_url="https://open-vsx.org/api/${publisher_id}/${extension_id}/${version}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Query OpenVSX API and return full JSON
|
||||||
|
debug "Querying OpenVSX API for ${extension}@${version}: ${openvsx_api_url}"
|
||||||
|
if curl --silent --compressed "${openvsx_api_url}" 2> /dev/null; then
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
return 1
|
return 1
|
||||||
@@ -434,17 +503,14 @@ query_latest_version() {
|
|||||||
# Returns: Latest version string via `STDOUT` on success.
|
# Returns: Latest version string via `STDOUT` on success.
|
||||||
query_openvsx_latest_version() {
|
query_openvsx_latest_version() {
|
||||||
local extension="$1"
|
local extension="$1"
|
||||||
local publisher_id="${extension%%.*}"
|
|
||||||
local extension_id="${extension#*.}"
|
|
||||||
local openvsx_api_url="https://open-vsx.org/api/${publisher_id}/${extension_id}"
|
|
||||||
|
|
||||||
# Check for jq availability
|
# Check for jq availability
|
||||||
if ! command -v jq > /dev/null 2>&1; then
|
if ! command -v jq > /dev/null 2>&1; then
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Query OpenVSX API and extract latest version
|
# Query OpenVSX metadata and extract latest version
|
||||||
if curl --silent --compressed "${openvsx_api_url}" 2> /dev/null |
|
if query_openvsx_metadata "${extension}" "latest" |
|
||||||
jq -r '.version // empty' 2> /dev/null; then
|
jq -r '.version // empty' 2> /dev/null; then
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
@@ -452,10 +518,10 @@ query_openvsx_latest_version() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Query latest version from VS Marketplace.
|
# Query extension metadata from VS Marketplace.
|
||||||
#
|
#
|
||||||
# Returns: Latest version string via `STDOUT` on success.
|
# Returns: JSON metadata via `STDOUT` on success.
|
||||||
query_marketplace_latest_version() {
|
query_marketplace_metadata() {
|
||||||
local extension="$1"
|
local extension="$1"
|
||||||
local metadata_url="https://marketplace.visualstudio.com/_apis/public/gallery/extensionquery"
|
local metadata_url="https://marketplace.visualstudio.com/_apis/public/gallery/extensionquery"
|
||||||
|
|
||||||
@@ -473,11 +539,31 @@ query_marketplace_latest_version() {
|
|||||||
flags: 2
|
flags: 2
|
||||||
}')
|
}')
|
||||||
|
|
||||||
# Query the marketplace and extract latest version
|
# Query the marketplace and return full JSON
|
||||||
|
debug "Querying VS Marketplace API for ${extension}: ${metadata_url}"
|
||||||
if curl --silent --compressed -X POST \
|
if curl --silent --compressed -X POST \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-H "Accept: application/json; api-version=7.2-preview.1" \
|
-H "Accept: application/json; api-version=7.2-preview.1" \
|
||||||
-d "${request_data}" "${metadata_url}" 2> /dev/null |
|
-d "${request_data}" "${metadata_url}" 2> /dev/null; then
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Query latest version from VS Marketplace.
|
||||||
|
#
|
||||||
|
# Returns: Latest version string via `STDOUT` on success.
|
||||||
|
query_marketplace_latest_version() {
|
||||||
|
local extension="$1"
|
||||||
|
|
||||||
|
# Check for jq availability
|
||||||
|
if ! command -v jq > /dev/null 2>&1; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Query marketplace metadata and extract latest version
|
||||||
|
if query_marketplace_metadata "${extension}" |
|
||||||
jq -r '.results[0].extensions[0].versions[0].version // empty' 2> /dev/null; then
|
jq -r '.results[0].extensions[0].versions[0].version // empty' 2> /dev/null; then
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
@@ -485,6 +571,92 @@ query_marketplace_latest_version() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Find platform-specific version from VS Marketplace metadata.
|
||||||
|
#
|
||||||
|
# Returns: Version and target platform via `STDOUT` as "version:platform".
|
||||||
|
query_marketplace_platform_version() {
|
||||||
|
local extension="$1"
|
||||||
|
local version="$2"
|
||||||
|
local metadata="$3" # JSON metadata from query_marketplace_metadata
|
||||||
|
local current_platform
|
||||||
|
current_platform="$(get_current_platform)"
|
||||||
|
local install_version=""
|
||||||
|
local target_platform=""
|
||||||
|
|
||||||
|
# Check for jq availability
|
||||||
|
if ! command -v jq > /dev/null 2>&1; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If version is "latest", find the latest version for our platform
|
||||||
|
if [[ "${version}" == "latest" ]]; then
|
||||||
|
# First try to find a version for our specific platform
|
||||||
|
install_version=$(
|
||||||
|
echo "${metadata}" | jq -r --arg platform "$current_platform" \
|
||||||
|
'.results[0].extensions[0].versions[] | select(.targetPlatform == $platform) | .version' \
|
||||||
|
2> /dev/null | head -1
|
||||||
|
)
|
||||||
|
target_platform="$current_platform"
|
||||||
|
|
||||||
|
# If no platform-specific version, get the latest universal version
|
||||||
|
if [[ -z "${install_version}" || "${install_version}" == "null" ]]; then
|
||||||
|
install_version=$(
|
||||||
|
echo "${metadata}" | jq -r \
|
||||||
|
'.results[0].extensions[0].versions[] | select(.targetPlatform == null or .targetPlatform == "universal") | .version' \
|
||||||
|
2> /dev/null | head -1
|
||||||
|
)
|
||||||
|
target_platform="universal"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If still no version, get the very latest regardless of platform
|
||||||
|
if [[ -z "${install_version}" || "${install_version}" == "null" ]]; then
|
||||||
|
install_version=$(
|
||||||
|
echo "${metadata}" | jq -r '.results[0].extensions[0].versions[0].version // empty' \
|
||||||
|
2> /dev/null
|
||||||
|
)
|
||||||
|
target_platform=$(
|
||||||
|
echo "${metadata}" | jq -r '.results[0].extensions[0].versions[0].targetPlatform // "universal"' \
|
||||||
|
2> /dev/null
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# Find the specific version entry for our platform and version
|
||||||
|
local version_info
|
||||||
|
version_info=$(
|
||||||
|
echo "${metadata}" | jq -r --arg version "$version" --arg platform "$current_platform" \
|
||||||
|
'.results[0].extensions[0].versions[] | select(.version == $version and .targetPlatform == $platform)' \
|
||||||
|
2> /dev/null
|
||||||
|
)
|
||||||
|
|
||||||
|
# If no platform-specific version found, try universal
|
||||||
|
if [[ -z "${version_info}" || "${version_info}" == "null" ]]; then
|
||||||
|
version_info=$(
|
||||||
|
echo "${metadata}" | jq -r --arg version "$version" \
|
||||||
|
'.results[0].extensions[0].versions[] | select(.version == $version and (.targetPlatform == null or .targetPlatform == "universal"))' \
|
||||||
|
2> /dev/null
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If still no specific version found, use the first version with that version number
|
||||||
|
if [[ -z "${version_info}" || "${version_info}" == "null" ]]; then
|
||||||
|
version_info=$(
|
||||||
|
echo "${metadata}" | jq -r --arg version "$version" \
|
||||||
|
'.results[0].extensions[0].versions[] | select(.version == $version)' \
|
||||||
|
2> /dev/null | head -1
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
|
||||||
|
install_version="$version"
|
||||||
|
target_platform=$(echo "${version_info}" | jq -r '.targetPlatform // "universal"' 2> /dev/null)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "${install_version}" || "${install_version}" == "null" ]]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "${install_version}:${target_platform}"
|
||||||
|
}
|
||||||
|
|
||||||
# Install an extension directly using the marketplace.
|
# Install an extension directly using the marketplace.
|
||||||
install_extension_direct() {
|
install_extension_direct() {
|
||||||
local editor_cmd="$1"
|
local editor_cmd="$1"
|
||||||
@@ -494,19 +666,19 @@ install_extension_direct() {
|
|||||||
local result=0
|
local result=0
|
||||||
|
|
||||||
if [[ "${version}" == "latest" ]]; then
|
if [[ "${version}" == "latest" ]]; then
|
||||||
echo "Installing ${extension} (latest version)" >&2
|
info "Installing ${extension} (latest version)"
|
||||||
if ! "${editor_cmd}" --install-extension "${extension}" --force 2> /dev/null; then
|
if ! "${editor_cmd}" --install-extension "${extension}" --force 2> /dev/null; then
|
||||||
echo "Warning: Direct install failed for ${extension}" >&2
|
warn "Direct install failed for ${extension}"
|
||||||
result=1
|
result=1
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo "Installing ${extension}@${version}"
|
info "Installing ${extension}@${version}"
|
||||||
local install_cmd=("${editor_cmd}" --install-extension "${extension}@${version}")
|
local install_cmd=("${editor_cmd}" --install-extension "${extension}@${version}")
|
||||||
if [[ "${force_install}" == "true" ]]; then
|
if [[ "${force_install}" == "true" ]]; then
|
||||||
install_cmd+=(--force)
|
install_cmd+=(--force)
|
||||||
fi
|
fi
|
||||||
if ! "${install_cmd[@]}" 2> /dev/null; then
|
if ! "${install_cmd[@]}" 2> /dev/null; then
|
||||||
echo "Warning: Direct install failed for ${extension}@${version}" >&2
|
warn "Direct install failed for ${extension}@${version}"
|
||||||
result=1
|
result=1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@@ -524,46 +696,90 @@ download_from_openvsx() {
|
|||||||
local publisher_id="${extension%%.*}"
|
local publisher_id="${extension%%.*}"
|
||||||
local extension_id="${extension#*.}"
|
local extension_id="${extension#*.}"
|
||||||
local install_version="${version}"
|
local install_version="${version}"
|
||||||
|
local metadata=""
|
||||||
|
local download_url=""
|
||||||
|
local vsix_filename=""
|
||||||
local vsix_path=""
|
local vsix_path=""
|
||||||
|
|
||||||
|
info "Downloading ${extension}@${version} from OpenVSX..."
|
||||||
|
|
||||||
|
# Check for jq availability
|
||||||
|
if ! command -v jq > /dev/null 2>&1; then
|
||||||
|
error "jq is required to parse OpenVSX API response"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
# If version is "latest", query OpenVSX API for latest version
|
# If version is "latest", query OpenVSX API for latest version
|
||||||
if [[ "${version}" == "latest" ]]; then
|
if [[ "${version}" == "latest" ]]; then
|
||||||
echo "Querying OpenVSX for latest version of ${extension}..." >&2
|
info "Querying OpenVSX for latest version of ${extension}..."
|
||||||
if install_version=$(query_openvsx_latest_version "${extension}"); then
|
if install_version=$(query_openvsx_latest_version "${extension}"); then
|
||||||
if [[ -z "${install_version}" ]]; then
|
if [[ -z "${install_version}" ]]; then
|
||||||
echo "Error: Could not determine latest version from OpenVSX for ${extension}" >&2
|
error "Could not determine latest version from OpenVSX for ${extension}"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
echo "Latest version of ${extension} from OpenVSX is ${install_version}" >&2
|
info "Latest version of ${extension} from OpenVSX is ${install_version}"
|
||||||
else
|
else
|
||||||
echo "Error: Failed to query OpenVSX API for ${extension}" >&2
|
error "Failed to query OpenVSX API for ${extension}"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Set up download path and URL
|
# Query extension metadata to get download information
|
||||||
vsix_path="${extensions_cache_dir}/${extension}@${install_version}.vsix"
|
info "Querying OpenVSX metadata for ${extension}@${install_version}..."
|
||||||
local openvsx_url="https://open-vsx.org/api/${publisher_id}/${extension_id}/${install_version}/file/${publisher_id}.${extension_id}-${install_version}.vsix"
|
if ! metadata=$(query_openvsx_metadata "${extension}" "${install_version}"); then
|
||||||
|
error "Failed to query OpenVSX metadata for ${extension}@${install_version}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
echo "Downloading ${extension}@${install_version} from OpenVSX..." >&2
|
# Check if extension has platform-specific downloads
|
||||||
echo " - OpenVSX URL: ${openvsx_url}" >&2
|
local current_platform
|
||||||
|
current_platform="$(get_current_platform)"
|
||||||
|
|
||||||
|
# Try to get platform-specific download URL first
|
||||||
|
download_url=$(echo "${metadata}" | jq -r ".downloads[\"${current_platform}\"] // empty" 2> /dev/null)
|
||||||
|
|
||||||
|
# If no platform-specific version, try universal
|
||||||
|
if [[ -z "${download_url}" || "${download_url}" == "null" ]]; then
|
||||||
|
download_url=$(echo "${metadata}" | jq -r '.downloads.universal // .files.download // empty' 2> /dev/null)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Fallback to constructing the URL if no downloads object exists
|
||||||
|
if [[ -z "${download_url}" || "${download_url}" == "null" ]]; then
|
||||||
|
warn "No downloads information found, using fallback URL construction"
|
||||||
|
download_url="https://open-vsx.org/api/${publisher_id}/${extension_id}/${install_version}/file/${publisher_id}.${extension_id}-${install_version}.vsix"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Extract filename from URL or construct it
|
||||||
|
if [[ "${download_url}" =~ @([^/]+)\.vsix$ ]]; then
|
||||||
|
# Platform-specific filename (e.g., name-version@platform.vsix)
|
||||||
|
vsix_filename="${publisher_id}.${extension_id}-${install_version}@${BASH_REMATCH[1]}.vsix"
|
||||||
|
else
|
||||||
|
# Universal filename
|
||||||
|
vsix_filename="${publisher_id}.${extension_id}-${install_version}.vsix"
|
||||||
|
fi
|
||||||
|
|
||||||
|
vsix_path="${extensions_cache_dir}/${vsix_filename}"
|
||||||
|
|
||||||
|
info "Downloading ${extension}@${install_version} from OpenVSX..."
|
||||||
|
info " - Platform: ${current_platform}"
|
||||||
|
info " - OpenVSX URL: ${download_url}"
|
||||||
|
|
||||||
# Create extensions directory if it doesn't exist
|
# Create extensions directory if it doesn't exist
|
||||||
mkdir -p "${extensions_cache_dir}"
|
mkdir -p "${extensions_cache_dir}"
|
||||||
|
|
||||||
if curl --compressed -L -o "${vsix_path}" "${openvsx_url}" 2> /dev/null; then
|
if curl --compressed -L -o "${vsix_path}" "${download_url}" 2> /dev/null; then
|
||||||
# Verify the download was successful by checking file size
|
# Verify the download was successful by checking file size
|
||||||
if [[ -s "${vsix_path}" ]]; then
|
if [[ -s "${vsix_path}" ]]; then
|
||||||
echo "Successfully downloaded from OpenVSX" >&2
|
info "Successfully downloaded from OpenVSX"
|
||||||
echo "${vsix_path}"
|
echo "${vsix_path}"
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
echo "OpenVSX download failed (empty file)" >&2
|
error "OpenVSX download failed (empty file)"
|
||||||
rm -f "${vsix_path}"
|
rm -f "${vsix_path}"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo "OpenVSX download failed" >&2
|
error "OpenVSX download failed"
|
||||||
rm -f "${vsix_path}"
|
rm -f "${vsix_path}"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
@@ -578,83 +794,93 @@ download_from_marketplace() {
|
|||||||
local extensions_cache_dir="$3"
|
local extensions_cache_dir="$3"
|
||||||
local publisher_id="${extension%%.*}"
|
local publisher_id="${extension%%.*}"
|
||||||
local extension_id="${extension#*.}"
|
local extension_id="${extension#*.}"
|
||||||
local install_version="${version}"
|
local metadata=""
|
||||||
|
local version_platform=""
|
||||||
|
local install_version=""
|
||||||
|
local target_platform=""
|
||||||
|
local download_url=""
|
||||||
|
local vsix_filename=""
|
||||||
local vsix_path=""
|
local vsix_path=""
|
||||||
|
|
||||||
# If version is "latest", query VS Marketplace API for latest version
|
info "Downloading ${extension}@${version} from VS Marketplace..."
|
||||||
if [[ "${version}" == "latest" ]]; then
|
|
||||||
echo "Querying VS Marketplace for latest version of ${extension}..." >&2
|
|
||||||
local metadata_url="https://marketplace.visualstudio.com/_apis/public/gallery/extensionquery"
|
|
||||||
local temp_metadata="${extensions_cache_dir}/marketplace-${extension}.json"
|
|
||||||
|
|
||||||
# Create extensions directory if it doesn't exist
|
# Check for jq availability
|
||||||
mkdir -p "${extensions_cache_dir}"
|
if ! command -v jq > /dev/null 2>&1; then
|
||||||
|
error "jq is required to parse VS Marketplace API response"
|
||||||
# Check for jq availability
|
return 1
|
||||||
if ! command -v jq > /dev/null 2>&1; then
|
|
||||||
echo "Error: jq is required to parse VS Marketplace API response for latest version" >&2
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Use jq to properly construct JSON
|
|
||||||
local request_data
|
|
||||||
request_data=$(jq -n --arg ext "$extension" '{
|
|
||||||
filters: [{
|
|
||||||
criteria: [{ filterType: 7, value: $ext }]
|
|
||||||
}],
|
|
||||||
flags: 2
|
|
||||||
}')
|
|
||||||
|
|
||||||
# Query the marketplace for extension metadata
|
|
||||||
if curl --silent --compressed -X POST \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-H "Accept: application/json; api-version=7.2-preview.1" \
|
|
||||||
-d "${request_data}" "${metadata_url}" > "${temp_metadata}" 2> /dev/null; then
|
|
||||||
|
|
||||||
# Extract the latest version from the response using jq
|
|
||||||
install_version=$(
|
|
||||||
jq -r '.results[0].extensions[0].versions[0].version // empty' "${temp_metadata}" \
|
|
||||||
2> /dev/null
|
|
||||||
)
|
|
||||||
|
|
||||||
if [[ -z "${install_version}" || "${install_version}" == "null" ]]; then
|
|
||||||
echo "Error: Could not determine latest version from VS Marketplace for ${extension}" >&2
|
|
||||||
rm -f "${temp_metadata}"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Latest version of ${extension} from VS Marketplace is ${install_version}" >&2
|
|
||||||
else
|
|
||||||
echo "Error: Failed to query VS Marketplace API for ${extension}" >&2
|
|
||||||
rm -f "${temp_metadata}"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
rm -f "${temp_metadata}"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Set up download path and URL
|
|
||||||
vsix_path="${extensions_cache_dir}/${extension}@${install_version}.vsix"
|
|
||||||
local marketplace_url="https://marketplace.visualstudio.com/_apis/public/gallery/publishers/${publisher_id}/vsextensions/${extension_id}/${install_version}/vspackage"
|
|
||||||
|
|
||||||
echo "Downloading ${extension}@${install_version} from VS Marketplace..." >&2
|
|
||||||
echo " - Marketplace URL: ${marketplace_url}" >&2
|
|
||||||
|
|
||||||
# Create extensions directory if it doesn't exist
|
# Create extensions directory if it doesn't exist
|
||||||
mkdir -p "${extensions_cache_dir}"
|
mkdir -p "${extensions_cache_dir}"
|
||||||
|
|
||||||
if curl --compressed -L -o "${vsix_path}" "${marketplace_url}"; then
|
# Query extension metadata
|
||||||
|
info "Querying VS Marketplace for ${extension}@${version}..."
|
||||||
|
if ! metadata=$(query_marketplace_metadata "${extension}"); then
|
||||||
|
error "Failed to query VS Marketplace API for ${extension}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Find the appropriate version and platform
|
||||||
|
if ! version_platform=$(query_marketplace_platform_version "${extension}" "${version}" "${metadata}"); then
|
||||||
|
error "Could not determine version and platform for ${extension}@${version}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Parse the version:platform result
|
||||||
|
install_version="${version_platform%:*}"
|
||||||
|
target_platform="${version_platform#*:}"
|
||||||
|
|
||||||
|
if [[ "${version}" == "latest" ]]; then
|
||||||
|
info "Latest version of ${extension} from VS Marketplace is ${install_version}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
vsix_filename="${publisher_id}.${extension_id}-${install_version}.vsix"
|
||||||
|
|
||||||
|
# Extract download URL directly from metadata
|
||||||
|
if [[ "${target_platform}" != "universal" && "${target_platform}" != "null" ]]; then
|
||||||
|
download_url=$(
|
||||||
|
echo "${metadata}" | jq -r --arg version "$install_version" --arg platform "$target_platform" \
|
||||||
|
'.results[0].extensions[0].versions[] | select(.version == $version and .targetPlatform == $platform) | .files[] | select(.assetType == "Microsoft.VisualStudio.Services.VSIXPackage") | .source' \
|
||||||
|
2> /dev/null
|
||||||
|
)
|
||||||
|
vsix_filename="${publisher_id}.${extension_id}-${install_version}@${target_platform}.vsix"
|
||||||
|
else
|
||||||
|
download_url=$(
|
||||||
|
echo "${metadata}" | jq -r --arg version "$install_version" \
|
||||||
|
'.results[0].extensions[0].versions[] | select(.version == $version and (.targetPlatform == null or .targetPlatform == "universal")) | .files[] | select(.assetType == "Microsoft.VisualStudio.Services.VSIXPackage") | .source' \
|
||||||
|
2> /dev/null
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Fallback to manual URL construction if no download URL found in metadata
|
||||||
|
if [[ -z "${download_url}" || "${download_url}" == "null" ]]; then
|
||||||
|
warn "No download URL found in metadata, using fallback URL construction"
|
||||||
|
if [[ "${target_platform}" != "universal" && "${target_platform}" != "null" ]]; then
|
||||||
|
download_url="https://marketplace.visualstudio.com/_apis/public/gallery/publishers/${publisher_id}/vsextensions/${extension_id}/${install_version}/vspackage?targetPlatform=${target_platform}"
|
||||||
|
vsix_filename="${publisher_id}.${extension_id}-${install_version}@${target_platform}.vsix"
|
||||||
|
else
|
||||||
|
download_url="https://marketplace.visualstudio.com/_apis/public/gallery/publishers/${publisher_id}/vsextensions/${extension_id}/${install_version}/vspackage"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
vsix_path="${extensions_cache_dir}/${vsix_filename}"
|
||||||
|
|
||||||
|
info "Downloading ${extension}@${install_version} from VS Marketplace..."
|
||||||
|
info " - Platform: $(get_current_platform) (using ${target_platform})"
|
||||||
|
info " - Marketplace URL: ${download_url}"
|
||||||
|
|
||||||
|
if curl --compressed -L -o "${vsix_path}" "${download_url}" 2> /dev/null; then
|
||||||
if [[ -s "${vsix_path}" ]]; then
|
if [[ -s "${vsix_path}" ]]; then
|
||||||
echo "Successfully downloaded from VS Marketplace" >&2
|
info "Successfully downloaded from VS Marketplace"
|
||||||
echo "${vsix_path}"
|
echo "${vsix_path}"
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
echo "VS Marketplace download failed (empty file)" >&2
|
error "VS Marketplace download failed (empty file)"
|
||||||
rm -f "${vsix_path}"
|
rm -f "${vsix_path}"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo "VS Marketplace download failed" >&2
|
error "VS Marketplace download failed"
|
||||||
rm -f "${vsix_path}"
|
rm -f "${vsix_path}"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
@@ -667,24 +893,18 @@ download_extension_vsix() {
|
|||||||
local extension="$1"
|
local extension="$1"
|
||||||
local version="$2"
|
local version="$2"
|
||||||
local extensions_cache_dir="$3"
|
local extensions_cache_dir="$3"
|
||||||
local downloaded_path=""
|
|
||||||
|
|
||||||
# Try VS Marketplace first
|
(
|
||||||
echo "Trying VS Marketplace for ${extension}@${version}..." >&2
|
[[ "${PREFER_OPENVSX}" == "true" ]] &&
|
||||||
if downloaded_path=$(download_from_marketplace "${extension}" "${version}" "${extensions_cache_dir}"); then
|
download_from_openvsx "${extension}" "${version}" "${extensions_cache_dir}"
|
||||||
echo "${downloaded_path}"
|
) ||
|
||||||
return 0
|
download_from_marketplace "${extension}" "${version}" "${extensions_cache_dir}" ||
|
||||||
fi
|
(
|
||||||
|
[[ "${PREFER_OPENVSX}" != "true" ]] &&
|
||||||
# Try OpenVSX second
|
download_from_openvsx "${extension}" "${version}" "${extensions_cache_dir}"
|
||||||
echo "Trying OpenVSX for ${extension}@${version}..." >&2
|
) ||
|
||||||
if downloaded_path=$(download_from_openvsx "${extension}" "${version}" "${extensions_cache_dir}"); then
|
error "Failed to download ${extension}@${version} from both OpenVSX and VS Marketplace" &&
|
||||||
echo "${downloaded_path}"
|
return 1
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Error: Failed to download ${extension}@${version} from both OpenVSX and VS Marketplace" >&2
|
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Install an extension via downloading `*.vsix` file.
|
# Install an extension via downloading `*.vsix` file.
|
||||||
@@ -705,14 +925,14 @@ install_extension_via_vsix() {
|
|||||||
# Note: Installing from `*.vsix` automatically overwrites existing versions.
|
# Note: Installing from `*.vsix` automatically overwrites existing versions.
|
||||||
echo "Installing extension from ${vsix_path}"
|
echo "Installing extension from ${vsix_path}"
|
||||||
if ! "${editor_cmd}" --install-extension "${vsix_path}" --force; then
|
if ! "${editor_cmd}" --install-extension "${vsix_path}" --force; then
|
||||||
echo "Warning: Failed to install ${extension} from '*.vsix'" >&2
|
warn "Failed to install ${extension} from '*.vsix'"
|
||||||
result=1
|
result=1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Clean up the `*.vsix` file after installation attempt.
|
# Clean up the `*.vsix` file after installation attempt.
|
||||||
rm -f "${vsix_path}"
|
rm -f "${vsix_path}"
|
||||||
else
|
else
|
||||||
echo "Warning: Failed to download ${extension}@${version}.vsix" >&2
|
warn "Failed to download ${extension}@${version}.vsix"
|
||||||
result=1
|
result=1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -741,27 +961,28 @@ install_extension() {
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Checking latest version for ${extension}..." >&2
|
info "Checking latest version for ${extension}..."
|
||||||
local latest_version
|
local latest_version
|
||||||
if latest_version=$(query_latest_version "${extension}"); then
|
latest_version=$(query_latest_version "${extension}")
|
||||||
echo " - Latest available version: ${latest_version}"
|
if [[ -n "${latest_version}" ]]; then
|
||||||
|
info " - Latest available version: ${latest_version}"
|
||||||
version="${latest_version}"
|
version="${latest_version}"
|
||||||
else
|
else
|
||||||
echo "Error: Could not determine latest version for ${extension}" >&2
|
error "Could not determine latest version for ${extension}"
|
||||||
exit 1
|
return 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -z "${current_version}" ]]; then
|
if [[ -z "${current_version}" ]]; then
|
||||||
# Extension not installed.
|
# Extension not installed.
|
||||||
echo "Installing ${extension}@${version}"
|
info "Installing ${extension}@${version}"
|
||||||
elif [[ "${current_version}" == "${version}" ]]; then
|
elif [[ "${current_version}" == "${version}" ]]; then
|
||||||
# Exact version already installed.
|
# Exact version already installed.
|
||||||
echo "Extension ${extension}@${version} is already installed, skipping"
|
info "Extension ${extension}@${version} is already installed, skipping"
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
# Wrong version installed, need to force install.
|
# Wrong version installed, need to force install.
|
||||||
echo "Extension ${extension} has wrong version installed" \
|
info "Extension ${extension} has wrong version installed" \
|
||||||
"(current: ${current_version}, wanted: ${version})," \
|
"(current: ${current_version}, wanted: ${version})," \
|
||||||
"force-installing ${version}"
|
"force-installing ${version}"
|
||||||
force_install="true"
|
force_install="true"
|
||||||
@@ -777,17 +998,53 @@ install_extension() {
|
|||||||
|
|
||||||
if ! install_extension_direct "${editor_cmd}" "${extension}" \
|
if ! install_extension_direct "${editor_cmd}" "${extension}" \
|
||||||
"${version}" "${force_install}"; then
|
"${version}" "${force_install}"; then
|
||||||
echo "Direct installation failed, trying .vsix download method..." >&2
|
warn "Direct installation failed, trying .vsix download method..."
|
||||||
install_extension_via_vsix "${editor_cmd}" "${extension}" "${version}" \
|
install_extension_via_vsix "${editor_cmd}" "${extension}" "${version}" \
|
||||||
"${extensions_cache_dir}"
|
"${extensions_cache_dir}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Clean up extensions directory if empty
|
# Clean up extensions directory if empty
|
||||||
rmdir "${extensions_cache_dir}" 2> /dev/null || true
|
rmdir "${extensions_cache_dir}" 2> /dev/null || true
|
||||||
echo "Extension ${extension} installed successfully!"
|
info "Extension ${extension} installed successfully!"
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
# Command Functions
|
||||||
|
# ==============================================================================
|
||||||
|
|
||||||
|
# Dump installed extensions to `extensions.lock`.
|
||||||
|
do_dump_extensions() {
|
||||||
|
local editor_cmd
|
||||||
|
editor_cmd="$(find_editor_cmd)"
|
||||||
|
local current_date
|
||||||
|
current_date="$(date)"
|
||||||
|
local extensions_lock
|
||||||
|
extensions_lock="$(get_extensions_lock)"
|
||||||
|
|
||||||
|
{
|
||||||
|
echo "# ${SETUP_EDITOR} Extensions"
|
||||||
|
echo "# Generated on ${current_date}"
|
||||||
|
echo
|
||||||
|
"${editor_cmd}" --list-extensions --show-versions 2> /dev/null
|
||||||
|
} > "${extensions_lock}"
|
||||||
|
|
||||||
|
info "Extensions list dumped to ${extensions_lock}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Public function: Create static symlinks only.
|
||||||
|
do_static_config() {
|
||||||
|
symlink_static_config
|
||||||
|
info "Static symlink setup complete!"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Public function: Create all symlinks (editor-specific + static).
|
||||||
|
do_config() {
|
||||||
|
symlink_editor_config
|
||||||
|
symlink_static_config
|
||||||
|
info "Symlink setup complete!"
|
||||||
|
}
|
||||||
|
|
||||||
# Install extensions from `extensions.lock`.
|
# Install extensions from `extensions.lock`.
|
||||||
do_install_extensions() {
|
do_install_extensions() {
|
||||||
local editor_cmd
|
local editor_cmd
|
||||||
@@ -797,8 +1054,7 @@ do_install_extensions() {
|
|||||||
local use_latest="${1:-false}"
|
local use_latest="${1:-false}"
|
||||||
|
|
||||||
if [[ ! -f "${extensions_lock}" ]]; then
|
if [[ ! -f "${extensions_lock}" ]]; then
|
||||||
echo "Error: ${extensions_lock} not found"
|
fatal "${extensions_lock} not found"
|
||||||
exit 1
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Warm the installed extensions cache before we start processing the lockfile.
|
# Warm the installed extensions cache before we start processing the lockfile.
|
||||||
@@ -829,14 +1085,12 @@ do_install_extension() {
|
|||||||
local use_latest="${2:-false}"
|
local use_latest="${2:-false}"
|
||||||
local editor_cmd
|
local editor_cmd
|
||||||
editor_cmd="$(find_editor_cmd)"
|
editor_cmd="$(find_editor_cmd)"
|
||||||
local extensions_cache_dir="${SCRIPT_DIR}/cache/extensions"
|
|
||||||
local extension=""
|
local extension=""
|
||||||
local version=""
|
local version=""
|
||||||
|
|
||||||
if [[ -z "${extension_id}" ]]; then
|
if [[ -z "${extension_id}" ]]; then
|
||||||
echo "Error: Extension identifier required"
|
error "Extension identifier required"
|
||||||
echo "Usage: siren EDITOR install EXTENSION_ID"
|
info "Usage: siren EDITOR install EXTENSION_ID"
|
||||||
echo "Example: siren cursor install ms-python.python"
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -844,8 +1098,8 @@ do_install_extension() {
|
|||||||
if [[ "${extension_id}" =~ @ ]]; then
|
if [[ "${extension_id}" =~ @ ]]; then
|
||||||
# Extension with specific version
|
# Extension with specific version
|
||||||
if ! validate_extension_line "${extension_id}"; then
|
if ! validate_extension_line "${extension_id}"; then
|
||||||
echo "Error: Invalid extension format '${extension_id}'"
|
error "Invalid extension format '${extension_id}'"
|
||||||
echo "Expected format: publisher.extension or publisher.extension@version"
|
info "Expected format: publisher.extension or publisher.extension@version"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
extension="${extension_id%@*}"
|
extension="${extension_id%@*}"
|
||||||
@@ -853,8 +1107,8 @@ do_install_extension() {
|
|||||||
else
|
else
|
||||||
# Extension without version - install latest
|
# Extension without version - install latest
|
||||||
if [[ ! "${extension_id}" =~ ^[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+$ ]]; then
|
if [[ ! "${extension_id}" =~ ^[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+$ ]]; then
|
||||||
echo "Error: Invalid extension format '${extension_id}'"
|
error "Invalid extension format '${extension_id}'"
|
||||||
echo "Expected format: publisher.extension or publisher.extension@version"
|
info "Expected format: publisher.extension or publisher.extension@version"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
extension="${extension_id}"
|
extension="${extension_id}"
|
||||||
@@ -878,7 +1132,7 @@ do_install_extension() {
|
|||||||
|
|
||||||
main() {
|
main() {
|
||||||
if [[ $# -lt 1 ]]; then
|
if [[ $# -lt 1 ]]; then
|
||||||
echo "Error: No editor specified"
|
error "No editor specified"
|
||||||
show_help
|
show_help
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
@@ -898,7 +1152,7 @@ main() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ $# -lt 2 ]]; then
|
if [[ $# -lt 2 ]]; then
|
||||||
echo "Error: No command specified"
|
error "No command specified"
|
||||||
show_help
|
show_help
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
@@ -920,10 +1174,11 @@ main() {
|
|||||||
;;
|
;;
|
||||||
"kiro" | "k")
|
"kiro" | "k")
|
||||||
SETUP_EDITOR="kiro"
|
SETUP_EDITOR="kiro"
|
||||||
|
PREFER_OPENVSX="true"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "Error: Unsupported editor '${editor}'"
|
error "Unsupported editor '${editor}'"
|
||||||
echo "Supported editors: cursor, kiro, vscode (vsc), vscode-insiders (vsci), windsurf (wind)"
|
info "Supported editors: cursor, kiro, vscode (vsc), vscode-insiders (vsci), windsurf (wind)"
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
@@ -944,9 +1199,9 @@ main() {
|
|||||||
"install" | "inst")
|
"install" | "inst")
|
||||||
# Handle install command specially since it requires an extension argument
|
# Handle install command specially since it requires an extension argument
|
||||||
if [[ $# -lt 1 ]]; then
|
if [[ $# -lt 1 ]]; then
|
||||||
echo "Error: Extension identifier required for install command"
|
error "Extension identifier required for install command"
|
||||||
echo "Usage: siren EDITOR install EXTENSION_ID"
|
info "Usage: siren EDITOR install EXTENSION_ID"
|
||||||
echo "Example: siren cursor install ms-python.python"
|
info "Example: siren cursor install ms-python.python"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -955,8 +1210,8 @@ main() {
|
|||||||
|
|
||||||
# For install command, reject any additional options
|
# For install command, reject any additional options
|
||||||
if [[ $# -gt 0 ]]; then
|
if [[ $# -gt 0 ]]; then
|
||||||
echo "Error: Unknown option '$1' for install command"
|
error "Unknown option '$1' for install command"
|
||||||
echo "Usage: siren EDITOR install EXTENSION_ID"
|
info "Usage: siren EDITOR install EXTENSION_ID"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
@@ -976,7 +1231,7 @@ main() {
|
|||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "Error: Unknown option '$1'"
|
error "Unknown option '$1'"
|
||||||
show_help
|
show_help
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
@@ -1000,12 +1255,12 @@ main() {
|
|||||||
do_install_extension "${extension_id}"
|
do_install_extension "${extension_id}"
|
||||||
;;
|
;;
|
||||||
"")
|
"")
|
||||||
echo "Error: No command provided"
|
error "No command provided"
|
||||||
show_help
|
show_help
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "Error: Unknown command '${command}'"
|
error "Unknown command '${command}'"
|
||||||
show_help
|
show_help
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
|
|||||||
Reference in New Issue
Block a user