diff --git a/CHANGES b/CHANGES index 88d8c7350..0f8963ae1 100644 --- a/CHANGES +++ b/CHANGES @@ -3,7 +3,7 @@ contributors are listed. Note that Calamares does not have a historical changelog -- this log starts with version 3.2.0. The release notes on the website will have to do for older versions. -# 3.2.3 (unreleased) # +# 3.2.4 (unreleased) # This release contains contributions from (alphabetically by first name): - Alf Gaida @@ -45,6 +45,30 @@ This release contains contributions from (alphabetically by first name): for all operations, not just during install (keep in mind that these run as three separate shells, though). + +# 3.2.3 (2019-01-09) # + +This release contains contributions from (alphabetically by first name): + - aliveafter1000 + +## Core ## + +There are no core changes in this release. + +## Modules ## + + * *partition* Fixed bug where, during detection of existing systems, the + existing system partitions may be mounted and then files deleted. + This is a **limited** version of the patch from aliveafter1000 + that will be in 3.2.4, which tries harder to mount filesystems + read-only and unmodifiable. + * *locale* It was possible to set the installer and system language + (e.g. to German) while the global storage value for *locale* + remained set to English. Then no localization packages are installed + (see feature `${LOCALE}` in `packages.conf`). Reported downstream + in Netrunner. + + # 3.2.2 (2018-09-04) # This release contains contributions from (alphabetically by first name): diff --git a/CMakeLists.txt b/CMakeLists.txt index e3cffc383..ec3439976 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -75,7 +75,7 @@ set( CALAMARES_DESCRIPTION_SUMMARY set( CALAMARES_VERSION_MAJOR 3 ) set( CALAMARES_VERSION_MINOR 2 ) -set( CALAMARES_VERSION_PATCH 3 ) +set( CALAMARES_VERSION_PATCH 4 ) set( CALAMARES_VERSION_RC 1 ) @@ -152,7 +152,7 @@ set( CMAKE_C_STANDARD_REQUIRED ON ) # location database. # - DEBUG_FILESYSTEMS does extra logging and checking when looking at # partition configuration. Lists known KPMCore FS types. -# +# # The flags listed here are enabled in Debug builds. By default, none # are **actually** listed, because they're for such specific scenarios. set( _enable_debug_flags diff --git a/src/libcalamares/PythonJobApi.cpp b/src/libcalamares/PythonJobApi.cpp index f540c2683..b953f821a 100644 --- a/src/libcalamares/PythonJobApi.cpp +++ b/src/libcalamares/PythonJobApi.cpp @@ -1,7 +1,7 @@ /* === This file is part of Calamares - === * * Copyright 2014-2016, Teo Mrnjavac - * Copyright 2017-2018, Adriaan de Groot + * Copyright 2017-2019, Adriaan de Groot * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -275,16 +275,21 @@ gettext_path() } _add_localedirs( candidatePaths, QDir().canonicalPath() ); // . - cDebug() << "Standard paths" << candidatePaths; + cDebug() << "Determining gettext path from" << candidatePaths; - for ( auto lang : _gettext_languages() ) + QStringList candidateLanguages = _gettext_languages(); + + for ( const auto& lang : candidateLanguages ) for ( auto localedir : candidatePaths ) { QDir ldir( localedir ); - cDebug() << "Checking" << lang << "in" < === * * Copyright 2016, Teo Mrnjavac - * Copyright 2017-2018, Adriaan de Groot + * Copyright 2017-2019, Adriaan de Groot * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,14 +27,23 @@ LocaleConfiguration::LocaleConfiguration() } -LocaleConfiguration -LocaleConfiguration::createDefault() +LocaleConfiguration::LocaleConfiguration( const QString& localeName, const QString& formatsName ) + : LocaleConfiguration() { - LocaleConfiguration lc = LocaleConfiguration(); - lc.lang = lc.lc_numeric = lc.lc_time = lc.lc_monetary = lc.lc_paper = lc.lc_name - = lc.lc_address = lc.lc_telephone = lc.lc_measurement - = lc.lc_identification = "en_US.UTF-8"; - return lc; + lc_numeric = lc_time = lc_monetary = lc_paper = lc_name + = lc_address = lc_telephone = lc_measurement + = lc_identification = formatsName; + + (void) setLanguage( localeName ); +} + + +void +LocaleConfiguration::setLanguage(const QString& localeName ) +{ + QString language = localeName.split( '_' ).first(); + m_languageLocaleBcp47 = QLocale( language ).bcp47Name().toLower(); + m_lang = localeName; } @@ -43,11 +52,7 @@ LocaleConfiguration::fromLanguageAndLocation( const QString& languageLocale, const QStringList& availableLocales, const QString& countryCode ) { - LocaleConfiguration lc; - - // Note that the documentation how this works is in packages.conf QString language = languageLocale.split( '_' ).first(); - lc.myLanguageLocaleBcp47 = QLocale(language).bcp47Name().toLower(); QStringList linesForLanguage; for ( const QString &line : availableLocales ) @@ -264,19 +269,14 @@ LocaleConfiguration::fromLanguageAndLocation( const QString& languageLocale, if ( lc_formats.isEmpty() ) lc_formats = lang; - lc.lang = lang; - lc.lc_address = lc.lc_identification = lc.lc_measurement = lc.lc_monetary - = lc.lc_name = lc.lc_numeric = lc.lc_paper = lc.lc_telephone - = lc.lc_time = lc_formats; - - return lc; + return LocaleConfiguration( lang, lc_formats ); } bool LocaleConfiguration::isEmpty() const { - return lang.isEmpty() && + return m_lang.isEmpty() && lc_numeric.isEmpty() && lc_time.isEmpty() && lc_monetary.isEmpty() && @@ -294,8 +294,8 @@ LocaleConfiguration::toMap() const { QMap< QString, QString > map; - if ( !lang.isEmpty() ) - map.insert( "LANG", lang ); + if ( !m_lang.isEmpty() ) + map.insert( "LANG", m_lang ); if ( !lc_numeric.isEmpty() ) map.insert( "LC_NUMERIC", lc_numeric ); @@ -327,8 +327,3 @@ LocaleConfiguration::toMap() const return map; } -QString -LocaleConfiguration::toBcp47() const -{ - return myLanguageLocaleBcp47; -} diff --git a/src/modules/locale/LocaleConfiguration.h b/src/modules/locale/LocaleConfiguration.h index c077ef6f7..abe90ffcb 100644 --- a/src/modules/locale/LocaleConfiguration.h +++ b/src/modules/locale/LocaleConfiguration.h @@ -1,7 +1,7 @@ /* === This file is part of Calamares - === * * Copyright 2016, Teo Mrnjavac - * Copyright 2017-2018, Adriaan de Groot + * Copyright 2017-2019, Adriaan de Groot * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,28 +20,42 @@ #ifndef LOCALECONFIGURATION_H #define LOCALECONFIGURATION_H +#include #include #include class LocaleConfiguration { public: + /// @brief Create an empty locale, with nothing set explicit LocaleConfiguration(); + /// @brief Create a locale with everything set to the given @p localeName + explicit LocaleConfiguration( const QString& localeName /* "en_US.UTF-8" */ ) + : LocaleConfiguration( localeName, localeName ) { }; + /// @brief Create a locale with language and formats separate + explicit LocaleConfiguration( const QString& localeName, const QString& formatsName ); - static LocaleConfiguration createDefault(); static LocaleConfiguration fromLanguageAndLocation( const QString& language, const QStringList& availableLocales, const QString& countryCode ); bool isEmpty() const; - QMap< QString, QString > toMap() const; + /** @brief sets lang and the BCP47 representation + * + * Note that the documentation how this works is in packages.conf + */ + void setLanguage( const QString& localeName ); + QString language() const { return m_lang; } + // Note that the documentation how this works is in packages.conf - QString toBcp47() const; + QString toBcp47() const { return m_languageLocaleBcp47; } + + QMap< QString, QString > toMap() const; // These become all uppercase in locale.conf, but we keep them lowercase here to // avoid confusion with locale.h. - QString lang, lc_numeric, lc_time, lc_monetary, lc_paper, lc_name, lc_address, + QString lc_numeric, lc_time, lc_monetary, lc_paper, lc_name, lc_address, lc_telephone, lc_measurement, lc_identification; // If the user has explicitly selected language (from the dialog) @@ -49,7 +63,13 @@ public: bool explicit_lang, explicit_lc; private: - QString myLanguageLocaleBcp47; + QString m_lang; + QString m_languageLocaleBcp47; }; +inline QDebug& operator <<( QDebug& s, const LocaleConfiguration& l ) +{ + return s << l.language() << '(' << l.toBcp47() << ") +" << l.lc_numeric; +} + #endif // LOCALECONFIGURATION_H diff --git a/src/modules/locale/LocalePage.cpp b/src/modules/locale/LocalePage.cpp index ea77d6b9f..1ddb2cc0a 100644 --- a/src/modules/locale/LocalePage.cpp +++ b/src/modules/locale/LocalePage.cpp @@ -1,7 +1,7 @@ /* === This file is part of Calamares - === * * Copyright 2014-2016, Teo Mrnjavac - * Copyright 2017-2018, Adriaan de Groot + * Copyright 2017-2019, Adriaan de Groot * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -164,16 +164,17 @@ LocalePage::LocalePage( QWidget* parent ) { LCLocaleDialog* dlg = new LCLocaleDialog( m_selectedLocaleConfiguration.isEmpty() ? - guessLocaleConfiguration().lang : - m_selectedLocaleConfiguration.lang, + guessLocaleConfiguration().language() : + m_selectedLocaleConfiguration.language(), m_localeGenLines, this ); dlg->exec(); if ( dlg->result() == QDialog::Accepted && !dlg->selectedLCLocale().isEmpty() ) { - m_selectedLocaleConfiguration.lang = dlg->selectedLCLocale(); + m_selectedLocaleConfiguration.setLanguage( dlg->selectedLCLocale() ); m_selectedLocaleConfiguration.explicit_lang = true; + this->updateGlobalLocale(); this->updateLocaleLabels(); } @@ -317,7 +318,7 @@ LocalePage::init( const QString& initialRegion, } else { - cDebug() << "Cannot open file" << localeGenPath + cWarning() << "Cannot open file" << localeGenPath << ". Assuming the supported languages are already built into " "the locale archive."; QProcess localeA; @@ -386,7 +387,7 @@ std::pair< QString, QString > LocalePage::prettyLocaleStatus( const LocaleConfig { using CalamaresUtils::LocaleLabel; - LocaleLabel lang( lc.lang, LocaleLabel::LabelFormat::AlwaysWithCountry ); + LocaleLabel lang( lc.language(), LocaleLabel::LabelFormat::AlwaysWithCountry ); LocaleLabel num( lc.lc_numeric, LocaleLabel::LabelFormat::AlwaysWithCountry ); return std::make_pair< QString, QString >( @@ -443,7 +444,8 @@ LocalePage::onActivate() !m_selectedLocaleConfiguration.explicit_lang ) { auto newLocale = guessLocaleConfiguration(); - m_selectedLocaleConfiguration.lang = newLocale.lang; + m_selectedLocaleConfiguration.setLanguage( newLocale.language() ); + updateGlobalLocale(); updateLocaleLabels(); } } @@ -452,41 +454,39 @@ LocalePage::onActivate() LocaleConfiguration LocalePage::guessLocaleConfiguration() const { - QLocale myLocale; // User-selected language - - // If we cannot say anything about available locales - if ( m_localeGenLines.isEmpty() ) - { - cWarning() << "guessLocaleConfiguration can't guess from an empty list."; - return LocaleConfiguration::createDefault(); - } - - QString myLanguageLocale = myLocale.name(); - if ( myLanguageLocale.isEmpty() ) - return LocaleConfiguration::createDefault(); - - return LocaleConfiguration::fromLanguageAndLocation( myLanguageLocale, + return LocaleConfiguration::fromLanguageAndLocation( QLocale().name(), m_localeGenLines, m_tzWidget->getCurrentLocation().country ); } +void +LocalePage::updateGlobalLocale() +{ + auto *gs = Calamares::JobQueue::instance()->globalStorage(); + const QString bcp47 = m_selectedLocaleConfiguration.toBcp47(); + gs->insert( "locale", bcp47 ); +} + + void LocalePage::updateGlobalStorage() { - LocaleGlobal::Location location = m_tzWidget->getCurrentLocation(); - Calamares::JobQueue::instance()->globalStorage() - ->insert( "locationRegion", location.region ); - Calamares::JobQueue::instance()->globalStorage() - ->insert( "locationZone", location.zone ); + auto *gs = Calamares::JobQueue::instance()->globalStorage(); - const QString bcp47 = m_selectedLocaleConfiguration.toBcp47(); - Calamares::JobQueue::instance()->globalStorage()->insert( "locale", bcp47 ); + LocaleGlobal::Location location = m_tzWidget->getCurrentLocation(); + bool locationChanged = ( location.region != gs->value( "locationRegion" ) ) || + ( location.zone != gs->value( "locationZone" ) ); + + gs->insert( "locationRegion", location.region ); + gs->insert( "locationZone", location.zone ); + + updateGlobalLocale(); // If we're in chroot mode (normal install mode), then we immediately set the // timezone on the live system. When debugging timezones, don't bother. #ifndef DEBUG_TIMEZONES - if ( Calamares::Settings::instance()->doChroot() ) + if ( locationChanged && Calamares::Settings::instance()->doChroot() ) { QProcess::execute( "timedatectl", // depends on systemd { "set-timezone", @@ -498,7 +498,7 @@ LocalePage::updateGlobalStorage() auto newLocale = guessLocaleConfiguration(); if ( !m_selectedLocaleConfiguration.isEmpty() && m_selectedLocaleConfiguration.explicit_lang ) - newLocale.lang = m_selectedLocaleConfiguration.lang; + newLocale.setLanguage( m_selectedLocaleConfiguration.language() ); if ( !m_selectedLocaleConfiguration.isEmpty() && m_selectedLocaleConfiguration.explicit_lc ) { diff --git a/src/modules/locale/LocalePage.h b/src/modules/locale/LocalePage.h index fae16cfb9..2a9dc8b60 100644 --- a/src/modules/locale/LocalePage.h +++ b/src/modules/locale/LocalePage.h @@ -1,6 +1,7 @@ /* === This file is part of Calamares - === * * Copyright 2014, Teo Mrnjavac + * Copyright 2019, Adriaan de Groot * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -56,6 +57,12 @@ private: // the settings for language and numbers. std::pair< QString, QString > prettyLocaleStatus( const LocaleConfiguration& ) const; + /** @brief Update the GS *locale* key with the selected system language. + * + * This uses whatever is set in m_selectedLocaleConfiguration as the language, + * and writes it to GS *locale* key (as a string, in BCP47 format). + */ + void updateGlobalLocale(); void updateGlobalStorage(); void updateLocaleLabels(); diff --git a/src/modules/locale/Tests.cpp b/src/modules/locale/Tests.cpp new file mode 100644 index 000000000..0e1a3eb48 --- /dev/null +++ b/src/modules/locale/Tests.cpp @@ -0,0 +1,80 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, Adriaan de Groot + * + * Calamares is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Calamares 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Calamares. If not, see . + */ + + +#include "Tests.h" +#include "LocaleConfiguration.h" + +#include + +QTEST_GUILESS_MAIN( LocaleTests ) + + +LocaleTests::LocaleTests() +{ +} + +LocaleTests::~LocaleTests() +{ +} + +void LocaleTests::initTestCase() +{ +} + +void LocaleTests::testEmptyLocaleConfiguration() +{ + LocaleConfiguration lc; + + QVERIFY( lc.isEmpty() ); + QCOMPARE( lc.toBcp47(), QString() ); +} + +void LocaleTests::testDefaultLocaleConfiguration() +{ + LocaleConfiguration lc( "en_US.UTF-8" ); + QVERIFY( !lc.isEmpty() ); + QCOMPARE( lc.language(), "en_US.UTF-8" ); + QCOMPARE( lc.toBcp47(), "en" ); + + LocaleConfiguration lc2( "de_DE.UTF-8" ); + QVERIFY( !lc2.isEmpty() ); + QCOMPARE( lc2.language(), "de_DE.UTF-8" ); + QCOMPARE( lc2.toBcp47(), "de" ); +} + +void LocaleTests::testSplitLocaleConfiguration() +{ + LocaleConfiguration lc( "en_US.UTF-8", "de_DE.UTF-8" ); + QVERIFY( !lc.isEmpty() ); + QCOMPARE( lc.language(), "en_US.UTF-8" ); + QCOMPARE( lc.toBcp47(), "en" ); + QCOMPARE( lc.lc_numeric, QStringLiteral( "de_DE.UTF-8" ) ); + + LocaleConfiguration lc2( "de_DE.UTF-8", "da_DK.UTF-8" ); + QVERIFY( !lc2.isEmpty() ); + QCOMPARE( lc2.language(), "de_DE.UTF-8" ); + QCOMPARE( lc2.toBcp47(), "de" ); + QCOMPARE( lc2.lc_numeric, "da_DK.UTF-8" ); + + LocaleConfiguration lc3( "da_DK.UTF-8", "de_DE.UTF-8" ); + QVERIFY( !lc3.isEmpty() ); + QCOMPARE( lc3.toBcp47(), "da" ); + QCOMPARE( lc3.lc_numeric, "de_DE.UTF-8" ); + +} diff --git a/src/modules/locale/Tests.h b/src/modules/locale/Tests.h new file mode 100644 index 000000000..299eac61d --- /dev/null +++ b/src/modules/locale/Tests.h @@ -0,0 +1,40 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, Adriaan de Groot + * + * Calamares is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Calamares 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Calamares. If not, see . + */ + + +#ifndef TESTS_H +#define TESTS_H + +#include + +class LocaleTests : public QObject +{ + Q_OBJECT +public: + LocaleTests(); + ~LocaleTests() override; + +private Q_SLOTS: + void initTestCase(); + // Check the sample config file is processed correctly + void testEmptyLocaleConfiguration(); + void testDefaultLocaleConfiguration(); + void testSplitLocaleConfiguration(); +}; + +#endif diff --git a/src/modules/locale/timezonewidget/localeglobal.h b/src/modules/locale/timezonewidget/localeglobal.h index 5452b0b09..1a8f796d4 100644 --- a/src/modules/locale/timezonewidget/localeglobal.h +++ b/src/modules/locale/timezonewidget/localeglobal.h @@ -1,6 +1,7 @@ /* === This file is part of Calamares - === * * Copyright 2014-2016, Teo Mrnjavac + * Copyright 2019, Adriaan de Groot * * Originally from the Manjaro Installation Framework * by Roland Singer @@ -38,11 +39,13 @@ class LocaleGlobal { public: - struct Locale { + struct Locale + { QString description, locale; }; - struct Location { + struct Location + { QString region, zone, country; double latitude, longitude; static QString pretty( const QString& s ); @@ -59,7 +62,12 @@ private: static void initLocales(); static void initLocations(); - static double getRightGeoLocation(QString str); + static double getRightGeoLocation( QString str ); }; +inline QDebug& operator <<( QDebug& s, const LocaleGlobal::Location& l ) +{ + return s << l.region << '/' << l.zone << '(' << l.country << ") @N" << l.latitude << 'E' << l.longitude; +} + #endif // LOCALEGLOBAL_H