2016-08-23 00:59:01 +02:00
#!/bin/bash
# This code is based on an example recipe from the AppImage project,
# https://github.com/probonopd/AppImages/blob/e05cbebc62c86f8c602d74d9050bbfbf10df1c69/recipes/powershell/Recipe
# Copyright (c) 2016 Simon Peter
# The license of this code and of https://github.com/probonopd/AppImages/raw/e05cbebc62c86f8c602d74d9050bbfbf10df1c69/functions.sh
# is the MIT License, see https://github.com/probonopd/AppImages/blob/e05cbebc62c86f8c602d74d9050bbfbf10df1c69/LICENSE
#
# Generate AppImage, http://appimage.org
#
# The resulting PowerShell AppImage is known to run on
# CentOS-7.0-1406-x86_64-GnomeLive.iso
# CentOS-7-x86_64-LiveGNOME-1511.iso
# Chromixium-1.5-amd64.iso
# Fedora-Live-Workstation-x86_64-22-3.iso
# Fedora-Live-Workstation-x86_64-23-10.iso
# SL-72-x86_64-2016-02-03-LiveDVDgnome.iso
# debian-live-8.0.0-amd64-xfce-desktop+nonfree.iso
# debian-live-8.4.0-amd64-gnome-desktop.iso
# elementary_OS_0.3_freya_amd64.iso
# kali-linux-2.0-amd64.iso
# kali-linux-2016.1-amd64.iso
# kubuntu-14.04.4-desktop-amd64.iso
# kubuntu-15.04-desktop-amd64.iso
# kubuntu-16.04-desktop-amd64.iso
# linuxmint-17.3-cinnamon-64bit.iso
# neon-devedition-gitunstable-20160814-0806-amd64.iso
# netrunner-17-64bit.iso
# ubuntu-14.04.1-desktop-amd64.iso
# ubuntu-16.04-desktop-amd64.iso
# ubuntu-gnome-16.04-desktop-amd64.iso
# ubuntu-mate-16.04-desktop-amd64.iso
# xubuntu-16.04-desktop-amd64.iso
APP = powershell
2017-03-03 19:37:16 +01:00
# Generate status file for use by apt-get; assuming that the recipe uses no newer
# ingredients than what would require more recent dependencies than what we assume
# to be part of the base system
generate_status( )
{
mkdir -p ./tmp/archives/
mkdir -p ./tmp/lists/partial
touch tmp/pkgcache.bin tmp/srcpkgcache.bin
rm status 2>/dev/null || true
for PACKAGE in "apt apt-transport-https dbus debconf dictionaries-common dpkg fontconfig fontconfig-config gksu glib-networking gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-ugly gstreamer1.0-pulseaudio gtk2-engines-pixbuf gvfs-backends kde-runtime libasound2 libatk1.0-0 libc6 libc6-dev libcairo2 libcups2 libdbus-1-3 libdrm2 libegl1-mesa libfontconfig1 libgbm1 libgcc1 libgdk-pixbuf2.0-0 libgl1 libgl1-mesa libgl1-mesa-dri libgl1-mesa-glx libglib2.0-0 libglu1-mesa libgpg-error0 libgtk2.0-0 libgtk-3-0 libnss3 libpango-1.0-0 libpango1.0-0 libpangocairo-1.0-0 libpangoft2-1.0-0 libstdc++6 libtasn1-6 libwayland-egl1-mesa libxcb1 lsb-base mime-support passwd udev uuid-runtime" ; do
printf " Package: $PACKAGE \nStatus: install ok installed\nArchitecture: all\nVersion: 9:999.999.999\n\n " >> status
done
}
# Delete blacklisted files
delete_blacklisted( )
{
BLACKLISTED_FILES = "libc.so.6 libdl.so.2 libstdc++.so.6 libm.so.6 libpthread.so.0 libresolv.so.2 libGL.so.1 libdrm.so.2 libxcb.so.1 libX11.so.6 libgio-2.0.so.0 libgdk-x11-2.0.so.0 libgtk-x11-2.0.so.0 libasound.so.2 libgdk_pixbuf-2.0.so.0 libfontconfig.so.1 libselinux.so.1 libcom_err.so.2 libcrypt.so.1 libexpat.so.1 libgcc_s.so.1 libglib-2.0.so.0 libgpg-error.so.0 libgssapi_krb5.so.2 libhcrypto.so.4 libhx509.so.5 libICE.so.6 libidn.so.11 libk5crypto.so.3 libkeyutils.so.1 libkrb5.so.26 libkrb5.so.3 libkrb5support.so.0 libm.so.6 libp11-kit.so.0 libpthread.so.0 libresolv.so.2 libroken.so.18 librt.so.1 libSM.so.6 libusb-1.0.so.0 libuuid.so.1 libwind.so.0 libz.so.1 libGL.so.1 libdrm.so.2 libgobject-2.0.so.0 libgpg-error.so.0 libxcb.so.1"
echo $BLACKLISTED_FILES
for FILE in $BLACKLISTED_FILES ; do
FOUND = $( find . -type f -name " ${ FILE } " 2>/dev/null)
if [ ! -z " $FOUND " ] ; then
echo " Deleting blacklisted ${ FOUND } "
rm -f " ${ FOUND } "
fi
done
# Do not bundle developer stuff
rm -rf usr/include || true
rm -rf usr/lib/cmake || true
rm -rf usr/lib/pkgconfig || true
find . -name '*.la' | xargs -i rm { }
}
# Add desktop integration
# Usage: get_desktopintegration name_of_desktop_file_and_exectuable
get_desktopintegration( )
{
REALBIN = $( grep -o "^Exec=.*" *.desktop | sed -e 's|Exec=||g' | cut -d " " -f 1 | head -n 1)
cat > ./usr/bin/$REALBIN .wrapper <<\E OxxF
#!/bin/bash
# The purpose of this script is to provide lightweight desktop integration
# into the host system without special help from the host system.
# If you want to use it, then place this in usr/bin/$APPNAME.wrapper
# and set it as the Exec= line of the .desktop file in the AppImage.
#
# For example, to install the appropriate icons for Scribus,
# put them into the AppDir at the following locations:
#
# ./usr/share/icons/default/128x128/apps/scribus.png
# ./usr/share/icons/default/128x128/mimetypes/application-vnd.scribus.png
#
# Note that the filename application-vnd.scribus.png is derived from
# and must be match MimeType=application/vnd.scribus; in scribus.desktop
# (with "/" characters replaced by "-").
#
# Then, change Exec=scribus to Exec=scribus.wrapper and place the script
# below in usr/bin/scribus.wrapper and make it executable.
# When you run AppRun, then AppRun runs the wrapper script below
# which in turn will run the main application.
#
# TODO:
# Handle multiple versions of the same AppImage?
# Handle removed AppImages? Currently we are just setting TryExec=
# See http://specifications.freedesktop.org/thumbnail-spec/thumbnail-spec-latest.html#DELETE
# Possibly move this to the C runtime that is part of every AppImage?
# Exit on errors
set -e
# Be verbose if $DEBUG=1 is set
if [ ! -z " $DEBUG " ] ; then
env
set -x
fi
THIS = " $0 "
args = ( " $@ " ) # http://stackoverflow.com/questions/3190818/
NUMBER_OF_ARGS = " $# "
# Please do not change $VENDORPREFIX as it will allow for desktop files
# belonging to AppImages to be recognized by future AppImageKit components
# such as desktop integration daemons
VENDORPREFIX = appimagekit
find-up ( ) {
path = " $( dirname " $( readlink -f " ${ THIS } " ) " ) "
while [ [ " $path " != "" && ! -e " $path / $1 " ] ] ; do
path = ${ path %/* }
done
# echo "$path"
}
if [ -z $APPDIR ] ; then
# Find the AppDir. It is the directory that contains AppRun.
# This assumes that this script resides inside the AppDir or a subdirectory.
# If this script is run inside an AppImage, then the AppImage runtime
# likely has already set $APPDIR
APPDIR = $( find-up "AppRun" )
fi
FILENAME = " $( readlink -f " ${ THIS } " ) "
DIRNAME = $( dirname $FILENAME )
DESKTOPFILE = $( find " $APPDIR " -maxdepth 1 -name "*.desktop" | head -n 1)
DESKTOPFILE_NAME = $( basename " ${ DESKTOPFILE } " )
APP_FULL = $( sed -n -e 's/^Name=//p' " ${ DESKTOPFILE } " | head -n 1)
APP = $( echo " $APP_FULL " | tr -c -d '[:alnum:]' )
if [ -z " $APP " ] || [ -z " $APP_FULL " ] ; then
APP = $( echo " $DESKTOPFILE_NAME " | sed -e 's/.desktop//g' )
APP_FULL = " $APP "
fi
RETURN = "yes"
if [ [ " $FILENAME " != *.wrapper ] ] ; then
echo " ${ THIS } is not named correctly. It should be named \$Exec.wrapper "
exit 0
fi
BIN = $( echo " $FILENAME " | sed -e 's|.wrapper||g' )
if [ [ ! -f " $BIN " ] ] ; then
echo " $BIN not found "
exit 0
fi
trap atexit EXIT
# Note that the following handles 0, 1 or more arguments (file paths)
# which can include blanks but uses a bashism; can the same be achieved
# in POSIX-shell? (FIXME)
# http://stackoverflow.com/questions/3190818
atexit( )
{
if [ -z " $SKIP " ] ; then
if [ $NUMBER_OF_ARGS -eq 0 ] ; then
exec " ${ BIN } "
else
exec " ${ BIN } " " ${ args [@] } "
fi
fi
}
error( )
{
if [ -x /usr/bin/zenity ] ; then
LD_LIBRARY_PATH = "" zenity --error --text " ${ 1 } " 2>/dev/null
elif [ -x /usr/bin/kdialog ] ; then
LD_LIBRARY_PATH = "" kdialog --msgbox " ${ 1 } " 2>/dev/null
elif [ -x /usr/bin/Xdialog ] ; then
LD_LIBRARY_PATH = "" Xdialog --msgbox " ${ 1 } " 2>/dev/null
else
echo " ${ 1 } "
fi
exit 1
}
yesno( )
{
TITLE = $1
TEXT = $2
if [ -x /usr/bin/zenity ] ; then
LD_LIBRARY_PATH = "" zenity --question --title= " $TITLE " --text= " $TEXT " 2>/dev/null && RETURN = "yes" || RETURN = "no"
elif [ -x /usr/bin/kdialog ] ; then
LD_LIBRARY_PATH = "" kdialog --caption "" --title " $TITLE " -yesno " $TEXT " && RETURN = "yes" || RETURN = "no"
elif [ -x /usr/bin/Xdialog ] ; then
LD_LIBRARY_PATH = "" Xdialog --title " $TITLE " --clear --yesno " $TEXT " 10 80 && RETURN = "yes" || RETURN = "no"
else
echo " zenity, kdialog, Xdialog missing. Skipping ${ THIS } . "
exit 0
fi
}
check_prevent( )
{
FILE = $1
if [ -e " $FILE " ] ; then
exit 0
fi
}
check_dep( )
{
DEP = $1
if [ -z $( which $DEP ) ] ; then
echo " $DEP is missing. Skipping ${ THIS } . "
exit 0
fi
}
# Determine where the desktop file should be installed
if [ [ $EUID -ne 0 ] ] ; then
DESTINATION_DIR_DESKTOP = " $HOME /.local/share/applications "
STAMP_DIR = " $HOME /.local/share/ $VENDORPREFIX "
SYSTEM_WIDE = ""
else
# TODO: Check $XDG_DATA_DIRS
DESTINATION_DIR_DESKTOP = "/usr/local/share/applications"
STAMP_DIR = " /etc/ $VENDORPREFIX "
SYSTEM_WIDE = "--mode system" # for xdg-mime and xdg-icon-resource
fi
# Remove desktop integration for this AppImage
if [ " x $1 " = "x--remove-appimage-desktop-integration" ] ; then
SKIP = "yes"
rm -f " $STAMP_DIR / ${ APP } _no_desktopintegration " " $DESTINATION_DIR_DESKTOP / $VENDORPREFIX - $DESKTOPFILE_NAME "
check_dep xdg-desktop-menu
xdg-desktop-menu forceupdate
exit 0
fi
# Exit immediately if one of these files is present
# (e.g., because the desktop environment wants to handle desktop integration itself)
check_prevent " $HOME /.local/share/ $VENDORPREFIX /no_desktopintegration "
check_prevent " /usr/share/ $VENDORPREFIX /no_desktopintegration "
check_prevent " /etc/ $VENDORPREFIX /no_desktopintegration "
# Exit immediately if appimaged is running
pidof appimaged >/dev/null 2>& 1 && exit 0
# Exit immediately if $DESKTOPINTEGRATION is not empty
if [ ! -z " $DESKTOPINTEGRATION " ] ; then
exit 0
fi
# Check whether dependencies are present in base system (we do not bundle these)
# http://cgit.freedesktop.org/xdg/desktop-file-utils/
check_dep desktop-file-validate
check_dep update-desktop-database
check_dep desktop-file-install
check_dep xdg-icon-resource
check_dep xdg-mime
check_dep xdg-desktop-menu
# Exit immediately if one of these files is present (disabled per app)
check_prevent " $HOME /.local/share/ $VENDORPREFIX / ${ APP } _no_desktopintegration "
check_prevent " /usr/share/ $VENDORPREFIX / ${ APP } _no_desktopintegration "
check_prevent " /etc/ $VENDORPREFIX / ${ APP } _no_desktopintegration "
if [ ! -f " $DESKTOPFILE " ] ; then
echo " Desktop file is missing. Please run ${ THIS } from within an AppImage. "
exit 0
fi
if [ -z " $APPIMAGE " ] ; then
APPIMAGE = " $APPDIR /AppRun "
# Not running from within an AppImage; hence using the AppRun for Exec=
fi
ICONFILE = " $APPDIR /.DirIcon "
# $XDG_DATA_DIRS contains the default paths /usr/local/share:/usr/share
# desktop file has to be installed in an applications subdirectory
# of one of the $XDG_DATA_DIRS components
if [ -z " $XDG_DATA_DIRS " ] ; then
echo " \$XDG_DATA_DIRS is missing. Please run ${ THIS } from within an AppImage. "
exit 0
fi
# Check if the desktop file is already there
# and if so, whether it points to the same AppImage
if [ -e " $DESTINATION_DIR_DESKTOP / $VENDORPREFIX - $DESKTOPFILE_NAME " ] ; then
# echo "$DESTINATION_DIR_DESKTOP/$VENDORPREFIX-$DESKTOPFILE_NAME already there"
EXEC = $( grep "^Exec=" " $DESTINATION_DIR_DESKTOP / $VENDORPREFIX - $DESKTOPFILE_NAME " | head -n 1 | cut -d " " -f 1)
# echo $EXEC
if [ " Exec=\" $APPIMAGE \" " = = " $EXEC " ] ; then
exit 0
fi
fi
# We ask the user only if we have found no reason to skip until here
if [ -z " $SKIP " ] ; then
yesno "Install" " Would you like to integrate $APPIMAGE with your system?\n\nThis will add it to your applications menu and install icons.\nIf you don't do this you can still launch the application by double-clicking on the AppImage. "
fi
if [ " $RETURN " = "no" ] ; then
yesno "Disable question?" " Should this question be permanently disabled for $APP ?\n\nTo re-enable this question you have to delete\n\" $STAMP_DIR / ${ APP } _no_desktopintegration\" "
if [ " $RETURN " = "yes" ] ; then
mkdir -p " $STAMP_DIR "
touch " $STAMP_DIR / ${ APP } _no_desktopintegration "
fi
exit 0
fi
# If the user has agreed, rewrite and install the desktop file, and the MIME information
if [ -z " $SKIP " ] ; then
# desktop-file-install is supposed to install .desktop files to the user's
# applications directory when run as a non-root user,
# and to /usr/share/applications if run as root
# but that does not really work for me...
#
# For Exec we must use quotes
# For TryExec quotes is not supported, so, space must be replaced to \s
# https://askubuntu.com/questions/175404/how-to-add-space-to-exec-path-in-a-thumbnailer-descrption/175567
RESOURCE_NAME = $( echo " $VENDORPREFIX - $DESKTOPFILE_NAME " | sed -e 's/.desktop//g' )
desktop-file-install --rebuild-mime-info-cache \
--vendor= $VENDORPREFIX --set-key= Exec --set-value= " \" ${ APPIMAGE } \" %U " \
--set-key= X-AppImage-Comment --set-value= " Generated by ${ THIS } " \
--set-icon= " $RESOURCE_NAME " --set-key= TryExec --set-value= ${ APPIMAGE // / \\ s } " $DESKTOPFILE " \
--dir " $DESTINATION_DIR_DESKTOP "
chmod a+x " $DESTINATION_DIR_DESKTOP / " *
# echo $RESOURCE_NAME
# delete "Actions" entry and add an "Uninstall" action
sed -i -e '/^Actions=/d' " $DESTINATION_DIR_DESKTOP / $VENDORPREFIX - $DESKTOPFILE_NAME "
cat >> " $DESTINATION_DIR_DESKTOP / $VENDORPREFIX - $DESKTOPFILE_NAME " << EOF
Actions = Uninstall;
[ Uninstall]
Name = Remove desktop integration for $APP_FULL
Exec = " $APPIMAGE " --remove-appimage-desktop-integration
EOF
# Install the icon files for the application; TODO: scalable
ICONS = $( find " ${ APPDIR } /usr/share/icons/ " -iwholename " */apps/ ${ APP } .png " 2>/dev/null || true )
for ICON in $ICONS ; do
ICON_SIZE = $( echo " ${ ICON } " | rev | cut -d "/" -f 3 | rev | cut -d "x" -f 1)
xdg-icon-resource install --context apps --size ${ ICON_SIZE } " ${ ICON } " " ${ RESOURCE_NAME } "
done
# Install mime type
find " ${ APPDIR } /usr/share/mime/ " -type f -name *xml -exec xdg-mime install $SYSTEM_WIDE --novendor { } \; 2>/dev/null || true
# Install the icon files for the mime type; TODO: scalable
ICONS = $( find " ${ APPDIR } /usr/share/icons/ " -iwholename "*/mimetypes/*.png" 2>/dev/null || true )
for ICON in $ICONS ; do
ICON_SIZE = $( echo " ${ ICON } " | rev | cut -d "/" -f 3 | rev | cut -d "x" -f 1)
xdg-icon-resource install --context mimetypes --size ${ ICON_SIZE } " ${ ICON } " $( basename $ICON | sed -e 's/.png//g' )
done
xdg-desktop-menu forceupdate
gtk-update-icon-cache # for MIME
fi
EOxxF
chmod a+x ./usr/bin/$REALBIN .wrapper
sed -i -e " s|^Exec= $REALBIN |Exec= $REALBIN .wrapper|g " $1 .desktop
}
2016-08-23 00:59:01 +02:00
mkdir -p ./$APP /$APP .AppDir/usr/lib
cd ./$APP /
# We get this app and almost all its dependencies via apt-get
# but not using the host system's information about what is
# installed on the system but our own assumptions instead
mkdir -p ./tmp/archives/
mkdir -p ./tmp/lists/partial
touch tmp/pkgcache.bin tmp/srcpkgcache.bin
generate_status
echo " deb http://archive.ubuntu.com/ubuntu/ trusty main universe
" > sources.list
OPTIONS = " -o Debug::NoLocking=1
-o APT::Cache-Limit= 125829120
-o Dir::Etc::sourcelist= ./sources.list
-o Dir::State= ./tmp
-o Dir::Cache= ./tmp
-o Dir::State::status= ./status
-o Dir::Etc::sourceparts= -
-o APT::Get::List-Cleanup= 0
-o APT::Get::AllowUnauthenticated= 1
-o Debug::pkgProblemResolver= true
-o Debug::pkgDepCache::AutoInstall= true
-o APT::Install-Recommends= 0
-o APT::Install-Suggests= 0
"
cp ../powershell_*_amd64.deb .
# Add local repository so that we can install deb files
# that were downloaded outside of a repository
dpkg-scanpackages . /dev/null | gzip -9c > Packages.gz
echo " deb file: $( readlink -e $PWD ) ./ " >> sources.list
apt-get $OPTIONS update
URLS = $( apt-get $OPTIONS -y install --print-uris $APP | cut -d "'" -f 2 | grep -e "^http" )
wget -c $URLS
cd ./$APP .AppDir/
find ../*.deb -exec dpkg -x { } . \; || true
rm usr/bin/powershell
mv opt/microsoft/powershell/*/* usr/bin/
cat > $APP .desktop <<\E OF
[ Desktop Entry]
Name = PowerShell
Comment = Microsoft PowerShell
Exec = powershell
Keywords = shell; prompt; command; commandline; cmd;
Icon = powershell
Type = Application
Categories = System; TerminalEmulator;
StartupNotify = true
Terminal = true
EOF
cp ../../assets/Powershell_256.png $APP .png
2017-02-15 19:47:44 +01:00
cp ../../assets/AppImageThirdPartyNotices.txt ThirdPartyNotices.txt
2016-08-23 00:59:01 +02:00
cat > ./AppRun <<\E OF
2017-04-11 00:49:05 +02:00
#!/bin/bash
2016-08-23 00:59:01 +02:00
HERE = $( dirname $( readlink -f " ${ 0 } " ) )
export PATH = " ${ HERE } /usr/bin/ " :$PATH
export LD_LIBRARY_PATH = " ${ HERE } /usr/lib/ " :$LD_LIBRARY_PATH
exec " ${ HERE } /usr/bin/powershell.wrapper " " $@ "
EOF
chmod a+x ./AppRun
2017-03-03 19:37:16 +01:00
mkdir -p ./usr/lib ./lib && find ./lib/ -exec cp -v --parents -rfL { } ./usr/ \; && rm -rf ./lib
mkdir -p ./usr/lib ./lib64 && find ./lib64/ -exec cp -v --parents -rfL { } ./usr/ \; && rm -rf ./lib64
2016-08-23 00:59:01 +02:00
mv ./usr/lib/x86_64-linux-gnu/* ./usr/lib/ # AppRun sets Qt env here
mv ./usr/lib/pulseaudio/*.so usr/lib/ || true
mv usr/local/share/man usr/share/ || true
delete_blacklisted
rm -rf ./etc/ ./home/ ./lib/ || true
rm -r opt/ usr/lib/x86_64-linux-gnu/ usr/lib64 usr/share/ || true
VERSION = $( find ../*.deb -name $APP "_*" | head -n 1 | cut -d "~" -f 1 | cut -d "_" -f 2 | cut -d "-" -f 1-2 | sed -e 's|1%3a||g' )
echo $VERSION
get_desktopintegration $APP
sed -i -e 's|^echo|# echo|g' usr/bin/$APP .wrapper # Make less verbose
# Go out of AppImage
cd ..
2017-03-03 19:37:16 +01:00
wget -c https://psgithub.blob.core.windows.net/files/appimagetool-x86_64.AppImage
chmod a+x appimagetool-x86_64.AppImage
./appimagetool-x86_64.AppImage ./powershell.AppDir
cp ./PowerShell*AppImage ..
2016-08-23 00:59:01 +02:00
cd ..