Merge branch 'issue-1635' into calamares

FIXES #1635
This commit is contained in:
Adriaan de Groot 2021-03-23 12:10:49 +01:00
commit 7e8ef85dc9
6 changed files with 280 additions and 66 deletions

View File

@ -63,6 +63,7 @@ set( libSources
packages/Globals.cpp
# Partition service
partition/Global.cpp
partition/Mount.cpp
partition/PartitionSize.cpp
partition/Sync.cpp
@ -241,7 +242,10 @@ calamares_add_test(
calamares_add_test(
libcalamarespartitiontest
SOURCES
partition/Global.cpp
partition/Tests.cpp
LIBRARIES
${OPTIONAL_PRIVATE_LIBRARIES}
)
if( KPMcore_FOUND )

View File

@ -0,0 +1,56 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2021 Adriaan de Groot <groot@kde.org>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
*
*
*/
#include "Global.h"
#include "FileSystem.h"
#include "GlobalStorage.h"
#include "JobQueue.h"
#include <QVariantMap>
static const QString fsUse_key = QStringLiteral( "filesystem_use" );
bool
CalamaresUtils::Partition::isFilesystemUsedGS( const Calamares::GlobalStorage* gs, const QString& filesystemType )
{
if ( !gs )
{
return false;
}
const QVariantMap fsUse = gs->value( fsUse_key ).toMap();
QString key = filesystemType.toLower();
if ( fsUse.contains( key ) )
{
const auto v = fsUse.value( key );
return v.toBool();
}
return false;
}
void
CalamaresUtils::Partition::useFilesystemGS( Calamares::GlobalStorage* gs, const QString& filesystemType, bool used )
{
if ( gs )
{
QVariantMap existingMap = gs->contains( fsUse_key ) ? gs->value( fsUse_key ).toMap() : QVariantMap();
QString key = filesystemType.toLower();
existingMap.insert( key, used );
gs->insert( fsUse_key, existingMap );
}
}
void
CalamaresUtils::Partition::clearFilesystemGS( Calamares::GlobalStorage* gs )
{
if ( gs )
{
gs->remove( fsUse_key );
}
}

View File

@ -0,0 +1,107 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2021 Adriaan de Groot <groot@kde.org>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
*
*
*/
/*
* This is the API for manipulating Global Storage keys related to
* filesystems and partitions.
*/
#ifndef PARTITION_GLOBAL_H
#define PARTITION_GLOBAL_H
#include "DllMacro.h"
#include "JobQueue.h"
#ifdef WITH_KPMCORE4API
#include "FileSystem.h"
#include <kpmcore/fs/filesystem.h>
#endif
namespace CalamaresUtils
{
namespace Partition
{
/** @brief Mark a particular filesystem type as used (or not)
*
* Filesystems are marked used (or not) in the global storage
* key *filesystem_use*. Sub-keys are the filesystem name,
* and the values are boolean; filesystems that are used in
* the target system are marked with @c true. Unused filesystems
* may be unmarked, or may be marked @c false.
*
* The filesystem name should be the untranslated name. Filesystem
* names are **lower**cased when used as keys.
*/
void DLLEXPORT useFilesystemGS( Calamares::GlobalStorage* gs, const QString& filesystemType, bool used );
/** @brief Reads from global storage whether the filesystem type is used
*
* Reads from the global storage key *filesystem_use* and returns
* the boolean value stored in subkey @p filesystemType. Returns
* @c false if the subkey is not set at all.
*
* The filesystem name should be the untranslated name. Filesystem
* names are **lower**cased when used as keys.
*/
bool DLLEXPORT isFilesystemUsedGS( const Calamares::GlobalStorage* gs, const QString& filesystemType );
/** @brief Clears the usage data for filesystems
*
* This removes the internal key *filesystem_use*.
*/
void DLLEXPORT clearFilesystemGS( Calamares::GlobalStorage* gs );
/** @brief Convenience function for using "the" Global Storage
*
* @see useFilesystemGS(const QString&, bool)
*/
inline void
useFilesystemGS( const QString& filesystemType, bool used )
{
useFilesystemGS( Calamares::JobQueue::instanceGlobalStorage(), filesystemType, used );
}
/** @brief Convenience function for using "the" Global Storage
*
* @see isFilesystemUsedGS(const QString&);
*/
inline bool
isFilesystemUsedGS( const QString& filesystemType )
{
return isFilesystemUsedGS( Calamares::JobQueue::instanceGlobalStorage(), filesystemType );
}
#ifdef WITH_KPMCORE4API
/** @brief Mark a particular filesystem type as used (or not)
*
* See useFilesystemGS(const QString&, bool); this method uses the filesystem type
* enumeration to pick the name.
*/
inline void
useFilesystemGS( FileSystem::Type filesystem, bool used )
{
useFilesystemGS( untranslatedFS( filesystem ), used );
}
/* @brief Reads from global storage whether the typesystem type is used
*
* See isFilesystemUsedGS(const QString&).
*/
inline bool
isFilesystemUsedGS( FileSystem::Type filesystem )
{
return isFilesystemUsedGS( untranslatedFS( filesystem ) );
}
#endif
} // namespace Partition
} // namespace CalamaresUtils
#endif

View File

@ -8,32 +8,50 @@
*
*/
#include "Tests.h"
#include "Global.h"
#include "PartitionSize.h"
#include "GlobalStorage.h"
#include "utils/Logger.h"
#include <QObject>
#include <QtTest/QtTest>
using SizeUnit = CalamaresUtils::Partition::SizeUnit;
using PartitionSize = CalamaresUtils::Partition::PartitionSize;
Q_DECLARE_METATYPE( SizeUnit )
#include "utils/Logger.h"
class PartitionServiceTests : public QObject
{
Q_OBJECT
public:
PartitionServiceTests();
~PartitionServiceTests() override;
#include <QtTest/QtTest>
private Q_SLOTS:
void initTestCase();
QTEST_GUILESS_MAIN( PartitionSizeTests )
void testUnitComparison_data();
void testUnitComparison();
PartitionSizeTests::PartitionSizeTests() {}
void testUnitNormalisation_data();
void testUnitNormalisation();
PartitionSizeTests::~PartitionSizeTests() {}
void testFilesystemGS();
};
PartitionServiceTests::PartitionServiceTests() {}
PartitionServiceTests::~PartitionServiceTests() {}
void
PartitionSizeTests::initTestCase()
PartitionServiceTests::initTestCase()
{
}
void
PartitionSizeTests::testUnitComparison_data()
PartitionServiceTests::testUnitComparison_data()
{
QTest::addColumn< SizeUnit >( "u1" );
QTest::addColumn< SizeUnit >( "u2" );
@ -71,7 +89,7 @@ original_compare( SizeUnit m_unit, SizeUnit other_m_unit )
}
void
PartitionSizeTests::testUnitComparison()
PartitionServiceTests::testUnitComparison()
{
QFETCH( SizeUnit, u1 );
QFETCH( SizeUnit, u2 );
@ -98,7 +116,7 @@ constexpr qint64 operator""_qi( unsigned long long m )
}
void
PartitionSizeTests::testUnitNormalisation_data()
PartitionServiceTests::testUnitNormalisation_data()
{
QTest::addColumn< SizeUnit >( "u1" );
QTest::addColumn< int >( "v" );
@ -131,7 +149,7 @@ PartitionSizeTests::testUnitNormalisation_data()
}
void
PartitionSizeTests::testUnitNormalisation()
PartitionServiceTests::testUnitNormalisation()
{
QFETCH( SizeUnit, u1 );
QFETCH( int, v );
@ -139,3 +157,70 @@ PartitionSizeTests::testUnitNormalisation()
QCOMPARE( PartitionSize( v, u1 ).toBytes(), bytes );
}
void
PartitionServiceTests::testFilesystemGS()
{
using CalamaresUtils::Partition::isFilesystemUsedGS;
using CalamaresUtils::Partition::useFilesystemGS;
// Some filesystems names, they don't have to be real
const QStringList fsNames { "ext4", "zfs", "berries", "carrot" };
// Predicate to return whether we consider this FS in use
auto pred = []( const QString& s ) { return !s.startsWith( 'z' ); };
// Fill the GS
Calamares::GlobalStorage gs;
for ( const auto& s : fsNames )
{
useFilesystemGS( &gs, s, pred( s ) );
}
QVERIFY( gs.contains( "filesystem_use" ) );
{
const auto map = gs.value( "filesystem_use" ).toMap();
QCOMPARE( map.count(), fsNames.count() );
}
for ( const auto& s : fsNames )
{
QCOMPARE( isFilesystemUsedGS( &gs, s ), pred( s ) );
}
QCOMPARE( isFilesystemUsedGS( &gs, QStringLiteral( "derp" ) ), false );
QCOMPARE( isFilesystemUsedGS( &gs, QString() ), false );
// But I can set a value for QString!
useFilesystemGS( &gs, QString(), true );
QCOMPARE( isFilesystemUsedGS( &gs, QString() ), true );
// .. and replace it again
useFilesystemGS( &gs, QString(), false );
QCOMPARE( isFilesystemUsedGS( &gs, QString() ), false );
// Now there is one more key
{
const auto map = gs.value( "filesystem_use" ).toMap();
QCOMPARE( map.count(), fsNames.count() + 1 );
}
// The API says that it it case-insensitive
QVERIFY( !isFilesystemUsedGS( &gs, "ZFS" ) );
QVERIFY( isFilesystemUsedGS( &gs, "EXT4" ) );
QCOMPARE( isFilesystemUsedGS( &gs, "ZFS" ), isFilesystemUsedGS( &gs, "zfs" ) );
QCOMPARE( isFilesystemUsedGS( &gs, "EXT4" ), isFilesystemUsedGS( &gs, "ext4" ) );
useFilesystemGS( &gs, "EXT4", false );
QVERIFY( !isFilesystemUsedGS( &gs, "EXT4" ) );
QCOMPARE( isFilesystemUsedGS( &gs, "EXT4" ), isFilesystemUsedGS( &gs, "ext4" ) );
useFilesystemGS( &gs, "ext4", true );
QVERIFY( isFilesystemUsedGS( &gs, "EXT4" ) );
CalamaresUtils::Partition::clearFilesystemGS( &gs );
QVERIFY( !isFilesystemUsedGS( &gs, "ZFS" ) );
QVERIFY( !isFilesystemUsedGS( &gs, "EXT4" ) );
QVERIFY( !isFilesystemUsedGS( &gs, "ext4" ) );
}
QTEST_GUILESS_MAIN( PartitionServiceTests )
#include "utils/moc-warnings.h"
#include "Tests.moc"

View File

@ -1,33 +0,0 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2019 Adriaan de Groot <groot@kde.org>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
*
*
*/
#ifndef LIBCALAMARES_PARTITION_TESTS_H
#define LIBCALAMARES_PARTITION_TESTS_H
#include <QObject>
class PartitionSizeTests : public QObject
{
Q_OBJECT
public:
PartitionSizeTests();
~PartitionSizeTests() override;
private Q_SLOTS:
void initTestCase();
void testUnitComparison_data();
void testUnitComparison();
void testUnitNormalisation_data();
void testUnitNormalisation();
};
#endif

View File

@ -18,6 +18,7 @@
#include "GlobalStorage.h"
#include "JobQueue.h"
#include "partition/FileSystem.h"
#include "partition/Global.h"
#include "partition/PartitionIterator.h"
#include "utils/Logger.h"
@ -291,35 +292,29 @@ FillGlobalStorageJob::prettyStatusMessage() const
* .. mark as "1" if it's on the system, somewhere
* .. mark as "2" if it's one of the claimed / in-use FSses
*
* Stores a GS key called "filesystems_use" with this mapping.
* Stores a GS key called "filesystem_use" with this mapping.
* @see CalamaresUtils::Partition::useFilesystemGS()
*/
static void
storeFSUse( Calamares::GlobalStorage* storage, const QVariantList& partitions )
{
QMap< QString, int > fsUses;
if ( storage )
{
CalamaresUtils::Partition::clearFilesystemGS( storage );
for ( const auto& p : partitions )
{
const auto pmap = p.toMap();
QString fs = pmap.value( "fs" ).toString();
int thisUse = pmap.value( "claimed" ).toBool() ? 2 : 1;
if ( fs.isEmpty() )
{
continue;
}
int newUse = qMax( fsUses.value( fs ), thisUse ); // value() is 0 if not present
fsUses.insert( fs, newUse );
CalamaresUtils::Partition::useFilesystemGS( storage, fs, true );
}
QVariantMap fsUsesVariant;
for ( auto it = fsUses.cbegin(); it != fsUses.cend(); ++it )
{
fsUsesVariant.insert( it.key(), it.value() );
}
storage->insert( "filesystems_use", fsUsesVariant );
}
Calamares::JobResult