diff --git a/build/build.linux.sh b/build/build.linux.sh
index 0432dcfe..55bc2f62 100755
--- a/build/build.linux.sh
+++ b/build/build.linux.sh
@@ -3,17 +3,16 @@
version=`cat ../VERSION`
# Cleanup
-rm -rf SourceGit *.tar.gz resources/deb/opt *.deb *.rpm
+rm -rf SourceGit *.tar.gz resources/deb/opt *.deb *.rpm *.AppImage
-# Compile
-dotnet publish ../src/SourceGit.csproj -c Release -r linux-x64 -o SourceGit -p:PublishAot=true -p:PublishTrimmed=true -p:TrimMode=link --self-contained
-mv SourceGit/SourceGit SourceGit/sourcegit
-cp resources/app/App.icns SourceGit/sourcegit.icns
-rm -f SourceGit/*.dbg
+# Generic AppImage
+cd resources/appimage
+./publish-appimage -y -o sourcegit-${version}.linux.x86_64.AppImage
-# General Linux archive
-tar -zcvf sourcegit_${version}.linux-x64.tar.gz SourceGit
-rm -f SourceGit/sourcegit.icns
+# Move to build dir
+mv AppImages/sourcegit-${version}.linux.x86_64.AppImage ../../
+mv AppImages/AppDir/usr/bin ../../SourceGit
+cd ../../
# Debain/Ubuntu package
mkdir -p resources/deb/opt/sourcegit/
diff --git a/build/resources/appimage/publish-appimage b/build/resources/appimage/publish-appimage
new file mode 100755
index 00000000..b8010187
--- /dev/null
+++ b/build/resources/appimage/publish-appimage
@@ -0,0 +1,708 @@
+#!/bin/bash
+################################################################################
+# PROJECT : Publish-AppImage for .NET
+# WEBPAGE : https://github.com/kuiperzone/Publish-AppImage
+# COPYRIGHT : Andy Thomas 2021-2023
+# LICENSE : MIT
+################################################################################
+
+###############################
+# CONSTANTS
+###############################
+
+declare -r _SCRIPT_VERSION="1.3.1"
+declare -r _SCRIPT_TITLE="Publish-AppImage for .NET"
+declare -r _SCRIPT_IMPL_MIN=1
+declare -r _SCRIPT_IMPL_MAX=1
+declare -r _SCRIPT_COPYRIGHT="Copyright 2023 Andy Thomas"
+declare -r _SCRIPT_WEBSITE="https://github.com/kuiperzone/Publish-AppImage"
+
+declare -r _SCRIPT_NAME="publish-appimage"
+declare -r _DEFAULT_CONF="${_SCRIPT_NAME}.conf"
+
+declare -r _APPIMAGE_KIND="appimage"
+declare -r _ZIP_KIND="zip"
+declare -r _DOTNET_NONE="null"
+
+
+###############################
+# FUNCTIONS
+###############################
+
+function assert_result
+{
+ local _ret=$?
+
+ if [ ${_ret} -ne 0 ]; then
+ echo
+ exit ${_ret}
+ fi
+}
+
+function exec_or_die
+{
+ echo "${1}"
+ eval "${1}"
+ assert_result
+}
+
+function ensure_directory
+{
+ local _path="${1}"
+
+ if [ ! -d "${_path}" ]; then
+ mkdir -p "${_path}"
+ assert_result
+ fi
+}
+
+function remove_path
+{
+ local _path="${1}"
+
+ if [ -d "${_path}" ]; then
+ rm -rf "${_path}"
+ assert_result
+ elif [ -f "${_path}" ]; then
+ rm -f "${_path}"
+ assert_result
+ fi
+}
+
+function assert_mandatory
+{
+ local _name="${1}"
+ local _value="${2}"
+
+ if [ "${_value}" == "" ]; then
+ echo "${_name} undefined in: ${_conf_arg_value}"
+ echo
+ exit 1
+ fi
+}
+
+function assert_opt_file
+{
+ local _name="${1}"
+ local _value="${2}"
+
+ if [ "${_value}" != "" ] && [ ! -f "${_value}" ]; then
+ echo "File not found: ${_value}"
+
+ if [ "${_name}" != "" ]; then
+ echo "See ${_name} in: ${_conf_arg_value}"
+ fi
+
+ echo
+ exit 1
+ fi
+}
+
+###############################
+# HANDLE ARGUMENTS
+###############################
+
+# Specify conf file
+declare -r _CONF_ARG="f"
+declare -r _CONF_ARG_NAME="conf"
+_conf_arg_value="${_DEFAULT_CONF}"
+_arg_syntax=":${_CONF_ARG}:"
+
+# Runtime ID
+declare -r _RID_ARG="r"
+declare -r _RID_ARG_NAME="runtime"
+_rid_arg_value="linux-x64"
+_arg_syntax="${_arg_syntax}${_RID_ARG}:"
+
+# Package kind
+declare -r _KIND_ARG="k"
+declare -r _KIND_ARG_NAME="kind"
+declare -l _kind_arg_value="${_APPIMAGE_KIND}"
+_arg_syntax="${_arg_syntax}${_KIND_ARG}:"
+
+# Run app
+declare -r _RUNAPP_ARG="u"
+declare -r _RUNAPP_ARG_NAME="run"
+_runapp_arg_value=false
+_arg_syntax="${_arg_syntax}${_RUNAPP_ARG}"
+
+# Verbose
+declare -r _VERBOSE_ARG="b"
+declare -r _VERBOSE_ARG_NAME="verbose"
+_verbose_arg_value=false
+_arg_syntax="${_arg_syntax}${_VERBOSE_ARG}"
+
+# Skip yes (no prompt)
+declare -r _SKIPYES_ARG="y"
+declare -r _SKIPYES_ARG_NAME="skip-yes"
+_skipyes_arg_value=false
+_arg_syntax="${_arg_syntax}${_SKIPYES_ARG}"
+
+# Output name
+declare -r _OUTPUT_ARG="o"
+declare -r _OUTPUT_ARG_NAME="output"
+_output_arg_value=""
+_arg_syntax="${_arg_syntax}${_OUTPUT_ARG}:"
+
+# Show version
+declare -r _VERSION_ARG="v"
+declare -r _VERSION_ARG_NAME="version"
+_version_arg_value=false
+_arg_syntax="${_arg_syntax}${_VERSION_ARG}"
+
+# Show help
+declare -r _HELP_ARG="h"
+declare -r _HELP_ARG_NAME="help"
+_help_arg_value=false
+_arg_syntax="${_arg_syntax}${_HELP_ARG}"
+
+_exit_help=0
+
+# Transform long options to short ones
+for arg in "${@}"; do
+ shift
+ case "${arg}" in
+ ("--${_CONF_ARG_NAME}") set -- "$@" "-${_CONF_ARG}" ;;
+ ("--${_RID_ARG_NAME}") set -- "$@" "-${_RID_ARG}" ;;
+ ("--${_KIND_ARG_NAME}") set -- "$@" "-${_KIND_ARG}" ;;
+ ("--${_RUNAPP_NAME}") set -- "$@" "-${_RUNAPP_ARG}" ;;
+ ("--${_VERBOSE_ARG_NAME}") set -- "$@" "-${_VERBOSE_ARG}" ;;
+ ("--${_SKIPYES_ARG_NAME}") set -- "$@" "-${_SKIPYES_ARG}" ;;
+ ("--${_OUTPUT_ARG_NAME}") set -- "$@" "-${_OUTPUT_ARG}" ;;
+ ("--${_VERSION_ARG_NAME}") set -- "$@" "-${_VERSION_ARG}" ;;
+ ("--${_HELP_ARG_NAME}") set -- "$@" "-${_HELP_ARG}" ;;
+ ("--"*)
+ echo "Illegal argument: ${arg}"
+ echo
+
+ _exit_help=1
+ break
+ ;;
+ (*) set -- "$@" "${arg}" ;;
+ esac
+done
+
+if [ ${_exit_help} == 0 ]; then
+ # Read arguments
+ while getopts ${_arg_syntax} arg; do
+ case "${arg}" in
+ (${_CONF_ARG}) _conf_arg_value="${OPTARG}" ;;
+ (${_RID_ARG}) _rid_arg_value="${OPTARG}" ;;
+ (${_KIND_ARG}) _kind_arg_value="${OPTARG}" ;;
+ (${_RUNAPP_ARG}) _runapp_arg_value=true ;;
+ (${_VERBOSE_ARG}) _verbose_arg_value=true ;;
+ (${_SKIPYES_ARG}) _skipyes_arg_value=true ;;
+ (${_OUTPUT_ARG}) _output_arg_value="${OPTARG}" ;;
+ (${_VERSION_ARG}) _version_arg_value=true ;;
+ (${_HELP_ARG}) _help_arg_value=true ;;
+ (*)
+ echo "Illegal argument"
+ echo
+
+ _exit_help=1
+ break
+ ;;
+ esac
+ done
+fi
+
+# Handle and help and version
+if [ ${_help_arg_value} == true ] || [ $_exit_help != 0 ]; then
+
+ _indent=" "
+ echo "Usage:"
+ echo "${_indent}${_SCRIPT_NAME} [-flags] [-option-n value-n]"
+ echo
+
+ echo "Help Options:"
+ echo "${_indent}-${_HELP_ARG}, --${_HELP_ARG_NAME}"
+ echo "${_indent}Show help information flag."
+ echo
+ echo "${_indent}-${_VERSION_ARG}, --${_VERSION_ARG_NAME}"
+ echo "${_indent}Show version and about information flag."
+ echo
+
+ echo "Build Options:"
+ echo "${_indent}-${_CONF_ARG}, --${_CONF_ARG_NAME} value"
+ echo "${_indent}Specifies the conf file. Defaults to ${_SCRIPT_NAME}.conf."
+ echo
+ echo "${_indent}-${_RID_ARG}, --${_RID_ARG_NAME} value"
+ echo "${_indent}Dotnet publish runtime identifier. Valid examples include:"
+ echo "${_indent}linux-x64 and linux-arm64. Default is linux-x64 if unspecified."
+ echo "${_indent}See also: https://docs.microsoft.com/en-us/dotnet/core/rid-catalog"
+ echo
+ echo "${_indent}-${_KIND_ARG}, --${_KIND_ARG_NAME} value"
+ echo "${_indent}Package output kind. Value must be one of: ${_APPIMAGE_KIND} or ${_ZIP_KIND}."
+ echo "${_indent}Default is ${_APPIMAGE_KIND} if unspecified."
+ echo
+ echo "${_indent}-${_VERBOSE_ARG}, --${_VERBOSE_ARG_NAME}"
+ echo "${_indent}Verbose review info output flag."
+ echo
+ echo "${_indent}-${_RUNAPP_ARG}, --${_RUNAPP_ARG_NAME}"
+ echo "${_indent}Run the application after successful build flag."
+ echo
+ echo "${_indent}-${_SKIPYES_ARG}, --${_SKIPYES_ARG_NAME}"
+ echo "${_indent}Skip confirmation prompt flag (assumes yes)."
+ echo
+ echo "${_indent}-${_OUTPUT_ARG}, --${_OUTPUT_ARG_NAME}"
+ echo "${_indent}Explicit final output filename (excluding directory part)."
+ echo
+
+ echo "Example:"
+ echo "${_indent}${_SCRIPT_NAME} -${_RID_ARG} linux-arm64"
+ echo
+
+ exit $_exit_help
+fi
+
+if [ ${_version_arg_value} == true ]; then
+ echo
+ echo "${_SCRIPT_TITLE}, ${_SCRIPT_VERSION}"
+ echo "${_SCRIPT_COPYRIGHT}"
+ echo "${_SCRIPT_WEBSITE}"
+ echo
+ echo "MIT License"
+ echo
+ echo "Permission is hereby granted, free of charge, to any person obtaining a copy"
+ echo "of this software and associated documentation files (the "Software"), to deal"
+ echo "in the Software without restriction, including without limitation the rights"
+ echo "to use, copy, modify, merge, publish, distribute, sublicense, and/or sell"
+ echo "copies of the Software, and to permit persons to whom the Software is"
+ echo "furnished to do so, subject to the following conditions:"
+ echo
+ echo "The above copyright notice and this permission notice shall be included in all"
+ echo "copies or substantial portions of the Software."
+ echo
+ echo "THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR"
+ echo "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,"
+ echo "FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE"
+ echo "AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER"
+ echo "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,"
+ echo "OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE"
+ echo "SOFTWARE."
+ echo
+
+ exit 0
+fi
+
+
+###############################
+# SOURCE & WORKING
+###############################
+
+# Export these now as may be
+# useful in an advanced config file
+export DOTNET_RID="${_rid_arg_value}"
+export PKG_KIND="${_kind_arg_value}"
+export ISO_DATE=`date +"%Y-%m-%d"`
+
+if [ ! -f "${_conf_arg_value}" ]; then
+ echo "Configuration file not found: ${_conf_arg_value}"
+ echo
+ exit 1
+fi
+
+# Export contents to any post publish command
+set -a
+
+# Source local to PWD
+source "${_conf_arg_value}"
+set +a
+
+# For AppImage tool and backward compatibility
+export VERSION="${APP_VERSION}"
+
+
+# Then change PWD to conf file
+cd "$(dirname "${_conf_arg_value}")"
+
+
+###############################
+# SANITY
+###############################
+
+if (( ${CONF_IMPL_VERSION} < ${_SCRIPT_IMPL_MIN} )) || (( ${CONF_IMPL_VERSION} > ${_SCRIPT_IMPL_MAX} )); then
+ echo "Configuration format version ${_SCRIPT_IMPL_VERSION} not compatible"
+ echo "Older conf file but newer ${_SCRIPT_NAME} implementation?"
+ echo "Update from: ${_SCRIPT_WEBSITE}"
+ echo
+ exit 1
+fi
+
+assert_mandatory "APP_MAIN" "${APP_MAIN}"
+assert_mandatory "APP_ID" "${APP_ID}"
+assert_mandatory "APP_ICON_SRC" "${APP_ICON_SRC}"
+assert_mandatory "DE_NAME" "${DE_NAME}"
+assert_mandatory "DE_CATEGORIES" "${DE_CATEGORIES}"
+assert_mandatory "PKG_OUTPUT_DIR" "${PKG_OUTPUT_DIR}"
+
+if [ "${_kind_arg_value}" == "${_APPIMAGE_KIND}" ]; then
+ assert_mandatory "APPIMAGETOOL_COMMAND" "${APPIMAGETOOL_COMMAND}"
+fi
+
+assert_opt_file "APP_ICON_SRC" "${APP_ICON_SRC}"
+assert_opt_file "APP_XML_SRC" "${APP_XML_SRC}"
+
+if [ "${DE_TERMINAL_FLAG}" != "true" ] && [ "${DE_TERMINAL_FLAG}" != "false" ]; then
+ echo "DE_TERMINAL_FLAG invalid value: ${DE_TERMINAL_FLAG}"
+ echo
+ exit 1
+fi
+
+if [ "${DOTNET_PROJECT_PATH}" == "${_DOTNET_NONE}" ] && [ "${POST_PUBLISH}" == "" ]; then
+ echo "No publish or build operation defined (nothing will be built)"
+ echo "See DOTNET_PROJECT_PATH and POST_PUBLISH in: ${_conf_arg_value}"
+ echo
+ exit 1
+fi
+
+if [ "${DOTNET_PROJECT_PATH}" != "" ] && [ "${DOTNET_PROJECT_PATH}" != "${_DOTNET_NONE}" ] &&
+ [ ! -f "${DOTNET_PROJECT_PATH}" ] && [ ! -d "${DOTNET_PROJECT_PATH}" ]; then
+ echo "DOTNET_PROJECT_PATH path not found: ${DOTNET_PROJECT_PATH}"
+ echo
+ exit 1
+fi
+
+if [ "${_kind_arg_value}" != "${_APPIMAGE_KIND}" ] && [ "${_kind_arg_value}" != "${_ZIP_KIND}" ]; then
+ echo "Invalid argument value: ${_kind_arg_value}"
+ echo "Use one of: ${_APPIMAGE_KIND} or ${_ZIP_KIND}"
+ echo
+ exit 1
+fi
+
+
+# Detect if publish for windows
+_exec_ext=""
+declare -l _tw="${_rid_arg_value}"
+
+if [[ "${_tw}" == "win"* ]]; then
+
+ # May use this in future
+ _exec_ext=".exe"
+
+ if [ "${_kind_arg_value}" == "${_APPIMAGE_KIND}" ]; then
+ echo "Invalid AppImage payload"
+ echo "Looks like a windows binary to be packaged as AppImage."
+ echo "Use --${_KIND_ARG_NAME} ${_ZIP_KIND} instead."
+ echo
+ exit 1
+ fi
+fi
+
+
+###############################
+# VARIABLES
+###############################
+
+# Abbreviate RID where it maps well to arch
+if [ "${_rid_arg_value}" == "linux-x64" ]; then
+ _file_out_arch="-x86_64"
+elif [ "${_rid_arg_value}" == "linux-arm64" ]; then
+ _file_out_arch="-aarch64"
+else
+ # Otherwise use RID itself
+ _file_out_arch="-${_rid_arg_value}"
+fi
+
+# APPDIR LOCATIONS
+export APPDIR_ROOT="${PKG_OUTPUT_DIR}/AppDir"
+
+if [ "${_kind_arg_value}" == "${_APPIMAGE_KIND}" ]; then
+ # AppImage
+ export APPDIR_USR="${APPDIR_ROOT}/usr"
+ export APPDIR_BIN="${APPDIR_ROOT}/usr/bin"
+ export APPDIR_SHARE="${APPDIR_ROOT}/usr/share"
+
+ _local_run="usr/bin/${APP_MAIN}${_exec_ext}"
+else
+ # Simple zip
+ export APPDIR_USR=""
+ export APPDIR_BIN="${APPDIR_ROOT}"
+ export APPDIR_SHARE="${APPDIR_ROOT}"
+
+ _local_run="${APP_MAIN}${_exec_ext}"
+fi
+
+export APPRUN_TARGET="${APPDIR_BIN}/${APP_MAIN}${_exec_ext}"
+
+
+# DOTNET PUBLISH
+if [ "${DOTNET_PROJECT_PATH}" != "${_DOTNET_NONE}" ]; then
+
+ _publish_cmd="dotnet publish"
+
+ if [ "${DOTNET_PROJECT_PATH}" != "" ] && [ "${DOTNET_PROJECT_PATH}" != "." ]; then
+ _publish_cmd="${_publish_cmd} \"${DOTNET_PROJECT_PATH}\""
+ fi
+
+ _publish_cmd="${_publish_cmd} -r ${_rid_arg_value}"
+
+ if [ "${APP_VERSION}" != "" ]; then
+ _publish_cmd="${_publish_cmd} -p:Version=${APP_VERSION}"
+ fi
+
+ if [ "${DOTNET_PUBLISH_ARGS}" != "" ]; then
+ _publish_cmd="${_publish_cmd} ${DOTNET_PUBLISH_ARGS}"
+ fi
+
+ _publish_cmd="${_publish_cmd} -o \"${APPDIR_BIN}\""
+
+fi
+
+
+# PACKAGE OUTPUT
+if [ $PKG_VERSION_FLAG == true ] && [ "${APP_VERSION}" != "" ]; then
+ _version_out="-${APP_VERSION}"
+fi
+
+if [ "${_kind_arg_value}" == "${_APPIMAGE_KIND}" ]; then
+
+ # AppImageTool
+ if [ "${_output_arg_value}" != "" ]; then
+ _package_out="${PKG_OUTPUT_DIR}/${_output_arg_value}"
+ else
+ _package_out="${PKG_OUTPUT_DIR}/${APP_MAIN}${_version_out}${_file_out_arch}${PKG_APPIMAGE_SUFFIX}"
+ fi
+
+ _package_cmd="${APPIMAGETOOL_COMMAND}"
+
+ if [ "${PKG_APPIMAGE_ARGS}" != "" ]; then
+ _package_cmd="${_package_cmd} ${PKG_APPIMAGE_ARGS}"
+ fi
+
+ _package_cmd="${_package_cmd} \"${APPDIR_ROOT}\" \"${_package_out}\""
+
+ if [ ${_runapp_arg_value} == true ]; then
+ _packrun_cmd="${_package_out}"
+ fi
+
+else
+
+ # Simple zip
+ if [ "${_output_arg_value}" != "" ]; then
+ _package_out="${PKG_OUTPUT_DIR}/${_output_arg_value}"
+ else
+ _package_out="${PKG_OUTPUT_DIR}/${APP_MAIN}${_version_out}${_file_out_arch}.zip"
+ fi
+
+ _package_cmd="(cd \"${APPDIR_ROOT}\" && zip -r \"${PWD}/${_package_out}\" ./)"
+
+ if [ ${_runapp_arg_value} == true ]; then
+ _packrun_cmd="${APPRUN_TARGET}"
+ fi
+
+fi
+
+
+###############################
+# DESKTOP ENTRY & APPDATA
+###############################
+
+if [ "${_kind_arg_value}" == "${_APPIMAGE_KIND}" ]; then
+
+ _desktop="[Desktop Entry]\n"
+ _desktop="${_desktop}Type=Application\n"
+ _desktop="${_desktop}Name=${DE_NAME}\n"
+ _desktop="${_desktop}Exec=AppRun\n"
+ _desktop="${_desktop}Terminal=${DE_TERMINAL_FLAG}\n"
+ _desktop="${_desktop}Categories=${DE_CATEGORIES}\n"
+
+ # Follow app-id
+ _desktop="${_desktop}Icon=${APP_ID}\n"
+
+ if [ "${DE_COMMENT}" != "" ]; then
+ _desktop="${_desktop}Comment=${DE_COMMENT}\n"
+ fi
+
+ if [ "${DE_KEYWORDS}" != "" ]; then
+ _desktop="${_desktop}Keywords=${DE_KEYWORDS}\n"
+ fi
+
+ _desktop="${_desktop}${DE_EXTEND}\n"
+fi
+
+
+# Load appdata.xml
+if [ "${APP_XML_SRC}" != "" ]; then
+
+ if command -v envsubst &> /dev/null; then
+ _appxml=$(envsubst <"${APP_XML_SRC}")
+ else
+ _appxml=$(<"${APP_XML_SRC}")
+ echo "WARNING: Variable substitution not available for: ${APP_XML_SRC}"
+ echo
+ fi
+
+fi
+
+
+###############################
+# DISPLAY & CONFIRM
+###############################
+
+echo "${_SCRIPT_TITLE}, ${_SCRIPT_VERSION}"
+echo "${_SCRIPT_COPYRIGHT}"
+echo
+
+echo "APP_MAIN: ${APP_MAIN}"
+echo "APP_ID: ${APP_ID}"
+echo "APP_VERSION: ${APP_VERSION}"
+echo "OUTPUT: ${_package_out}"
+echo
+
+if [ "${_desktop}" != "" ]; then
+ echo -e "${_desktop}"
+fi
+
+if [ ${_verbose_arg_value} == true ] && [ "${_appxml}" != "" ]; then
+ echo -e "${_appxml}\n"
+fi
+
+echo "Build Commands:"
+
+if [ "${_publish_cmd}" != "" ]; then
+ echo
+ echo "${_publish_cmd}"
+fi
+
+if [ "${POST_PUBLISH}" != "" ]; then
+ echo
+ echo "${POST_PUBLISH}"
+fi
+
+echo
+echo "${_package_cmd}"
+echo
+
+# Prompt
+if [ $_skipyes_arg_value == false ]; then
+
+ echo
+ read -p "Build now [N/y]? " prompt
+
+ if [ "${prompt}" != "y" ] && [ "${prompt}" != "Y" ]; then
+ echo
+ exit 1
+ fi
+
+ # Continue
+ echo
+fi
+
+
+###############################
+# PUBLISH & BUILD
+###############################
+
+# Clean and ensure directoy exists
+ensure_directory "${PKG_OUTPUT_DIR}"
+remove_path "${APPDIR_ROOT}"
+remove_path "${_package_out}"
+
+# Create AppDir structure
+ensure_directory "${APPDIR_BIN}"
+
+if [ "${_kind_arg_value}" != "${_ZIP_KIND}" ]; then
+ # We also create usr/share/icons, as some packages require this.
+ # See: https://github.com/kuiperzone/Publish-AppImage/issues/7
+ ensure_directory "${APPDIR_SHARE}/icons"
+fi
+
+echo
+
+# Publish dotnet
+if [ "${_publish_cmd}" != "" ]; then
+ exec_or_die "${_publish_cmd}"
+ echo
+fi
+
+# Post-publish
+if [ "${POST_PUBLISH}" != "" ]; then
+
+ exec_or_die "${POST_PUBLISH}"
+ echo
+
+fi
+
+# Application file must exist!
+if [ ! -f "${APPRUN_TARGET}" ]; then
+ echo "Expected application file not found: ${APPRUN_TARGET}"
+ echo
+ exit 1
+fi
+
+if [ "${_kind_arg_value}" == "${_APPIMAGE_KIND}" ]; then
+
+ echo
+
+ # Create desktop
+ if [ "${_desktop}" != "" ]; then
+ _file="${APPDIR_ROOT}/${APP_ID}.desktop"
+ echo "Creating: ${_file}"
+ echo -e "${_desktop}" > "${_file}"
+ assert_result
+ fi
+
+ if [ "${_appxml}" != "" ]; then
+ _dir="${APPDIR_SHARE}/metainfo"
+ _file="${_dir}/${APP_ID}.appdata.xml"
+ echo "Creating: ${_file}"
+ ensure_directory "${_dir}"
+ echo -e "${_appxml}" > "${_file}"
+ assert_result
+
+ if [ "${_desktop}" != "" ]; then
+ # Copy of desktop under "applications"
+ # Needed for launchable in appinfo.xml (if used)
+ # See https://github.com/AppImage/AppImageKit/issues/603
+ _dir="${APPDIR_SHARE}/applications"
+ _file="${_dir}/${APP_ID}.desktop"
+ echo "Creating: ${_file}"
+ ensure_directory "${_dir}"
+ echo -e "${_desktop}" > "${_file}"
+ assert_result
+ fi
+ fi
+
+ # Copy icon
+ if [ "${APP_ICON_SRC}" != "" ]; then
+
+ _icon_ext="${APP_ICON_SRC##*.}"
+
+ if [ "${_icon_ext}" != "" ]; then
+ _icon_ext=".${_icon_ext}"
+ fi
+
+ _temp="${APPDIR_ROOT}/${APP_ID}${_icon_ext}"
+ echo "Creating: ${_temp}"
+
+ cp "${APP_ICON_SRC}" "${_temp}"
+ assert_result
+ fi
+
+ # AppRun
+ _temp="${APPDIR_ROOT}/AppRun"
+
+ if [ ! -f "${_temp}" ]; then
+
+ echo "Creating: ${_temp}"
+ ln -s "${_local_run}" "${_temp}"
+ assert_result
+ fi
+fi
+
+# Build package
+echo
+exec_or_die "${_package_cmd}"
+echo
+
+echo "OUTPUT OK: ${_package_out}"
+echo
+
+if [ "${_packrun_cmd}" != "" ]; then
+ echo "RUNNING ..."
+ exec_or_die "${_packrun_cmd}"
+ echo
+fi
+
+exit 0
\ No newline at end of file
diff --git a/build/resources/appimage/publish-appimage.conf b/build/resources/appimage/publish-appimage.conf
new file mode 100644
index 00000000..6b17ddc0
--- /dev/null
+++ b/build/resources/appimage/publish-appimage.conf
@@ -0,0 +1,140 @@
+################################################################################
+# BASH FORMAT CONFIG: Publish-AppImage for .NET
+# WEBPAGE : https://kuiper.zone/publish-appimage-dotnet/
+################################################################################
+
+
+########################################
+# Application
+########################################
+
+# Mandatory application (file) name. This must be the base name of the main
+# runnable file to be created by the publish/build process. It should NOT
+# include any directory part or extension, i.e. do not append ".exe" or ".dll"
+# for dotnet. Example: "MyApp"
+APP_MAIN="sourcegit"
+
+# Mandatory application ID in reverse DNS form, i.e. "tld.my-domain.MyApp".
+# Exclude any ".desktop" post-fix. Note that reverse DNS form is necessary
+# for compatibility with Freedesktop.org metadata.
+APP_ID="com.sourcegit-scm.SourceGit"
+
+# Mandatory icon source file relative to this file (appimagetool seems to
+# require this). Use .svg or .png only. PNG should be one of standard sizes,
+# i.e, 128x128 or 256x256 pixels. Example: "Assets/app.svg"
+APP_ICON_SRC="sourcegit.png"
+
+# Optional Freedesktop.org metadata source file relative to this file. It is not essential
+# (leave empty) but will be used by appimagetool for repository information if provided.
+# See for information: https://docs.appimage.org/packaging-guide/optional/appstream.html
+# NB. The file may embed bash variables defined in this file and those listed below
+# (these will be substituted during the build). Examples include: "${APP_ID}"
+# and "".
+# $ISO_DATE : date of build, i.e. "2021-10-29",
+# $APP_VERSION : application version (if provided),
+# Example: "Assets/appdata.xml".
+APP_XML_SRC="sourcegit.appdata.xml"
+
+
+########################################
+# Desktop Entry
+########################################
+
+# Mandatory friendly name of the application.
+DE_NAME="SourceGit"
+
+# Mandatory category(ies), separated with semicolon, in which the entry should be
+# shown. See https://specifications.freedesktop.org/menu-spec/latest/apa.html
+# Examples: "Development", "Graphics", "Network", "Utility" etc.
+DE_CATEGORIES="Utility"
+
+# Optional short comment text (single line).
+# Example: "Perform calculations"
+DE_COMMENT="Open-source GUI client for git users"
+
+# Optional keywords, separated with semicolon. Values are not meant for
+# display and should not be redundant with the value of DE_NAME.
+DE_KEYWORDS=""
+
+# Flag indicating whether the program runs in a terminal window. Use true or false only.
+DE_TERMINAL_FLAG=false
+
+# Optional name-value text to be appended to the Desktop Entry file, thus providing
+# additional metadata. Name-values should not be redundant with values above and
+# are to be terminated with new line ("\n").
+# Example: "Comment[fr]=Effectue des calculs compliqués\nMimeType=image/x-foo"
+DE_EXTEND=""
+
+
+########################################
+# Dotnet Publish
+########################################
+
+# Optional path relative to this file in which to find the dotnet project (.csproj)
+# or solution (.sln) file, or the directory containing it. If empty (default), a single
+# project or solution file is expected under the same directory as this file.
+# IMPORTANT. If set to "null", dotnet publish is disabled (it is NOT called). Instead,
+# only POST_PUBLISH is called. Example: "Source/MyProject"
+DOTNET_PROJECT_PATH="../../../src/SourceGit.csproj"
+
+# Optional arguments suppled to "dotnet publish". Do NOT include "-r" (runtime) or version here as they will
+# be added (see also $APP_VERSION). Typically you want as a minimum: "-c Release --self-contained true".
+# Additional useful arguments include:
+# "-p:DebugType=None -p:DebugSymbols=false -p:PublishSingleFile=true -p:PublishTrimmed=true -p:TrimMode=link"
+# Refer: https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-publish
+DOTNET_PUBLISH_ARGS="-c Release -p:DebugType=None -p:DebugSymbols=false -p:PublishAot=true -p:PublishTrimmed=true -p:TrimMode=link --self-contained"
+
+
+########################################
+# POST-PUBLISH
+########################################
+
+# Optional post-publish or standalone build command. The value could, for example, copy
+# additional files into the "bin" directory. The working directory will be the location
+# of this file. The value is mandatory if DOTNET_PROJECT_PATH equals "null". In
+# addition to variables in this file, the following variables are exported prior:
+# $ISO_DATE : date of build, i.e. "2021-10-29",
+# $APP_VERSION : application version (if provided),
+# $DOTNET_RID : dotnet runtime identifier string provided at command line (i.e. "linux-x64),
+# $PKG_KIND : package kind (i.e. "appimage", "zip") provided at command line.
+# $APPDIR_ROOT : AppImage build directory root (i.e. "AppImages/AppDir").
+# $APPDIR_USR : AppImage user directory under root (i.e. "AppImages/AppDir/usr").
+# $APPDIR_BIN : AppImage bin directory under root (i.e. "AppImages/AppDir/usr/bin").
+# $APPRUN_TARGET : The expected target executable file (i.e. "AppImages/AppDir/usr/bin/app-name").
+# Example: "Assets/post-publish.sh"
+POST_PUBLISH="mv AppImages/AppDir/usr/bin/SourceGit AppImages/AppDir/usr/bin/sourcegit; rm -f AppImages/AppDir/usr/bin/*.dbg"
+
+
+########################################
+# Package Output
+########################################
+
+# Additional arguments for use with appimagetool. See appimagetool --help.
+# Default is empty. Example: "--sign"
+PKG_APPIMAGE_ARGS="--runtime-file=runtime-x86_64"
+
+# Mandatory output directory relative to this file. It will be created if it does not
+# exist. It will contain the final package file and temporary AppDir. Default: "AppImages".
+PKG_OUTPUT_DIR="AppImages"
+
+# Boolean which sets whether to include the application version in the filename of the final
+# output package (i.e. "HelloWorld-1.2.3-x86_64.AppImage"). It is ignored if $APP_VERSION is
+# empty or the "output" command arg is specified. Default and recommended: false.
+PKG_VERSION_FLAG=false
+
+# Optional AppImage output filename extension. It is ignored if generating a zip file, or if
+# the "output" command arg is specified. Default and recommended: ".AppImage".
+PKG_APPIMAGE_SUFFIX=".AppImage"
+
+
+########################################
+# Advanced Other
+########################################
+
+# The appimagetool command. Default is "appimagetool" which is expected to be found
+# in the $PATH. If the tool is not in path or has different name, a full path can be given,
+# example: "/home/user/Apps/appimagetool-x86_64.AppImage"
+APPIMAGETOOL_COMMAND="appimagetool"
+
+# Internal use only. Used for compatibility between conf and script. Do not modify.
+CONF_IMPL_VERSION=1
\ No newline at end of file
diff --git a/build/resources/appimage/runtime-x86_64 b/build/resources/appimage/runtime-x86_64
new file mode 100755
index 00000000..0c9535a1
Binary files /dev/null and b/build/resources/appimage/runtime-x86_64 differ
diff --git a/build/resources/appimage/sourcegit.appdata.xml b/build/resources/appimage/sourcegit.appdata.xml
new file mode 100644
index 00000000..ca304b4b
--- /dev/null
+++ b/build/resources/appimage/sourcegit.appdata.xml
@@ -0,0 +1,15 @@
+
+
+ com.sourcegit-scm.SourceGit
+ MIT
+ MIT
+ SourceGit
+ Open-source GUI client for git users
+
+
Open-source GUI client for git users
+
+ com.sourcegit-scm.SourceGit.desktop
+
+ com.sourcegit-scm.SourceGit.desktop
+
+
\ No newline at end of file
diff --git a/build/resources/appimage/sourcegit.png b/build/resources/appimage/sourcegit.png
new file mode 100644
index 00000000..8cdcd3a8
Binary files /dev/null and b/build/resources/appimage/sourcegit.png differ