mirror of
https://github.com/flatpak/flatpak.git
synced 2026-01-26 14:13:26 +00:00
The '&>' already redirects both stdout and stderr. Adding another '>' makes it ambiguous where stdout gets redirected to.
435 lines
13 KiB
Bash
Executable File
435 lines
13 KiB
Bash
Executable File
#!/bin/bash
|
|
#
|
|
# Copyright (C) 2020 Alexander Larsson <alexl@redhat.com>
|
|
#
|
|
# This library is free software; you can redistribute it and/or
|
|
# modify it under the terms of the GNU Lesser General Public
|
|
# License as published by the Free Software Foundation; either
|
|
# version 2 of the License, or (at your option) any later version.
|
|
#
|
|
# This library is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
# Lesser General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU Lesser General Public
|
|
# License along with this library; if not, write to the
|
|
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
# Boston, MA 02111-1307, USA.
|
|
|
|
set -euo pipefail
|
|
|
|
# We default to use systemdir, so we can also test shadowing from the user dir
|
|
export USE_SYSTEMDIR=yes
|
|
|
|
. $(dirname $0)/libtest.sh
|
|
|
|
skip_without_bwrap
|
|
skip_revokefs_without_fuse
|
|
|
|
echo "1..3"
|
|
|
|
setup_empty_repo &> /dev/null
|
|
|
|
# Manually add the user remote too
|
|
$FLATPAK remote-add --user --gpg-import=${FL_GPG_HOMEDIR}/pubring.gpg test-repo "http://127.0.0.1:${port}/test" >&2
|
|
|
|
|
|
# This tests the detection of unused refs. Used refs are any that have
|
|
# some kind of dependency from an installed application to the ref.
|
|
#
|
|
# Possible reasons a ref are used:
|
|
# Direct use:
|
|
# * App is installed
|
|
# * Runtime is marked as pinned and installed
|
|
#
|
|
# Dependent ref (of a used ref)
|
|
# * App $USED uses runtime $DEP
|
|
# * App $USED uses runtime $DEP as sdk (so that if you're developing the app we don't remove the sdk)
|
|
# * Runtime $USED has extra-data and not NoRuntime, and lists $DEP as "ExtensionOf"
|
|
# * Runtime $USED uses runtime $DEP as sdk
|
|
#
|
|
# Related ref (of a used ref):
|
|
# * App $USED uses extension $REL, which is not marked as autoprune-unless
|
|
# * Runtime $USED uses extension $REL, which is not marked as autoprune-unless
|
|
#
|
|
# There are options to affect this:
|
|
# * Specific refs can be excluded (never considered used), used to emulate them being uninstalled in a transaction
|
|
# * Specify custom new metadata for an installed ref, used to emulate it being updated in a transaction
|
|
#
|
|
# Additionally, for the system installation, the dependencies are considered from the user installation, such that any dependencies
|
|
# in the user installation that are resolved from the system installation (i.e. not in the user installation) are considered used.
|
|
# I.E. if an app and its runtime both are installed in the user dir, it is not considered used in the system installation, but if
|
|
# only the app is, then it is considered used.
|
|
|
|
create_runtime () {
|
|
local ID="${1}"
|
|
local SDK="${2}"
|
|
|
|
local BRANCH=stable
|
|
local DIR=`mktemp -d`
|
|
|
|
mkdir ${DIR}/files
|
|
mkdir ${DIR}/usr
|
|
cat > ${DIR}/metadata <<EOF
|
|
[Runtime]
|
|
name=${ID}
|
|
runtime=${ID}/$ARCH/$BRANCH
|
|
EOF
|
|
|
|
if test x$SDK != "x"; then
|
|
cat >> ${DIR}/metadata <<EOF
|
|
sdk=${SDK}/$ARCH/$BRANCH
|
|
EOF
|
|
fi
|
|
|
|
$FLATPAK build-finish $DIR ${finish_args[$ID]:-} &> /dev/null
|
|
$FLATPAK build-export -v ${FL_GPGARGS} --disable-sandbox --runtime repos/test ${DIR} ${BRANCH} &> /dev/null
|
|
rm -rf ${DIR}
|
|
}
|
|
|
|
create_app () {
|
|
local ID="${1}"
|
|
local RUNTIME="${2}"
|
|
local SDK="${3}"
|
|
|
|
local BRANCH=stable
|
|
local DIR=`mktemp -d`
|
|
|
|
mkdir ${DIR}/files
|
|
cat > ${DIR}/metadata <<EOF
|
|
[Application]
|
|
name=${ID}
|
|
runtime=${RUNTIME}/$ARCH/$BRANCH
|
|
EOF
|
|
|
|
if test x$SDK != "x"; then
|
|
cat >> ${DIR}/metadata <<EOF
|
|
sdk=${SDK}/$ARCH/$BRANCH
|
|
EOF
|
|
fi
|
|
|
|
set -x
|
|
$FLATPAK build-finish ${DIR} ${finish_args[$ID]:-} &> /dev/null
|
|
|
|
$FLATPAK build-export ${FL_GPGARGS} --disable-sandbox repos/test ${DIR} ${BRANCH} &> /dev/null > /dev/null
|
|
rm -rf ${DIR}
|
|
}
|
|
|
|
declare -a runtimes
|
|
declare -A runtimes_sdk
|
|
declare -A runtimes_pinned
|
|
declare -a apps
|
|
declare -A apps_runtime
|
|
declare -A apps_sdk
|
|
|
|
declare -A finish_args
|
|
|
|
declare -A installs_in
|
|
|
|
make_runtime() {
|
|
{ set +x; } 2>/dev/null
|
|
local ID="org.runtime.${1}"
|
|
local SDK="${2:-}"
|
|
if test x$SDK != x; then
|
|
SDK=org.runtime.$SDK
|
|
fi
|
|
runtimes+=( "$ID" )
|
|
runtimes_sdk["$ID"]="$SDK"
|
|
set -x
|
|
}
|
|
|
|
pin_runtime() {
|
|
{ set +x; } 2>/dev/null
|
|
local ID="org.runtime.${1}"
|
|
runtimes_pinned["$ID"]="yes"
|
|
set -x
|
|
}
|
|
|
|
install_runtime_in() {
|
|
{ set +x; } 2>/dev/null
|
|
local ID="org.runtime.${1}"
|
|
local WHERE="${2}"
|
|
installs_in["$ID"]=$WHERE
|
|
set -x
|
|
}
|
|
|
|
make_extension() {
|
|
{ set +x; } 2>/dev/null
|
|
local ID="org.extension.${1}"
|
|
runtimes+=( "$ID" )
|
|
set -x
|
|
}
|
|
|
|
pin_extension() {
|
|
{ set +x; } 2>/dev/null
|
|
local ID="org.extension.${1}"
|
|
runtimes_pinned["$ID"]="yes"
|
|
set -x
|
|
}
|
|
|
|
install_extension_in() {
|
|
{ set +x; } 2>/dev/null
|
|
local ID="org.extension.${1}"
|
|
local WHERE="${2}"
|
|
installs_in["$ID"]=$WHERE
|
|
set -x
|
|
}
|
|
|
|
runtime_add_extension() {
|
|
{ set +x; } 2>/dev/null
|
|
local RUNTIME="org.runtime.${1}"
|
|
local EXT="org.extension.${2}"
|
|
finish_args["$RUNTIME"]="${finish_args[$RUNTIME]:-} --extension=${EXT}=directory=/ext"
|
|
set -x
|
|
}
|
|
|
|
runtime_add_autoprune_extension() {
|
|
{ set +x; } 2>/dev/null
|
|
local RUNTIME="org.runtime.${1}"
|
|
local EXT="org.extension.${2}"
|
|
finish_args["$RUNTIME"]="${finish_args[$RUNTIME]:-} --extension=${EXT}=directory=/ext --extension=${EXT}=autoprune-unless=active-gl-driver"
|
|
set -x
|
|
}
|
|
|
|
make_runtime_full() {
|
|
make_runtime "$1" "${2:-}"
|
|
make_extension "$1.Locale"
|
|
runtime_add_extension "$1" $1.Locale
|
|
make_extension "$1.Debug"
|
|
runtime_add_extension "$1" $1.Debug
|
|
}
|
|
|
|
app_add_extension() {
|
|
{ set +x; } 2>/dev/null
|
|
local APP="org.app.${1}"
|
|
local EXT="org.extension.${2}"
|
|
finish_args["$APP"]="${finish_args[$APP]:-} --extension=${EXT}=directory=/ext"
|
|
set -x
|
|
}
|
|
|
|
install_app_in() {
|
|
{ set +x; } 2>/dev/null
|
|
local ID="org.app.${1}"
|
|
local WHERE="${2}"
|
|
installs_in["$ID"]=$WHERE
|
|
set -x
|
|
}
|
|
|
|
app_add_autoprune_extension() {
|
|
{ set +x; } 2>/dev/null
|
|
local APP="org.app.${1}"
|
|
local EXT="org.extension.${2}"
|
|
finish_args["$RUNTIME"]="${finish_args[$APP]:-} --extension=${EXT}=directory=/ext --extension=${EXT}=autoprune-unless=active-gl-driver"
|
|
set -x
|
|
}
|
|
|
|
make_app() {
|
|
{ set +x; } 2>/dev/null
|
|
local ID="org.app.${1}"
|
|
local RUNTIME="org.runtime.${2}"
|
|
local SDK="${3:-}"
|
|
if test x$SDK != x; then
|
|
SDK=org.runtime.$SDK
|
|
fi
|
|
|
|
apps+=( $ID )
|
|
apps_runtime[$ID]="$RUNTIME"
|
|
apps_sdk[$ID]="$SDK"
|
|
set -x
|
|
}
|
|
|
|
make_app_full() {
|
|
make_app "$1" "$2" "${3:-}"
|
|
make_extension "$1.Locale"
|
|
app_add_extension "$1" $1.Locale
|
|
make_extension "$1.Debug"
|
|
app_add_extension "$1" $1.Debug
|
|
}
|
|
|
|
make_it_happen() {
|
|
{ set +x; } 2>/dev/null
|
|
for runtime in "${runtimes[@]}"; do
|
|
create_runtime "$runtime" "${runtimes_sdk[$runtime]:-}"
|
|
done
|
|
for app in "${apps[@]}"; do
|
|
create_app "$app" "${apps_runtime[$app]}" "${apps_sdk[$app]}"
|
|
done
|
|
update_repo &> /dev/null
|
|
|
|
for runtime in "${runtimes[@]}"; do
|
|
local in=${installs_in[${runtime}]:-system}
|
|
if test $in = system -o $in = both; then
|
|
$FLATPAK install -y --system --no-deps --no-related --no-auto-pin test-repo runtime/$runtime/$ARCH/stable &> /dev/null
|
|
fi
|
|
if test $in = user -o $in = both; then
|
|
$FLATPAK install -y --user --no-deps --no-related --no-auto-pin test-repo runtime/$runtime/$ARCH/stable &> /dev/null
|
|
fi
|
|
if test "x${runtimes_pinned[$runtime]:-}" == "xyes"; then
|
|
$FLATPAK pin $runtime//stable
|
|
fi
|
|
done
|
|
for app in "${apps[@]}"; do
|
|
local in=${installs_in[$app]:-system}
|
|
if test $in = system -o $in = both; then
|
|
$FLATPAK install -y --system --no-deps --no-related --no-auto-pin test-repo app/$app/$ARCH/stable &> /dev/null
|
|
fi
|
|
if test $in = user -o $in = both; then
|
|
$FLATPAK install -y --user --no-deps --no-related --no-auto-pin test-repo app/$app/$ARCH/stable &> /dev/null
|
|
fi
|
|
done
|
|
|
|
$FLATPAK list --system -a --columns=ref | sort > installed.txt
|
|
$FLATPAK list --user -a --columns=ref | sort > user-installed.txt
|
|
|
|
# No USER_ should be in system dir
|
|
assert_not_file_has_content installed.txt USER_
|
|
|
|
set -x
|
|
}
|
|
|
|
verify_unused() {
|
|
comm -23 installed.txt unused.txt > used.txt
|
|
comm -12 used.txt unused.txt > used-and-unused.txt
|
|
assert_file_empty used-and-unused.txt
|
|
|
|
#echo ======= UNUSED ==============
|
|
#cat unused.txt
|
|
#echo ======= USED ==============
|
|
#cat used.txt
|
|
#echo =============================
|
|
|
|
assert_not_file_has_content unused.txt "\.USED"
|
|
assert_not_file_has_content used.txt "\.UNUSED"
|
|
# Also, no app or app extensions are unused
|
|
assert_not_file_has_content unused.txt "\.APP"
|
|
}
|
|
|
|
verify_autopruned() {
|
|
assert_file_has_content autopruned.txt "\.NONACTIVEGL"
|
|
assert_not_file_has_content autopruned.txt "PINNED_.\.NONACTIVEGL"
|
|
}
|
|
|
|
# This is used for the autoprune check
|
|
export FLATPAK_GL_DRIVERS=ACTIVEGL
|
|
|
|
# Runtime for app A, and it has its own sdk
|
|
make_runtime_full USED_A USED_A_SDK
|
|
make_runtime_full USED_A_SDK
|
|
# Sdk for app A, and it has its own sdk
|
|
make_runtime USED_A_SDK2 USED_A_SDK3
|
|
make_runtime USED_A_SDK3
|
|
# App A
|
|
make_app_full APP_A USED_A USED_A_SDK2
|
|
|
|
# Plain unused runtime
|
|
make_runtime_full UNUSED_B
|
|
|
|
# unused runtime with sdk
|
|
make_runtime_full UNUSED_C UNUSED_B_SDK
|
|
make_runtime_full UNUSED_C_SDK
|
|
|
|
# Unused extension and dependency
|
|
make_extension UNUSED_D
|
|
|
|
# Pinned runtime
|
|
make_runtime_full USED_E
|
|
pin_runtime USED_E
|
|
|
|
# Pinned extension
|
|
make_extension USED_F
|
|
pin_extension USED_F
|
|
|
|
# app with runtime with autopruned extension
|
|
make_app APP_G USED_G
|
|
make_runtime USED_G
|
|
make_extension USED_G.ACTIVEGL
|
|
runtime_add_autoprune_extension USED_G USED_G.ACTIVEGL
|
|
make_extension UNUSED_G.NONACTIVEGL
|
|
runtime_add_autoprune_extension USED_G UNUSED_G.NONACTIVEGL
|
|
make_extension PINNED_G.NONACTIVEGL
|
|
runtime_add_autoprune_extension USED_G PINNED_G.NONACTIVEGL
|
|
pin_extension PINNED_G.NONACTIVEGL
|
|
|
|
# unused runtime with autopruned extension
|
|
make_runtime UNUSED_H
|
|
make_extension UNUSED_H.ACTIVEGL
|
|
runtime_add_autoprune_extension UNUSED_H UNUSED_H.ACTIVEGL
|
|
make_extension UNUSED_H.NONACTIVEGL
|
|
runtime_add_autoprune_extension UNUSED_H UNUSED_H.NONACTIVEGL
|
|
|
|
# pinned runtime with autopruned extension
|
|
make_runtime USED_I
|
|
pin_runtime USED_I
|
|
make_extension USED_I.ACTIVEGL
|
|
runtime_add_autoprune_extension USED_I USED_I.ACTIVEGL
|
|
make_extension UNUSED_I.NONACTIVEGL
|
|
runtime_add_autoprune_extension USED_I UNUSED_I.NONACTIVEGL
|
|
|
|
# System runtime used by user app
|
|
make_runtime USED_J
|
|
make_app USER_APP_J USED_J
|
|
install_app_in USER_APP_J user
|
|
|
|
# System runtime shadowed by user app and runtime, but with and extension that isn't shadowed and one that is
|
|
make_extension USED_EXT_K
|
|
make_extension UNUSED_EXT2_K
|
|
install_extension_in UNUSED_EXT2_K both
|
|
make_runtime UNUSED_K
|
|
install_runtime_in UNUSED_K both
|
|
runtime_add_extension UNUSED_K USED_EXT_K
|
|
runtime_add_extension UNUSED_K UNUSED_EXT2_K
|
|
make_app USER_APP_K UNUSED_K
|
|
install_app_in USER_APP_K user
|
|
|
|
make_it_happen
|
|
|
|
# Verify that the right thing got user-installed
|
|
assert_file_has_content user-installed.txt USER_APP_J
|
|
assert_file_has_content user-installed.txt USER_APP_K
|
|
assert_file_has_content user-installed.txt UNUSED_K
|
|
assert_file_has_content user-installed.txt UNUSED_EXT2_K
|
|
assert_not_file_has_content user-installed.txt USED_EXT_K
|
|
|
|
${test_builddir}/list-unused | sed s@^app/@@g | sed s@^runtime/@@g | sort > unused.txt
|
|
|
|
verify_unused
|
|
|
|
ok "list unused regular"
|
|
|
|
${test_builddir}/list-unused --filter-autoprune | sed s@^app/@@g | sed s@^runtime/@@g | sort > autopruned.txt
|
|
|
|
verify_autopruned
|
|
|
|
ok "list autopruned"
|
|
|
|
mv unused.txt old-unused.txt
|
|
|
|
${test_builddir}/list-unused --exclude "app/org.app.APP_A/$ARCH/stable" | sed s@^app/@@g | sed s@^runtime/@@g | sort > unused.txt
|
|
|
|
# We don't report the excluded ref itself as unused. It's as if it wasn't even installed
|
|
assert_not_file_has_content unused.txt "org.app.APP_A/"
|
|
|
|
# Excluding a ref should not use more refs
|
|
comm -23 old-unused.txt unused.txt > newly-used.txt
|
|
assert_file_empty newly-used.txt
|
|
|
|
# We should add all dependencies from the app, but no more
|
|
assert_file_has_content unused.txt "org.extension.APP_A.Debug/"
|
|
assert_file_has_content unused.txt "org.extension.APP_A.Locale/"
|
|
assert_file_has_content unused.txt "org.runtime.USED_A/"
|
|
assert_file_has_content unused.txt "org.extension.USED_A.Debug/"
|
|
assert_file_has_content unused.txt "org.extension.USED_A.Locale/"
|
|
assert_file_has_content unused.txt "org.runtime.USED_A_SDK/"
|
|
assert_file_has_content unused.txt "org.extension.USED_A_SDK.Debug/"
|
|
assert_file_has_content unused.txt "org.extension.USED_A_SDK.Locale/"
|
|
assert_file_has_content unused.txt "org.runtime.USED_A_SDK2/"
|
|
assert_file_has_content unused.txt "org.runtime.USED_A_SDK3/"
|
|
|
|
comm -13 old-unused.txt unused.txt > newly-unused.txt
|
|
if [ $(cat newly-unused.txt | wc -l) -ne 10 ]; then
|
|
assert_not_reached "Unexpected unused ref"
|
|
fi
|
|
|
|
ok "list unused exclude"
|