{suffix!s}"
+"code> for unit {name!s}."
msgstr ""
-"Unknown systemd commands {command!s}
and "
-"{suffix!s}
for unit {name!s}."
-
-#: src/modules/mkinitfs/main.py:27
-msgid "Creating initramfs with mkinitfs."
-msgstr "Creating initramfs with mkinitfs."
-
-#: src/modules/mkinitfs/main.py:49
-msgid "Failed to run mkinitfs on the target"
-msgstr "Failed to run mkinitfs on the target"
#: src/modules/unpackfs/main.py:34
msgid "Filling up filesystems."
-msgstr "Filling up filesystems."
+msgstr ""
#: src/modules/unpackfs/main.py:254
msgid "rsync failed with error code {}."
-msgstr "rsync failed with error code {}."
+msgstr ""
#: src/modules/unpackfs/main.py:299
msgid "Unpacking image {}/{}, file {}/{}"
-msgstr "Unpacking image {}/{}, file {}/{}"
+msgstr ""
#: src/modules/unpackfs/main.py:314
msgid "Starting to unpack {}"
-msgstr "Starting to unpack {}"
+msgstr ""
#: src/modules/unpackfs/main.py:323 src/modules/unpackfs/main.py:467
msgid "Failed to unpack image \"{}\""
-msgstr "Failed to unpack image \"{}\""
+msgstr ""
#: src/modules/unpackfs/main.py:430
msgid "No mount point for root partition"
-msgstr "No mount point for root partition"
+msgstr ""
#: src/modules/unpackfs/main.py:431
msgid "globalstorage does not contain a \"rootMountPoint\" key."
-msgstr "globalstorage does not contain a \"rootMountPoint\" key."
+msgstr ""
#: src/modules/unpackfs/main.py:434
msgid "Bad mount point for root partition"
-msgstr "Bad mount point for root partition"
+msgstr ""
#: src/modules/unpackfs/main.py:435
msgid "rootMountPoint is \"{}\", which does not exist."
-msgstr "rootMountPoint is \"{}\", which does not exist."
+msgstr ""
#: src/modules/unpackfs/main.py:439 src/modules/unpackfs/main.py:455
#: src/modules/unpackfs/main.py:459 src/modules/unpackfs/main.py:465
#: src/modules/unpackfs/main.py:480
msgid "Bad unpackfs configuration"
-msgstr "Bad unpackfs configuration"
+msgstr ""
#: src/modules/unpackfs/main.py:440
msgid "There is no configuration information."
-msgstr "There is no configuration information."
+msgstr ""
#: src/modules/unpackfs/main.py:456
msgid "The filesystem for \"{}\" ({}) is not supported by your current kernel"
-msgstr "The filesystem for \"{}\" ({}) is not supported by your current kernel"
+msgstr ""
#: src/modules/unpackfs/main.py:460
msgid "The source filesystem \"{}\" does not exist"
-msgstr "The source filesystem \"{}\" does not exist"
+msgstr ""
#: src/modules/unpackfs/main.py:466
msgid ""
"Failed to find unsquashfs, make sure you have the squashfs-tools package "
"installed."
msgstr ""
-"Failed to find unsquashfs, make sure you have the squashfs-tools package "
-"installed."
#: src/modules/unpackfs/main.py:481
msgid "The destination \"{}\" in the target system is not a directory"
-msgstr "The destination \"{}\" in the target system is not a directory"
+msgstr ""
+
+#: src/modules/displaymanager/main.py:524
+msgid "Cannot write KDM configuration file"
+msgstr ""
+
+#: src/modules/displaymanager/main.py:525
+msgid "KDM config file {!s} does not exist"
+msgstr ""
+
+#: src/modules/displaymanager/main.py:586
+msgid "Cannot write LXDM configuration file"
+msgstr ""
+
+#: src/modules/displaymanager/main.py:587
+msgid "LXDM config file {!s} does not exist"
+msgstr ""
+
+#: src/modules/displaymanager/main.py:670
+msgid "Cannot write LightDM configuration file"
+msgstr ""
+
+#: src/modules/displaymanager/main.py:671
+msgid "LightDM config file {!s} does not exist"
+msgstr ""
+
+#: src/modules/displaymanager/main.py:745
+msgid "Cannot configure LightDM"
+msgstr ""
+
+#: src/modules/displaymanager/main.py:746
+msgid "No LightDM greeter installed."
+msgstr ""
+
+#: src/modules/displaymanager/main.py:777
+msgid "Cannot write SLIM configuration file"
+msgstr ""
+
+#: src/modules/displaymanager/main.py:778
+msgid "SLIM config file {!s} does not exist"
+msgstr ""
+
+#: src/modules/displaymanager/main.py:991
+msgid "No display managers selected for the displaymanager module."
+msgstr ""
+
+#: src/modules/displaymanager/main.py:992
+msgid ""
+"The displaymanagers list is empty or undefined in both globalstorage and "
+"displaymanager.conf."
+msgstr ""
+
+#: src/modules/displaymanager/main.py:1074
+msgid "Display manager configuration was incomplete"
+msgstr ""
+
+#: src/modules/initcpiocfg/main.py:28
+msgid "Configuring mkinitcpio."
+msgstr ""
+
+#: src/modules/initcpiocfg/main.py:240 src/modules/initramfscfg/main.py:90
+#: src/modules/openrcdmcryptcfg/main.py:77 src/modules/fstab/main.py:368
+#: src/modules/localecfg/main.py:141 src/modules/networkcfg/main.py:106
+msgid "No root mount point is given for {!s}
to use."
+msgstr ""
+
+#: src/modules/rawfs/main.py:26
+msgid "Installing data."
+msgstr ""
+
+#: src/modules/services-openrc/main.py:29
+msgid "Configure OpenRC services"
+msgstr ""
+
+#: src/modules/services-openrc/main.py:57
+msgid "Cannot add service {name!s} to run-level {level!s}."
+msgstr ""
+
+#: src/modules/services-openrc/main.py:59
+msgid "Cannot remove service {name!s} from run-level {level!s}."
+msgstr ""
+
+#: src/modules/services-openrc/main.py:61
+msgid ""
+"Unknown service-action {arg!s}
for service {name!s} in run-"
+"level {level!s}."
+msgstr ""
+
+#: src/modules/services-openrc/main.py:94
+msgid ""
+"rc-update {arg!s}
call in chroot returned error code {num!s}."
+msgstr ""
+
+#: src/modules/services-openrc/main.py:101
+msgid "Target runlevel does not exist"
+msgstr ""
+
+#: src/modules/services-openrc/main.py:102
+msgid ""
+"The path for runlevel {level!s} is {path!s}
, which does not "
+"exist."
+msgstr ""
+
+#: src/modules/services-openrc/main.py:110
+msgid "Target service does not exist"
+msgstr ""
+
+#: src/modules/services-openrc/main.py:111
+msgid ""
+"The path for service {name!s} is {path!s}
, which does not exist."
+msgstr ""
+
+#: src/modules/plymouthcfg/main.py:27
+msgid "Configure Plymouth theme"
+msgstr ""
+
+#: src/modules/packages/main.py:54 src/modules/packages/main.py:65
+#: src/modules/packages/main.py:75
+msgid "Install packages."
+msgstr ""
+
+#: src/modules/packages/main.py:63
+#, python-format
+msgid "Processing packages (%(count)d / %(total)d)"
+msgstr ""
+
+#: src/modules/packages/main.py:68
+#, python-format
+msgid "Installing one package."
+msgid_plural "Installing %(num)d packages."
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/modules/packages/main.py:71
+#, python-format
+msgid "Removing one package."
+msgid_plural "Removing %(num)d packages."
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/modules/packages/main.py:725 src/modules/packages/main.py:737
+#: src/modules/packages/main.py:765
+msgid "Package Manager error"
+msgstr ""
+
+#: src/modules/packages/main.py:726
+msgid ""
+"The package manager could not prepare updates. The command {!s}
"
+"returned error code {!s}."
+msgstr ""
+
+#: src/modules/packages/main.py:738
+msgid ""
+"The package manager could not update the system. The command {!s}
"
+"returned error code {!s}."
+msgstr ""
+
+#: src/modules/packages/main.py:766
+msgid ""
+"The package manager could not make changes to the installed system. The "
+"command {!s}
returned error code {!s}."
+msgstr ""
+
+#: src/modules/bootloader/main.py:43
+msgid "Install bootloader."
+msgstr ""
+
+#: src/modules/bootloader/main.py:614
+msgid "Failed to install grub, no partitions defined in global storage"
+msgstr ""
+
+#: src/modules/bootloader/main.py:782
+msgid "Bootloader installation error"
+msgstr ""
+
+#: src/modules/bootloader/main.py:783
+msgid ""
+"The bootloader could not be installed. The installation command {!s}"
+"pre> returned error code {!s}."
+msgstr ""
+
+#: src/modules/hwclock/main.py:26
+msgid "Setting hardware clock."
+msgstr ""
+
+#: src/modules/mkinitfs/main.py:27
+msgid "Creating initramfs with mkinitfs."
+msgstr ""
+
+#: src/modules/mkinitfs/main.py:49
+msgid "Failed to run mkinitfs on the target"
+msgstr ""
+
+#: src/modules/mkinitfs/main.py:50 src/modules/dracut/main.py:50
+msgid "The exit code was {}"
+msgstr ""
+
+#: src/modules/dracut/main.py:27
+msgid "Creating initramfs with dracut."
+msgstr ""
+
+#: src/modules/dracut/main.py:49
+msgid "Failed to run dracut on the target"
+msgstr ""
+
+#: src/modules/initramfscfg/main.py:32
+msgid "Configuring initramfs."
+msgstr ""
+
+#: src/modules/openrcdmcryptcfg/main.py:26
+msgid "Configuring OpenRC dmcrypt service."
+msgstr ""
+
+#: src/modules/fstab/main.py:29
+msgid "Writing fstab."
+msgstr ""
+
+#: src/modules/fstab/main.py:395
+msgid "No {!s}
configuration is given for {!s}
to use."
+msgstr ""
+
+#: src/modules/dummypython/main.py:35
+msgid "Dummy python job."
+msgstr ""
+
+#: src/modules/dummypython/main.py:37 src/modules/dummypython/main.py:93
+#: src/modules/dummypython/main.py:94
+msgid "Dummy python step {}"
+msgstr ""
+
+#: src/modules/localecfg/main.py:31
+msgid "Configuring locales."
+msgstr ""
+
+#: src/modules/networkcfg/main.py:29
+msgid "Saving network configuration."
+msgstr ""
diff --git a/lang/python/ko/LC_MESSAGES/python.po b/lang/python/ko/LC_MESSAGES/python.po
index d5bb1fa76..e8e751c9c 100644
--- a/lang/python/ko/LC_MESSAGES/python.po
+++ b/lang/python/ko/LC_MESSAGES/python.po
@@ -5,7 +5,7 @@
#
# Translators:
# Ji-Hyeon Gim , 2018
-# Junghee Lee , 2022
+# JungHee Lee , 2022
#
#, fuzzy
msgid ""
@@ -14,7 +14,7 @@ msgstr ""
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-03-21 17:21+0100\n"
"PO-Revision-Date: 2017-08-09 10:34+0000\n"
-"Last-Translator: Junghee Lee , 2022\n"
+"Last-Translator: JungHee Lee , 2022\n"
"Language-Team: Korean (https://www.transifex.com/calamares/teams/20061/ko/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -58,7 +58,7 @@ msgstr "부트로더 설치."
#: src/modules/bootloader/main.py:614
msgid "Failed to install grub, no partitions defined in global storage"
-msgstr "grub을 설치하지 못했습니다. 전역 저장소에 파티션이 정의되어 있지 않습니다"
+msgstr "grub을 설치하지 못했습니다. 파티션 없음이 전역 저장소에 정의되었습니다"
#: src/modules/bootloader/main.py:782
msgid "Bootloader installation error"
diff --git a/src/modules/fstab/main.py b/src/modules/fstab/main.py
old mode 100644
new mode 100755
index 9bc427b13..1cfb5e660
--- a/src/modules/fstab/main.py
+++ b/src/modules/fstab/main.py
@@ -158,11 +158,23 @@ class FstabGenerator(object):
if not mapper_name or not luks_uuid:
return None
+ password = "/crypto_keyfile.bin"
+ crypttab_options = self.crypttab_options
+
+ # Set crypttab password for partition to none and remove crypttab options
+ # on root partition when /boot is unencrypted
+ if partition["mountPoint"] == "/":
+ if any([p["mountPoint"] == "/boot"
+ and "luksMapperName" not in p
+ for p in self.partitions]):
+ password = "none"
+ crypttab_options = ""
+
return dict(
name=mapper_name,
device="UUID=" + luks_uuid,
- password="/crypto_keyfile.bin",
- options=self.crypttab_options,
+ password=password,
+ options=crypttab_options,
)
def print_crypttab_line(self, dct, file=None):
@@ -220,7 +232,7 @@ class FstabGenerator(object):
# Some "fs" names need special handling in /etc/fstab, so remap them.
filesystem = partition["fs"].lower()
filesystem = FS_MAP.get(filesystem, filesystem)
- has_luks = "luksMapperName" in partition
+ luks_mapper_name = partition.get("luksMapperName", None)
mount_point = partition["mountPoint"]
disk_name = disk_name_for_partition(partition)
is_ssd = disk_name in self.ssd_disks
@@ -263,13 +275,19 @@ class FstabGenerator(object):
if filesystem == "btrfs" and partition.get("subvol",None):
options = "subvol={},".format(partition["subvol"]) + options
- if has_luks:
- device = "/dev/mapper/" + partition["luksMapperName"]
+ device = None
+ if luks_mapper_name:
+ device = "/dev/mapper/" + luks_mapper_name
elif partition["uuid"]:
device = "UUID=" + partition["uuid"]
else:
device = partition["device"]
+ if not device:
+ # TODO: we get here when the user mounted a previously encrypted partition
+ # This should be catched early in the process
+ return None
+
return dict(device=device,
mount_point=mount_point,
fs=filesystem,
diff --git a/src/modules/keyboardq/keyboardq.qml b/src/modules/keyboardq/keyboardq.qml
index 1d59cf30e..be96ec85a 100644
--- a/src/modules/keyboardq/keyboardq.qml
+++ b/src/modules/keyboardq/keyboardq.qml
@@ -1,6 +1,6 @@
/* === This file is part of Calamares - ===
*
- * SPDX-FileCopyrightText: 2020 - 2021 Anke Boersma
+ * SPDX-FileCopyrightText: 2020 - 2022 Anke Boersma
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
@@ -137,6 +137,7 @@ Item {
hoverEnabled: true
width: parent.width
+ height: 18
highlighted: ListView.isCurrentItem
RowLayout {
@@ -216,6 +217,7 @@ Item {
delegate: ItemDelegate {
hoverEnabled: true
width: parent.width
+ height: 18
highlighted: ListView.isCurrentItem
RowLayout {
diff --git a/src/modules/locale/images/timezone_5.5.png b/src/modules/locale/images/timezone_5.5.png
index 78c972fab..172ad8127 100644
Binary files a/src/modules/locale/images/timezone_5.5.png and b/src/modules/locale/images/timezone_5.5.png differ
diff --git a/src/modules/locale/images/timezone_8.0.png b/src/modules/locale/images/timezone_8.0.png
index ee5095a26..6db98f18f 100644
Binary files a/src/modules/locale/images/timezone_8.0.png and b/src/modules/locale/images/timezone_8.0.png differ
diff --git a/src/modules/localecfg/main.py b/src/modules/localecfg/main.py
index 8f0edcd17..9cf593017 100644
--- a/src/modules/localecfg/main.py
+++ b/src/modules/localecfg/main.py
@@ -17,6 +17,7 @@ import os
import re
import shutil
+
import libcalamares
import gettext
@@ -71,8 +72,12 @@ def rewrite_locale_gen(srcfilename, destfilename, locale_conf):
# Get entire source-file contents
text = []
- with open(srcfilename, "r") as gen:
- text = gen.readlines()
+ try:
+ with open(srcfilename, "r") as gen:
+ text = gen.readlines()
+ except FileNotFoundError:
+ # That's ok, the file doesn't exist so assume empty
+ pass
# we want unique values, so locale_values should have 1 or 2 items
locale_values = set(locale_conf.values())
diff --git a/src/modules/localeq/Offline.qml b/src/modules/localeq/Offline.qml
index e5e6b31cf..937554cf6 100644
--- a/src/modules/localeq/Offline.qml
+++ b/src/modules/localeq/Offline.qml
@@ -1,6 +1,6 @@
/* === This file is part of Calamares - ===
*
- * SPDX-FileCopyrightText: 2020-2021 Anke Boersma
+ * SPDX-FileCopyrightText: 2020-2022 Anke Boersma
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
@@ -72,6 +72,7 @@ Page {
hoverEnabled: true
width: parent.width
+ height: 30
highlighted: ListView.isCurrentItem
Label {
@@ -146,6 +147,7 @@ Page {
hoverEnabled: true
width: parent.width
+ height: 30
highlighted: ListView.isCurrentItem
Label {
diff --git a/src/modules/luksbootkeyfile/CMakeLists.txt b/src/modules/luksbootkeyfile/CMakeLists.txt
index 6e98af468..dff682521 100644
--- a/src/modules/luksbootkeyfile/CMakeLists.txt
+++ b/src/modules/luksbootkeyfile/CMakeLists.txt
@@ -3,7 +3,7 @@
# SPDX-FileCopyrightText: 2020 Adriaan de Groot
# SPDX-License-Identifier: BSD-2-Clause
#
-calamares_add_plugin( luksbootkeyfile
+calamares_add_plugin(luksbootkeyfile
TYPE job
EXPORT_MACRO PLUGINDLLEXPORT_PRO
SOURCES
@@ -11,3 +11,10 @@ calamares_add_plugin( luksbootkeyfile
SHARED_LIB
NO_CONFIG
)
+
+calamares_add_test(
+ luksbootkeyfiletest
+ SOURCES
+ Tests.cpp
+ LuksBootKeyFileJob.cpp
+)
diff --git a/src/modules/luksbootkeyfile/LuksBootKeyFileJob.cpp b/src/modules/luksbootkeyfile/LuksBootKeyFileJob.cpp
index 137cb750d..e8dfd4724 100644
--- a/src/modules/luksbootkeyfile/LuksBootKeyFileJob.cpp
+++ b/src/modules/luksbootkeyfile/LuksBootKeyFileJob.cpp
@@ -150,26 +150,50 @@ setupLuks( const LuksDevice& d )
}
static QVariantList
-partitions()
+partitionsFromGlobalStorage()
{
Calamares::GlobalStorage* globalStorage = Calamares::JobQueue::instance()->globalStorage();
return globalStorage->value( QStringLiteral( "partitions" ) ).toList();
}
-static bool
+/// Checks if the partition (represented by @p map) mounts to the given @p path
+STATICTEST bool
+hasMountPoint( const QVariantMap& map, const QString& path )
+{
+ const auto v = map.value( QStringLiteral( "mountPoint" ) );
+ return v.isValid() && QDir::cleanPath( v.toString() ) == path;
+}
+
+STATICTEST bool
+isEncrypted( const QVariantMap& map )
+{
+ return map.contains( QStringLiteral( "luksMapperName" ) );
+}
+
+/// Checks for any partition satisfying @p pred
+STATICTEST bool
+anyPartition( bool ( *pred )( const QVariantMap& ) )
+{
+ const auto partitions = partitionsFromGlobalStorage();
+ return std::find_if( partitions.cbegin(),
+ partitions.cend(),
+ [ &pred ]( const QVariant& partitionVariant ) { return pred( partitionVariant.toMap() ); } )
+ != partitions.cend();
+}
+
+STATICTEST bool
hasUnencryptedSeparateBoot()
{
- const QVariantList partitions = ::partitions();
- for ( const QVariant& partition : partitions )
- {
- QVariantMap partitionMap = partition.toMap();
- QString mountPoint = partitionMap.value( QStringLiteral( "mountPoint" ) ).toString();
- if ( QDir::cleanPath( mountPoint ) == QStringLiteral( "/boot" ) )
- {
- return !partitionMap.contains( QStringLiteral( "luksMapperName" ) );
- }
- }
- return false;
+ return anyPartition(
+ []( const QVariantMap& partition )
+ { return hasMountPoint( partition, QStringLiteral( "/boot" ) ) && !isEncrypted( partition ); } );
+}
+
+STATICTEST bool
+hasEncryptedRoot()
+{
+ return anyPartition( []( const QVariantMap& partition )
+ { return hasMountPoint( partition, QStringLiteral( "/" ) ) && isEncrypted( partition ); } );
}
Calamares::JobResult
@@ -218,7 +242,8 @@ LuksBootKeyFileJob::exec()
}
// /boot partition is not encrypted, keyfile must not be used
- if ( hasUnencryptedSeparateBoot() )
+ // But only if root partition is not encrypted
+ if ( hasUnencryptedSeparateBoot() && !hasEncryptedRoot() )
{
cDebug() << Logger::SubEntry << "/boot partition is not encrypted, skipping keyfile creation.";
return Calamares::JobResult::ok();
@@ -241,6 +266,12 @@ LuksBootKeyFileJob::exec()
for ( const auto& d : s.devices )
{
+ // Skip setupLuks for root partition if system has an unencrypted /boot
+ if ( d.isRoot && hasUnencryptedSeparateBoot() )
+ {
+ continue;
+ }
+
if ( !setupLuks( d ) )
return Calamares::JobResult::error(
tr( "Encrypted rootfs setup error" ),
diff --git a/src/modules/luksbootkeyfile/Tests.cpp b/src/modules/luksbootkeyfile/Tests.cpp
new file mode 100644
index 000000000..6b6c7be81
--- /dev/null
+++ b/src/modules/luksbootkeyfile/Tests.cpp
@@ -0,0 +1,169 @@
+/* === This file is part of Calamares - ===
+ *
+ * SPDX-FileCopyrightText: 2022 Adriaan de Groot
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ * Calamares is Free Software: see the License-Identifier above.
+ *
+ */
+
+#include "GlobalStorage.h"
+#include "JobQueue.h"
+#include "utils/Logger.h"
+
+#include
+
+#undef STATICTEST
+#define STATICTEST extern
+
+// Implementation details
+STATICTEST bool hasMountPoint( const QVariantMap& map, const QString& path );
+
+STATICTEST bool isEncrypted( const QVariantMap& map );
+
+STATICTEST bool anyPartition( bool ( *pred )( const QVariantMap& ) );
+
+STATICTEST bool hasUnencryptedSeparateBoot();
+
+STATICTEST bool hasEncryptedRoot();
+
+class LuksBootKeyFileTests : public QObject
+{
+ Q_OBJECT
+public:
+ LuksBootKeyFileTests() {}
+ ~LuksBootKeyFileTests() override {}
+
+private Q_SLOTS:
+ void initTestCase();
+
+ void testMountPoint();
+ void testIsEncrypted();
+ void testAnyPartition();
+};
+
+void
+LuksBootKeyFileTests::initTestCase()
+{
+ Logger::setupLogLevel( Logger::LOGDEBUG );
+ cDebug() << "LuksBootKeyFile test started.";
+
+ if ( !Calamares::JobQueue::instance() )
+ {
+ (void)new Calamares::JobQueue();
+ }
+}
+
+void
+LuksBootKeyFileTests::testMountPoint()
+{
+ QVariantMap m; // As if this is a partition data
+ const QString key = QStringLiteral( "mountPoint" );
+ const QString boot = QStringLiteral( "/boot" );
+ const QString root = QStringLiteral( "/" );
+
+ QVERIFY( !hasMountPoint( m, QString() ) );
+ QVERIFY( !hasMountPoint( m, boot ) );
+
+ m.insert( key, boot );
+ QVERIFY( hasMountPoint( m, boot ) );
+ QVERIFY( !hasMountPoint( m, QString() ) );
+ QVERIFY( !hasMountPoint( m, root ) );
+
+ m.insert( key, root );
+ QVERIFY( !hasMountPoint( m, boot ) );
+ QVERIFY( !hasMountPoint( m, QString() ) );
+ QVERIFY( hasMountPoint( m, root ) );
+
+ m.remove( key );
+ QVERIFY( !hasMountPoint( m, root ) );
+}
+
+void
+LuksBootKeyFileTests::testIsEncrypted()
+{
+ QVariantMap m; // As if this is a partition data
+ const QString key = QStringLiteral( "luksMapperName" );
+ const QString name = QStringLiteral( "any-name" );
+
+ QVERIFY( !isEncrypted( m ) );
+
+ // Even an empty string is considered encrypted
+ m.insert( key, QString() );
+ QVERIFY( isEncrypted( m ) );
+
+ m.insert( key, name );
+ QVERIFY( isEncrypted( m ) );
+
+ m.insert( key, QString() );
+ QVERIFY( isEncrypted( m ) );
+
+ m.remove( key );
+ QVERIFY( !isEncrypted( m ) );
+}
+
+
+void
+LuksBootKeyFileTests::testAnyPartition()
+{
+ // This is kind of annoying: we need to build up
+ // partition data in GS because the functions we're testing
+ // go straight to GS.
+ auto* gs = Calamares::JobQueue::instanceGlobalStorage();
+ QVERIFY( gs );
+
+ const QString partitionsKey = QStringLiteral( "partitions" );
+ const QString mountPointKey = QStringLiteral( "mountPoint" );
+ const QString boot = QStringLiteral( "/boot" );
+ const QString root = QStringLiteral( "/" );
+
+ QVariantList partitions;
+ QVariantMap p;
+ QVERIFY( !gs->contains( partitionsKey ) );
+
+ // Empty list!
+ QVERIFY( !anyPartition( []( const QVariantMap& ) { return true; } ) );
+
+ gs->insert( partitionsKey, partitions );
+ QVERIFY( !anyPartition( []( const QVariantMap& ) { return true; } ) ); // Still an empty list
+
+ partitions.append( p );
+ QCOMPARE( partitions.count(), 1 );
+ gs->insert( partitionsKey, partitions );
+ QVERIFY( anyPartition( []( const QVariantMap& ) { return true; } ) ); // Now a one-element list
+ QVERIFY( !anyPartition( []( const QVariantMap& ) { return false; } ) ); // Now a one-element list
+
+ p.insert( mountPointKey, boot );
+ QVERIFY( hasMountPoint( p, boot ) );
+ partitions.append( p );
+ QCOMPARE( partitions.count(), 2 );
+
+ // Note that GS is not updated yet, so we expect this to fail
+ QEXPECT_FAIL( "", "GS not updated", Continue );
+ QVERIFY( anyPartition(
+ []( const QVariantMap& partdata )
+ {
+ cDebug() << partdata;
+ return hasMountPoint( partdata, QStringLiteral( "/boot" ) );
+ } ) );
+
+ gs->insert( partitionsKey, partitions ); // Update GS
+ QVERIFY( anyPartition(
+ []( const QVariantMap& partdata )
+ {
+ cDebug() << partdata;
+ return hasMountPoint( partdata, QStringLiteral( "/boot" ) );
+ } ) );
+ QVERIFY( !anyPartition( []( const QVariantMap& partdata )
+ { return hasMountPoint( partdata, QStringLiteral( "/" ) ); } ) );
+ QVERIFY( !anyPartition( []( const QVariantMap& partdata ) { return hasMountPoint( partdata, QString() ); } ) );
+
+ QVERIFY( !hasEncryptedRoot() );
+ QVERIFY( hasUnencryptedSeparateBoot() );
+}
+
+QTEST_GUILESS_MAIN( LuksBootKeyFileTests )
+
+#include "utils/moc-warnings.h"
+
+#include "Tests.moc"
diff --git a/src/modules/packagechooser/Config.cpp b/src/modules/packagechooser/Config.cpp
index 491fe5c25..667621597 100644
--- a/src/modules/packagechooser/Config.cpp
+++ b/src/modules/packagechooser/Config.cpp
@@ -237,6 +237,12 @@ Config::setPackageChoice( const QString& packageChoice )
emit packageChoiceChanged( m_packageChoice.value_or( QString() ) );
}
+QString
+Config::prettyName() const
+{
+ return m_stepName ? m_stepName->get() : tr( "Packages" );
+}
+
QString
Config::prettyStatus() const
{
@@ -343,4 +349,14 @@ Config::setConfigurationMap( const QVariantMap& configurationMap )
cWarning() << "Single-selection QML module must use 'Legacy' method.";
}
}
+
+ bool labels_ok = false;
+ auto labels = CalamaresUtils::getSubMap( configurationMap, "labels", labels_ok );
+ if ( labels_ok )
+ {
+ if ( labels.contains( "step" ) )
+ {
+ m_stepName = new CalamaresUtils::Locale::TranslatedString( labels, "step" );
+ }
+ }
}
diff --git a/src/modules/packagechooser/Config.h b/src/modules/packagechooser/Config.h
index b04b1c30b..d1b783a8d 100644
--- a/src/modules/packagechooser/Config.h
+++ b/src/modules/packagechooser/Config.h
@@ -98,6 +98,7 @@ public:
QString packageChoice() const { return m_packageChoice.value_or( QString() ); }
void setPackageChoice( const QString& packageChoice );
+ QString prettyName() const;
QString prettyStatus() const;
signals:
@@ -120,6 +121,7 @@ private:
* Reading the property will return an empty QString.
*/
std::optional< QString > m_packageChoice;
+ CalamaresUtils::Locale::TranslatedString* m_stepName; // As it appears in the sidebar
};
diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp
index 9057004de..c3f2ce6e2 100644
--- a/src/modules/packagechooser/PackageChooserViewStep.cpp
+++ b/src/modules/packagechooser/PackageChooserViewStep.cpp
@@ -29,7 +29,6 @@ PackageChooserViewStep::PackageChooserViewStep( QObject* parent )
: Calamares::ViewStep( parent )
, m_config( new Config( this ) )
, m_widget( nullptr )
- , m_stepName( nullptr )
{
emit nextStatusChanged( false );
}
@@ -41,14 +40,13 @@ PackageChooserViewStep::~PackageChooserViewStep()
{
m_widget->deleteLater();
}
- delete m_stepName;
}
QString
PackageChooserViewStep::prettyName() const
{
- return m_stepName ? m_stepName->get() : tr( "Packages" );
+ return m_config->prettyName();
}
@@ -139,16 +137,6 @@ PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap
m_config->setDefaultId( moduleInstanceKey() );
m_config->setConfigurationMap( configurationMap );
- bool labels_ok = false;
- auto labels = CalamaresUtils::getSubMap( configurationMap, "labels", labels_ok );
- if ( labels_ok )
- {
- if ( labels.contains( "step" ) )
- {
- m_stepName = new CalamaresUtils::Locale::TranslatedString( labels, "step" );
- }
- }
-
if ( m_widget )
{
hookupModel();
diff --git a/src/modules/packagechooser/PackageChooserViewStep.h b/src/modules/packagechooser/PackageChooserViewStep.h
index 7561f2bd7..76b35aed8 100644
--- a/src/modules/packagechooser/PackageChooserViewStep.h
+++ b/src/modules/packagechooser/PackageChooserViewStep.h
@@ -50,7 +50,6 @@ private:
Config* m_config;
PackageChooserPage* m_widget;
- CalamaresUtils::Locale::TranslatedString* m_stepName; // As it appears in the sidebar
};
CALAMARES_PLUGIN_FACTORY_DECLARATION( PackageChooserViewStepFactory )
diff --git a/src/modules/packagechooserq/PackageChooserQmlViewStep.cpp b/src/modules/packagechooserq/PackageChooserQmlViewStep.cpp
index 543c9771d..ae4aa3c48 100644
--- a/src/modules/packagechooserq/PackageChooserQmlViewStep.cpp
+++ b/src/modules/packagechooserq/PackageChooserQmlViewStep.cpp
@@ -29,7 +29,7 @@ PackageChooserQmlViewStep::PackageChooserQmlViewStep( QObject* parent )
QString
PackageChooserQmlViewStep::prettyName() const
{
- return tr( "Packages" );
+ return m_config->prettyName();
}
QString
diff --git a/src/modules/packagechooserq/packagechooserq.conf b/src/modules/packagechooserq/packagechooserq.conf
index 803c6f670..9c1878f34 100644
--- a/src/modules/packagechooserq/packagechooserq.conf
+++ b/src/modules/packagechooserq/packagechooserq.conf
@@ -42,6 +42,19 @@
#
method: legacy
+# Human-visible strings in this module. These are all optional.
+# The following translated keys are used:
+# - *step*, used in the overall progress view (left-hand pane)
+#
+# Each key can have a [locale] added to it, which is used as
+# the translated string for that locale. For the strings
+# associated with the "no-selection" item, see *items*, below
+# with the explicit item-*id* "".
+#
+labels:
+ step: "Packages"
+ step[nl]: "Pakketten"
+
# The *packageChoice* value is used for setting the default selection
# in the QML view; this should match one of the keys used in the QML
# module for package names.
diff --git a/src/modules/partition/jobs/FormatPartitionJob.cpp b/src/modules/partition/jobs/FormatPartitionJob.cpp
index 63d233426..599e29769 100644
--- a/src/modules/partition/jobs/FormatPartitionJob.cpp
+++ b/src/modules/partition/jobs/FormatPartitionJob.cpp
@@ -58,10 +58,13 @@ FormatPartitionJob::prettyDescription() const
QString
FormatPartitionJob::prettyStatusMessage() const
{
+ QString partitionLabel = m_partition->label().isEmpty()
+ ? m_partition->partitionPath()
+ : tr( "%1 (%2)", "partition label %1 (device path %2)" )
+ .arg( m_partition->label(), m_partition->partitionPath() );
return tr( "Formatting partition %1 with "
"file system %2." )
- .arg( m_partition->partitionPath() )
- .arg( userVisibleFS( m_partition->fileSystem() ) );
+ .arg( partitionLabel, userVisibleFS( m_partition->fileSystem() ) );
}
diff --git a/src/modules/usersq/usersq.qml b/src/modules/usersq/usersq.qml
index 9d49e6a7d..febdb5be5 100644
--- a/src/modules/usersq/usersq.qml
+++ b/src/modules/usersq/usersq.qml
@@ -1,6 +1,6 @@
/* === This file is part of Calamares - ===
*
- * SPDX-FileCopyrightText: 2020 - 2021 Anke Boersma
+ * SPDX-FileCopyrightText: 2020 - 2022 Anke Boersma
* SPDX-FileCopyrightText: 2021 Adriaan de Groot
* SPDX-License-Identifier: GPL-3.0-or-later
*
@@ -123,6 +123,7 @@ Kirigami.ScrollablePage {
Kirigami.InlineMessage {
id: userMessage
Layout.fillWidth: true
+ showCloseButton: true
visible: false
type: Kirigami.MessageType.Error
text: qsTr("Only lowercase letters, numbers, underscore and hyphen are allowed.")
@@ -131,6 +132,7 @@ Kirigami.ScrollablePage {
Kirigami.InlineMessage {
id: forbiddenMessage
Layout.fillWidth: true
+ showCloseButton: true
visible: false
type: Kirigami.MessageType.Error
text: qsTr("root is not allowed as username.")
@@ -185,6 +187,7 @@ Kirigami.ScrollablePage {
Kirigami.InlineMessage {
id: hostMessage
Layout.fillWidth: true
+ showCloseButton: true
visible: false
type: Kirigami.MessageType.Error
text: qsTr("Only letters, numbers, underscore and hyphen are allowed, minimal of two characters.")
@@ -193,6 +196,7 @@ Kirigami.ScrollablePage {
Kirigami.InlineMessage {
id: forbiddenHost
Layout.fillWidth: true
+ showCloseButton: true
visible: false
type: Kirigami.MessageType.Error
text: qsTr("localhost is not allowed as hostname.")