Commit f4778e7f2c for freeswitch.com

commit f4778e7f2c98417b2b23c088f7007d6b2c1653fb
Author: Andrey Volk <andywolk@gmail.com>
Date:   Fri Oct 9 16:18:38 2026 +0300

    [UTILS] FSGET: Add source/build-dep/showsrc actions, make token optional (if already configured), add swapi_ token support (#3217)

    - New optional actions: `source`, `build-dep`, `showsrc`. `source` and `build-dep` resolve the source version for the current dpkg architecture, so apt does not pick a package built for another arch.
      - TOKEN can be omitted when the apt repository is already configured.
      - `swapi_*` tokens are accepted as FreeSWITCH Enterprise tokens, same as `PT*`
      - Arguments can be given in any order.

      Examples:
    ```
        curl -sSL https://freeswitch.org/fsget | bash -s pat_xxxxx release install
        curl -sSL https://freeswitch.org/fsget | bash -s swapi_xxxxx prerelease build-dep
        curl -sSL https://freeswitch.org/fsget | bash -s build-dep release pat_xxxxx
        curl -sSL https://freeswitch.org/fsget | bash -s source
        curl -sSL https://freeswitch.org/fsget | bash -s showsrc
    ```

diff --git a/scripts/packaging/README.md b/scripts/packaging/README.md
index 88059328c7..46de902917 100644
--- a/scripts/packaging/README.md
+++ b/scripts/packaging/README.md
@@ -19,17 +19,63 @@ A `SignalWire Personal Access Token` (PAT) or an `API Token` (for enterprise cus

 ## Configuring FreeSWITCH Debian repository
 ```
-curl -sSL https://freeswitch.org/fsget | bash -s <PAT or API token> [release|prerelease] [install]
+curl -sSL https://freeswitch.org/fsget | bash -s <PAT or API token> [release|prerelease] [install|source|build-dep|showsrc]
 ```

 Notice that `fsget` accepts arguments:
-- `<PAT or FSA token>` (Required)
+- `<PAT or FSA token>` (Optional) - omit if the FreeSWITCH apt repository is already configured (the credentials are already in `/etc/apt/auth.conf`)
 - `[release|prerelease]` (Optional) - `release` by default, `prerelease` is what you see in the `master` branch
-- `[install]` (Optional) - If missing it will not install FreeSWITCH automatically after configuring the repository
+- `[install|source|build-dep|showsrc]` (Optional) - action to perform after the repository is configured. If missing it will not perform any action after configuring the repository.

 `FreeSWITCH Community` or `FreeSWITCH Enterprise` version is installed based on the token provided.

 Enterprise customers may install `FreeSWITCH Community` versions by using a `SignalWire Personal Access Token` instead of an `API Token`.
+
+Arguments can be supplied in any order — `fsget` recognises them by pattern. These commands are equivalent:
+```
+curl -sSL https://freeswitch.org/fsget | bash -s <PAT or API token> release build-dep
+curl -sSL https://freeswitch.org/fsget | bash -s <PAT or API token> build-dep release
+curl -sSL https://freeswitch.org/fsget | bash -s build-dep release <PAT or API token>
+```
+
+### Available actions
+
+| Action | Description |
+| --- | --- |
+| `install` | Install `freeswitch-meta-all` after the repository is configured. |
+| `source` | Download the FreeSWITCH source package for the current build architecture. |
+| `build-dep` | Install the FreeSWITCH build dependencies for the current build architecture. |
+| `showsrc` | Print the FreeSWITCH source version for the current build architecture and exit. |
+
+Because FreeSWITCH source packages encode the build architecture in the version string, `source` and `build-dep` look up the exact version for the current architecture before invoking `apt-get` — this prevents `apt` from picking a candidate built for a different architecture.
+
+### Examples
+
+Configure the repository and install FreeSWITCH:
+```
+curl -sSL https://freeswitch.org/fsget | bash -s <PAT or API token> release install
+```
+
+Configure the prerelease repository and install build dependencies:
+```
+curl -sSL https://freeswitch.org/fsget | bash -s <PAT or API token> prerelease build-dep
+```
+
+Token already configured — just install build dependencies for the current architecture:
+```
+curl -sSL https://freeswitch.org/fsget | bash -s build-dep
+```
+
+Token already configured — fetch the source package for the current architecture:
+```
+curl -sSL https://freeswitch.org/fsget | bash -s source
+```
+
+Print the FreeSWITCH source version for the current architecture:
+```
+curl -sSL https://freeswitch.org/fsget | bash -s showsrc
+```
+
 ## Installing FreeSWITCH
 If not installed already type

diff --git a/scripts/packaging/fsget.sh b/scripts/packaging/fsget.sh
index 0ef9cc3bb6..8d872233a9 100755
--- a/scripts/packaging/fsget.sh
+++ b/scripts/packaging/fsget.sh
@@ -6,6 +6,33 @@ set -e          # Exit immediately if a command exits with a non-zero status
 set -u          # Treat unset variables as an error
 set -o pipefail # Return value of a pipeline is the value of the last (rightmost) command to exit with a non-zero status

+print_usage()
+{
+	cat << EOF
+Usage: $0 [TOKEN] [release|prerelease] [install|source|build-dep|showsrc]
+
+  TOKEN        PAT (pat_*, ghapat_*) or FSA token (PT*, swapi_*). Optional if the
+               FreeSWITCH apt repository is already configured.
+  release      Use the stable repository (default when TOKEN is provided).
+  prerelease   Use the unstable repository.
+
+Actions (optional):
+  install      Install freeswitch-meta-all after configuring the repository.
+  source       Download FreeSWITCH source package for the build architecture.
+  build-dep    Install build dependencies for FreeSWITCH on the build architecture.
+  showsrc      Print the FreeSWITCH source version for the build architecture and exit.
+
+If TOKEN is omitted the repository is assumed to be configured already and the
+action is executed against the existing configuration.
+
+Examples:
+  $0 pat_xxxxx release install
+  $0 PT_xxxxx prerelease build-dep
+  $0 build-dep
+  $0 showsrc
+EOF
+}
+
 source_os_release()
 {
 	if [ ! -f /etc/os-release ]; then
@@ -13,7 +40,10 @@ source_os_release()
 		exit 1
 	fi
 	. /etc/os-release
+}

+print_os_identification()
+{
 	echo -n "Operating system identification:"
 	[ -n "$ID" ] && echo -n " ID=$ID"
 	[ -n "$VERSION_CODENAME" ] && echo -n " CODENAME=$VERSION_CODENAME"
@@ -42,25 +72,96 @@ configure_auth()
 	fi
 }

-install_freeswitch()
+# `apt-get source` extracts the source tree with `dpkg-source`, which lives in
+# `dpkg-dev` — only pull that package in when we actually need extraction.
+# Callers must run `apt-get update` before invoking this (the `source` action
+# already does so as part of the version lookup).
+ensure_dpkg_source()
+{
+	if ! command -v dpkg-source > /dev/null 2>&1; then
+		apt-get install -y dpkg-dev
+	fi
+}
+
+# FreeSWITCH source versions encode build arch in the version string (e.g.
+# 1.10.X-release.YYYYMMDDHHMMSS+1.debNN-amd64). Plain `apt-get source freeswitch`
+# or `apt-get build-dep freeswitch` may pick a candidate that does not match the
+# current architecture, so we filter showsrc output by the dpkg architecture.
+get_freeswitch_source_version()
+{
+	apt-cache showsrc freeswitch \
+		| grep "^Version" \
+		| grep "$(dpkg --print-architecture)" \
+		| awk '{print $2}' \
+		| head -n 1
+}
+
+run_action()
 {
 	local edition="$1"
 	local action="$2"
+	local label="FreeSWITCH"
+	[ -n "${edition}" ] && label="FreeSWITCH ${edition}"

-	apt-get update
-
-	if [ "${action}" = "install" ]; then
-		echo "Installing FreeSWITCH ${edition}"
-		apt-get install -y freeswitch-meta-all
-		echo "------------------------------------------------------------------"
-		echo " Done installing FreeSWITCH ${edition}"
-		echo "------------------------------------------------------------------"
-	else
-		echo "------------------------------------------------------------------"
-		echo " Done configuring FreeSWITCH Debian repository"
-		echo "------------------------------------------------------------------"
-		echo "To install FreeSWITCH ${edition} type: apt-get install -y freeswitch-meta-all"
-	fi
+	case "${action}" in
+		"")
+			echo "------------------------------------------------------------------"
+			echo " Done configuring ${label} Debian repository"
+			echo "------------------------------------------------------------------"
+			echo "To install ${label} type: apt-get install -y freeswitch-meta-all"
+			;;
+		install)
+			apt-get update
+			echo "Installing ${label}"
+			apt-get install -y freeswitch-meta-all
+			echo "------------------------------------------------------------------"
+			echo " Done installing ${label}"
+			echo "------------------------------------------------------------------"
+			;;
+		source)
+			apt-get update
+			local version
+			version=$(get_freeswitch_source_version)
+			if [ -z "${version}" ]; then
+				echo "Error: Unable to determine FreeSWITCH source version for $(dpkg --print-architecture)"
+				exit 1
+			fi
+			ensure_dpkg_source
+			echo "Downloading ${label} source (version: ${version})"
+			apt-get source "freeswitch=${version}"
+			echo "------------------------------------------------------------------"
+			echo " Done downloading ${label} source (version: ${version})"
+			echo "------------------------------------------------------------------"
+			;;
+		build-dep)
+			apt-get update
+			local version
+			version=$(get_freeswitch_source_version)
+			if [ -z "${version}" ]; then
+				echo "Error: Unable to determine FreeSWITCH source version for $(dpkg --print-architecture)"
+				exit 1
+			fi
+			echo "Installing ${label} build dependencies (version: ${version})"
+			apt-get build-dep -y "freeswitch=${version}"
+			echo "------------------------------------------------------------------"
+			echo " Done installing ${label} build dependencies (version: ${version})"
+			echo "------------------------------------------------------------------"
+			;;
+		showsrc)
+			local version
+			version=$(get_freeswitch_source_version)
+			if [ -z "${version}" ]; then
+				echo "Error: Unable to determine FreeSWITCH source version for $(dpkg --print-architecture)"
+				exit 1
+			fi
+			echo "${version}"
+			;;
+		*)
+			echo "Error: Unknown action '${action}'"
+			print_usage
+			exit 1
+			;;
+	esac
 }

 if [ "$(id -u)" != "0" ]; then
@@ -68,23 +169,61 @@ if [ "$(id -u)" != "0" ]; then
 fi

 if [ "$#" -lt 1 ] || [ "$#" -gt 3 ]; then
-	echo "Usage: $0 <PAT or FSA token> [[release|prerelease] [install]]"
+	print_usage
 	exit 1
 fi

-TOKEN=$1
-RELEASE="${2:-release}"
-ACTION="${3:-}"
+TOKEN=""
+RELEASE="release"
+ACTION=""
+
+for arg in "$@"; do
+	case "${arg}" in
+		release | prerelease)
+			RELEASE="${arg}"
+			;;
+		install | source | build-dep | showsrc)
+			ACTION="${arg}"
+			;;
+		pat_* | ghapat_* | PT* | swapi_* | not_a_real_token_but_a_dummy_token_*)
+			TOKEN="${arg}"
+			;;
+		*)
+			echo "Error: Unrecognized argument '${arg}'"
+			print_usage
+			exit 1
+			;;
+	esac
+done
+
+if [ -z "${TOKEN}" ] && [ -z "${ACTION}" ]; then
+	echo "Error: Either a TOKEN or an action must be specified."
+	print_usage
+	exit 1
+fi

 source_os_release

-if [ "${ID,,}" = "debian" ]; then
-	ARCH=$(dpkg --print-architecture)
+if [ "${ID,,}" != "debian" ]; then
+	echo "Unrecognized OS. We support Debian only."
+	exit 1
+fi

+# `showsrc` is meant to be machine-readable (a single version line); keep its
+# stdout clean. All other paths print the OS identification for context.
+if [ "${ACTION}" != "showsrc" ]; then
+	print_os_identification
+fi
+
+ARCH=$(dpkg --print-architecture)
+EDITION=""
+
+if [ -n "${TOKEN}" ]; then
 	if [[ ${TOKEN} == pat_* || ${TOKEN} == ghapat_* || ${TOKEN} == not_a_real_token_but_a_dummy_token_* ]]; then
 		DOMAIN="freeswitch.signalwire.com"
 		GPG_KEY="/usr/share/keyrings/signalwire-freeswitch-repo.gpg"
 		RPI=""
+		EDITION="Community"

 		if [ "${RELEASE,,}" = "prerelease" ]; then
 			RELEASE="unstable"
@@ -96,7 +235,7 @@ if [ "${ID,,}" = "debian" ]; then
 			RPI="rpi/"
 		fi

-		echo "FreeSWITCH Community ($RELEASE)"
+		echo "FreeSWITCH ${EDITION} (${RELEASE})"

 		setup_common
 		configure_auth "${DOMAIN}" "" "${TOKEN}"
@@ -112,12 +251,11 @@ if [ "${ID,,}" = "debian" ]; then
 		echo "Suites: ${VERSION_CODENAME}" >> /etc/apt/sources.list.d/freeswitch.sources
 		echo "Components: main" >> /etc/apt/sources.list.d/freeswitch.sources
 		echo "Signed-By: ${GPG_KEY}" >> /etc/apt/sources.list.d/freeswitch.sources
-
-		install_freeswitch "Community" "${ACTION}"
-	elif [[ ${TOKEN} == PT* ]]; then
+	elif [[ ${TOKEN} == PT* || ${TOKEN} == swapi_* ]]; then
 		DOMAIN="fsa.freeswitch.com"
 		GPG_KEY="/usr/share/keyrings/signalwire-freeswitch-advantage-repo.gpg"
 		RPI=""
+		EDITION="Enterprise"

 		if [ "${RELEASE,,}" = "prerelease" ]; then
 			RELEASE="unstable"
@@ -129,7 +267,7 @@ if [ "${ID,,}" = "debian" ]; then
 			RPI="-rpi"
 		fi

-		echo "FreeSWITCH Enterprise ($RELEASE)"
+		echo "FreeSWITCH ${EDITION} (${RELEASE})"

 		setup_common
 		configure_auth "${DOMAIN}" "" "${TOKEN}"
@@ -145,11 +283,7 @@ if [ "${ID,,}" = "debian" ]; then
 		echo "Suites: ${VERSION_CODENAME}" >> /etc/apt/sources.list.d/freeswitch.sources
 		echo "Components: ${RELEASE}" >> /etc/apt/sources.list.d/freeswitch.sources
 		echo "Signed-By: ${GPG_KEY}" >> /etc/apt/sources.list.d/freeswitch.sources
-
-		install_freeswitch "Enterprise" "${ACTION}"
-	else
-		echo "Unrecognized token type"
 	fi
-else
-	echo "Unrecognized OS. We support Debian only."
 fi
+
+run_action "${EDITION}" "${ACTION}"