[upstream] merge with master branch
This commit is contained in:
commit
0bdc8f11db
22
CHANGES
22
CHANGES
@ -8,14 +8,36 @@ website will have to do for older versions.
|
||||
This release contains contributions from (alphabetically by first name):
|
||||
- Alf Gaida
|
||||
- Caio Carvalho
|
||||
- Kevin Kofler
|
||||
- Philip Mueller
|
||||
- Scott Harvey
|
||||
|
||||
## Core ##
|
||||
|
||||
* The Calamares application now recognizes the `-X` or `--xdg-config`
|
||||
option, which adds XDG_DATA_DIRS to the places used to find QML
|
||||
and branding directories, and XDG_CONFIG_DIRS to the places used
|
||||
to find the global settings and module configurations. This allows
|
||||
a more fine-grained, and more layered, approach to setting up
|
||||
Calamares configurations (in particular, distro's can **add**
|
||||
configuration files and give them priority, instead of **forking**
|
||||
configuration files).
|
||||
|
||||
## Modules ##
|
||||
|
||||
* The *partition* module supports RAID devices, but only when Calamares
|
||||
is compiled with the newest KPMCore release.
|
||||
* The calculation of required space -- including swap -- has been simplified,
|
||||
and Calamares no longer reserves 2GiB of space in calculations for internal
|
||||
use (this means that it no longer mysteriously drops swap when the disk
|
||||
size is close to the required installation size).
|
||||
* The *keyboard* module now handles the (bogus) Austrian keymap for
|
||||
the system console properly.
|
||||
* The *preservefiles* module now has a mechanism for setting the permissions
|
||||
(and ownership) of preserved files.
|
||||
* New module *fsresizer* can be used to resize filesystems. It is intended
|
||||
for use in OEM installs where an image of fixed size is created,
|
||||
and then sized to the actual SD card the user has used.
|
||||
|
||||
# 3.2.2 (2018-09-04) #
|
||||
|
||||
|
@ -237,6 +237,11 @@ set_package_properties(
|
||||
find_package(ECM ${ECM_VERSION} NO_MODULE)
|
||||
if( ECM_FOUND )
|
||||
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_MODULE_PATH})
|
||||
if ( BUILD_TESTING )
|
||||
# ECM implies that we can build the tests, too
|
||||
find_package( Qt5 COMPONENTS Test REQUIRED )
|
||||
include( ECMAddTests )
|
||||
endif()
|
||||
endif()
|
||||
|
||||
find_package( KF5 COMPONENTS CoreAddons Crash )
|
||||
|
@ -14,165 +14,165 @@ Categories=Qt;System;
|
||||
X-AppStream-Ignore=true
|
||||
|
||||
Name[ar]=نظام التثبيت
|
||||
Icon[be]=calamares
|
||||
GenericName[be]=Усталёўшчык сістэмы
|
||||
Comment[be]=Calamares — усталёўшчык сістэмы
|
||||
Icon[be]=calamares
|
||||
Name[be]=Усталяваць сістэму
|
||||
Icon[bg]=calamares
|
||||
GenericName[bg]=Системен Инсталатор
|
||||
GenericName[be]=Усталёўшчык сістэмы
|
||||
Comment[bg]=Calamares — Системен Инсталатор
|
||||
Icon[bg]=calamares
|
||||
Name[bg]=Инсталирай системата
|
||||
Icon[ca]=calamares
|
||||
GenericName[ca]=Instal·lador de sistema
|
||||
GenericName[bg]=Системен Инсталатор
|
||||
Comment[ca]=Calamares — Instal·lador de sistema
|
||||
Icon[ca]=calamares
|
||||
Name[ca]=Instal·la el sistema
|
||||
Icon[da]=calamares
|
||||
GenericName[da]=Systeminstallationsprogram
|
||||
GenericName[ca]=Instal·lador de sistema
|
||||
Comment[da]=Calamares — Systeminstallationsprogram
|
||||
Icon[da]=calamares
|
||||
Name[da]=Installér system
|
||||
Icon[de]=calamares
|
||||
GenericName[de]=Installation des Betriebssystems
|
||||
GenericName[da]=Systeminstallationsprogram
|
||||
Comment[de]=Calamares - Installation des Betriebssystems
|
||||
Icon[de]=calamares
|
||||
Name[de]=System installieren
|
||||
Icon[el]=calamares
|
||||
GenericName[el]=Εγκατάσταση συστήματος
|
||||
GenericName[de]=Installation des Betriebssystems
|
||||
Comment[el]=Calamares — Εγκατάσταση συστήματος
|
||||
Icon[el]=calamares
|
||||
Name[el]=Εγκατάσταση συστήματος
|
||||
Icon[en_GB]=calamares
|
||||
GenericName[en_GB]=System Installer
|
||||
GenericName[el]=Εγκατάσταση συστήματος
|
||||
Comment[en_GB]=Calamares — System Installer
|
||||
Icon[en_GB]=calamares
|
||||
Name[en_GB]=Install System
|
||||
Icon[es]=calamares
|
||||
GenericName[es]=Instalador del Sistema
|
||||
GenericName[en_GB]=System Installer
|
||||
Comment[es]=Calamares — Instalador del Sistema
|
||||
Icon[es]=calamares
|
||||
Name[es]=Instalar Sistema
|
||||
Icon[et]=calamares
|
||||
GenericName[et]=Süsteemipaigaldaja
|
||||
GenericName[es]=Instalador del Sistema
|
||||
Comment[et]=Calamares — süsteemipaigaldaja
|
||||
Icon[et]=calamares
|
||||
Name[et]=Paigalda süsteem
|
||||
GenericName[et]=Süsteemipaigaldaja
|
||||
Name[eu]=Sistema instalatu
|
||||
Name[es_PR]=Instalar el sistema
|
||||
Icon[fr]=calamares
|
||||
GenericName[fr]=Installateur système
|
||||
Comment[fr]=Calamares - Installateur système
|
||||
Icon[fr]=calamares
|
||||
Name[fr]=Installer le système
|
||||
GenericName[fr]=Installateur système
|
||||
Name[gl]=Instalación do Sistema
|
||||
Icon[he]=calamares
|
||||
GenericName[he]=אשף התקנה
|
||||
Comment[he]=Calamares - אשף התקנה
|
||||
Icon[he]=calamares
|
||||
Name[he]=התקנת מערכת
|
||||
Icon[hi]=calamares
|
||||
GenericName[hi]=सिस्टम इंस्टॉलर
|
||||
GenericName[he]=אשף התקנה
|
||||
Comment[hi]=Calamares — सिस्टम इंस्टॉलर
|
||||
Icon[hi]=calamares
|
||||
Name[hi]=सिस्टम इंस्टॉल करें
|
||||
Icon[hr]=calamares
|
||||
GenericName[hr]=Instalacija sustava
|
||||
GenericName[hi]=सिस्टम इंस्टॉलर
|
||||
Comment[hr]=Calamares — Instalacija sustava
|
||||
Icon[hr]=calamares
|
||||
Name[hr]=Instaliraj sustav
|
||||
Icon[hu]=calamares
|
||||
GenericName[hu]=Rendszer Telepítő
|
||||
GenericName[hr]=Instalacija sustava
|
||||
Comment[hu]=Calamares — Rendszer Telepítő
|
||||
Icon[hu]=calamares
|
||||
Name[hu]=Rendszer telepítése
|
||||
Icon[id]=calamares
|
||||
GenericName[id]=Pemasang
|
||||
GenericName[hu]=Rendszer Telepítő
|
||||
Comment[id]=Calamares — Pemasang Sistem
|
||||
Icon[id]=calamares
|
||||
Name[id]=Instal Sistem
|
||||
Icon[is]=calamares
|
||||
GenericName[is]=Kerfis uppsetning
|
||||
GenericName[id]=Pemasang
|
||||
Comment[is]=Calamares — Kerfis uppsetning
|
||||
Icon[is]=calamares
|
||||
Name[is]=Setja upp kerfið
|
||||
Icon[cs_CZ]=calamares
|
||||
GenericName[cs_CZ]=Instalátor systému
|
||||
GenericName[is]=Kerfis uppsetning
|
||||
Comment[cs_CZ]=Calamares – instalátor operačních systémů
|
||||
Icon[cs_CZ]=calamares
|
||||
Name[cs_CZ]=Nainstalovat
|
||||
Icon[ja]=calamares
|
||||
GenericName[ja]=システムインストーラー
|
||||
GenericName[cs_CZ]=Instalátor systému
|
||||
Comment[ja]=Calamares — システムインストーラー
|
||||
Icon[ja]=calamares
|
||||
Name[ja]=システムをインストール
|
||||
Icon[ko]=깔라마레스
|
||||
GenericName[ko]=시스템 설치 관리자
|
||||
GenericName[ja]=システムインストーラー
|
||||
Comment[ko]=깔라마레스 — 시스템 설치 관리자
|
||||
Icon[ko]=깔라마레스
|
||||
Name[ko]=시스템 설치
|
||||
Icon[lt]=calamares
|
||||
GenericName[lt]=Sistemos diegimas į kompiuterį
|
||||
GenericName[ko]=시스템 설치 관리자
|
||||
Comment[lt]=Calamares — Sistemos diegimo programa
|
||||
Icon[lt]=calamares
|
||||
Name[lt]=Įdiegti Sistemą
|
||||
Icon[it_IT]=calamares
|
||||
GenericName[it_IT]=Programma d'installazione del sistema
|
||||
GenericName[lt]=Sistemos diegimas į kompiuterį
|
||||
Comment[it_IT]=Calamares — Programma d'installazione del sistema
|
||||
Icon[it_IT]=calamares
|
||||
Name[it_IT]=Installa il sistema
|
||||
Icon[nb]=calamares
|
||||
GenericName[nb]=Systeminstallatør
|
||||
GenericName[it_IT]=Programma d'installazione del sistema
|
||||
Comment[nb]=Calamares-systeminstallatør
|
||||
Icon[nb]=calamares
|
||||
Name[nb]=Installer System
|
||||
Icon[nl]=calamares
|
||||
GenericName[nl]=Installatieprogramma
|
||||
GenericName[nb]=Systeminstallatør
|
||||
Comment[nl]=Calamares — Installatieprogramma
|
||||
Icon[nl]=calamares
|
||||
Name[nl]=Installeer systeem
|
||||
Icon[pl]=calamares
|
||||
GenericName[pl]=Instalator systemu
|
||||
GenericName[nl]=Installatieprogramma
|
||||
Comment[pl]=Calamares — Instalator systemu
|
||||
Icon[pl]=calamares
|
||||
Name[pl]=Zainstaluj system
|
||||
Icon[pt_BR]=calamares
|
||||
GenericName[pt_BR]=Instalador de Sistema
|
||||
GenericName[pl]=Instalator systemu
|
||||
Comment[pt_BR]=Calamares — Instalador de Sistema
|
||||
Icon[pt_BR]=calamares
|
||||
Name[pt_BR]=Sistema de Instalação
|
||||
Icon[ro]=calamares
|
||||
GenericName[ro]=Instalator de sistem
|
||||
GenericName[pt_BR]=Instalador de Sistema
|
||||
Comment[ro]=Calamares — Instalator de sistem
|
||||
Icon[ro]=calamares
|
||||
Name[ro]=Instalează sistemul
|
||||
Icon[ru]=calamares
|
||||
GenericName[ru]=Установщик системы
|
||||
GenericName[ro]=Instalator de sistem
|
||||
Comment[ru]=Calamares - Установщик системы
|
||||
Icon[ru]=calamares
|
||||
Name[ru]=Установить систему
|
||||
Icon[sk]=calamares
|
||||
GenericName[sk]=Inštalátor systému
|
||||
GenericName[ru]=Установщик системы
|
||||
Comment[sk]=Calamares — Inštalátor systému
|
||||
Icon[sk]=calamares
|
||||
Name[sk]=Inštalovať systém
|
||||
GenericName[sk]=Inštalátor systému
|
||||
Name[sl]=Namesti sistem
|
||||
Icon[sq]=calamares
|
||||
GenericName[sq]=Instalues Sistemi
|
||||
Comment[sq]=Calamares — Instalues Sistemi
|
||||
Icon[sq]=calamares
|
||||
Name[sq]=Instalo Sistemin
|
||||
Icon[fi_FI]=calamares
|
||||
GenericName[fi_FI]=Järjestelmän Asennusohjelma
|
||||
GenericName[sq]=Instalues Sistemi
|
||||
Comment[fi_FI]=Calamares — Järjestelmän Asentaja
|
||||
Icon[fi_FI]=calamares
|
||||
Name[fi_FI]=Asenna Järjestelmä
|
||||
GenericName[fi_FI]=Järjestelmän Asennusohjelma
|
||||
Name[sr@latin]=Instaliraj sistem
|
||||
Name[sr]=Инсталирај систем
|
||||
Icon[sv]=calamares
|
||||
GenericName[sv]=Systeminstallerare
|
||||
Comment[sv]=Calamares — Systeminstallerare
|
||||
Icon[sv]=calamares
|
||||
Name[sv]=Installera system
|
||||
GenericName[sv]=Systeminstallerare
|
||||
Name[th]=ติดตั้งระบบ
|
||||
GenericName[uk]=Встановлювач системи
|
||||
Comment[uk]=Calamares - Встановлювач системи
|
||||
Name[uk]=Встановити Систему
|
||||
Icon[zh_CN]=calamares
|
||||
GenericName[zh_CN]=系统安装程序
|
||||
GenericName[uk]=Встановлювач системи
|
||||
Comment[zh_CN]=Calamares — 系统安装程序
|
||||
Icon[zh_CN]=calamares
|
||||
Name[zh_CN]=安装系统
|
||||
Icon[zh_TW]=calamares
|
||||
GenericName[zh_TW]=系統安裝程式
|
||||
GenericName[zh_CN]=系统安装程序
|
||||
Comment[zh_TW]=Calamares ── 系統安裝程式
|
||||
Icon[zh_TW]=calamares
|
||||
Name[zh_TW]=安裝系統
|
||||
Icon[ast]=calamares
|
||||
GenericName[ast]=Instalador del sistema
|
||||
GenericName[zh_TW]=系統安裝程式
|
||||
Comment[ast]=Calamares — Instalador del sistema
|
||||
Icon[ast]=calamares
|
||||
Name[ast]=Instalar sistema
|
||||
Icon[eo]=calamares
|
||||
GenericName[eo]=Sistema Instalilo
|
||||
GenericName[ast]=Instalador del sistema
|
||||
Comment[eo]=Calamares — Sistema Instalilo
|
||||
Icon[eo]=calamares
|
||||
Name[eo]=Instali Sistemo
|
||||
Icon[es_MX]=calamares
|
||||
GenericName[es_MX]=Instalador del sistema
|
||||
GenericName[eo]=Sistema Instalilo
|
||||
Comment[es_MX]=Calamares - Instalador del sistema
|
||||
Icon[es_MX]=calamares
|
||||
Name[es_MX]=Instalar el Sistema
|
||||
Icon[pt_PT]=calamares
|
||||
GenericName[pt_PT]=Instalador de Sistema
|
||||
GenericName[es_MX]=Instalador del sistema
|
||||
Comment[pt_PT]=Calamares - Instalador de Sistema
|
||||
Icon[pt_PT]=calamares
|
||||
Name[pt_PT]=Instalar Sistema
|
||||
Icon[tr_TR]=calamares
|
||||
GenericName[tr_TR]=Sistem Yükleyici
|
||||
GenericName[pt_PT]=Instalador de Sistema
|
||||
Comment[tr_TR]=Calamares — Sistem Yükleyici
|
||||
Icon[tr_TR]=calamares
|
||||
Name[tr_TR]=Sistemi Yükle
|
||||
GenericName[tr_TR]=Sistem Yükleyici
|
||||
|
@ -51,4 +51,4 @@ df -h
|
||||
echo "# Install results"
|
||||
install_debugging "$DESTDIR"
|
||||
|
||||
$result # Result of make install, above
|
||||
$result || { echo "! Install failed" ; exit 1 ; } # Result of make install, above
|
||||
|
@ -1693,7 +1693,7 @@ Installationsprogrammet vil stoppe og alle ændringer vil gå tabt.</translation
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/PartitionPage.cpp" line="196"/>
|
||||
<source>The partition table on %1 already has %2 primary partitions, and no more can be added. Please remove one primary partition and add an extended partition, instead.</source>
|
||||
<translation>Partitionstabellen på %1 har allerede %2 primære partitioner, og der kan ikke tilføjes flere. Fjern venligst en primær partition og tilføj i stedet en udviddet partition.</translation>
|
||||
<translation>Partitionstabellen på %1 har allerede %2 primære partitioner, og der kan ikke tilføjes flere. Fjern venligst en primær partition og tilføj i stedet en udvidet partition.</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
|
@ -4,7 +4,7 @@
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/BootInfoWidget.cpp" line="69"/>
|
||||
<source>The <strong>boot environment</strong> of this system.<br><br>Older x86 systems only support <strong>BIOS</strong>.<br>Modern systems usually use <strong>EFI</strong>, but may also show up as BIOS if started in compatibility mode.</source>
|
||||
<translation>L'<strong>environnement de démarrage</strong> de ce système.<br><br>Les anciens systèmes x86 supportent uniquement le <strong>BIOS</strong>.<br>Les systèmes récents utilisent habituellement <strong>EFI</strong>, mais peuvent également afficher BIOS s'ils sont démarrés en mode de compatibilité.</translation>
|
||||
<translation>L'<strong>environnement de démarrage</strong> de ce système.<br><br>Les anciens systèmes x86 supportent uniquement <strong>BIOS</strong>.<br>Les systèmes récents utilisent habituellement <strong>EFI</strong>, mais peuvent également afficher BIOS s'ils sont démarrés en mode de compatibilité.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/BootInfoWidget.cpp" line="79"/>
|
||||
|
@ -521,7 +521,7 @@ The installer will quit and all changes will be lost.</source>
|
||||
<message>
|
||||
<location filename="../src/modules/contextualprocess/ContextualProcessJob.cpp" line="117"/>
|
||||
<source>Contextual Processes Job</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>משימת תהליכי הקשר</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -2358,7 +2358,7 @@ Output:
|
||||
<message>
|
||||
<location filename="../src/modules/shellprocess/ShellProcessJob.cpp" line="51"/>
|
||||
<source>Shell Processes Job</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>משימת תהליכי מעטפת</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
|
@ -207,7 +207,7 @@
|
||||
<message>
|
||||
<location filename="../src/libcalamaresui/ViewManager.cpp" line="277"/>
|
||||
<source>&Install</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>&Telepítés</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libcalamaresui/ViewManager.cpp" line="325"/>
|
||||
@ -229,7 +229,7 @@ Minden változtatás elveszik, ha kilépsz a telepítőből.</translation>
|
||||
<message>
|
||||
<location filename="../src/libcalamaresui/ViewManager.cpp" line="332"/>
|
||||
<source>&No</source>
|
||||
<translation>@Nem</translation>
|
||||
<translation>&Nem</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libcalamaresui/ViewManager.cpp" line="163"/>
|
||||
@ -944,7 +944,7 @@ Telepítés nem folytatható. <a href="#details">Részletek...&l
|
||||
<message>
|
||||
<location filename="../src/modules/finished/FinishedPage.ui" line="98"/>
|
||||
<source>&Restart now</source>
|
||||
<translation>$Újraindítás most</translation>
|
||||
<translation>Új&raindítás most</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/finished/FinishedPage.cpp" line="51"/>
|
||||
|
@ -244,7 +244,7 @@ Diegimo programa užbaigs darbą ir visi pakeitimai bus prarasti.</translation>
|
||||
<message>
|
||||
<location filename="../src/libcalamaresui/ViewManager.cpp" line="238"/>
|
||||
<source>The %1 installer is about to make changes to your disk in order to install %2.<br/><strong>You will not be able to undo these changes.</strong></source>
|
||||
<translation>%1 diegimo programa, siekdama įdiegti %2, ketina atlikti pakeitimus diske.<br/><strong>Šių pakeitimų atšaukti nebegalėsite.</strong></translation>
|
||||
<translation>%1 diegimo programa, siekdama įdiegti %2, ketina atlikti pakeitimus diske.<br/><strong>Šių pakeitimų nebegalėsite atšaukti.</strong></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libcalamaresui/ViewManager.cpp" line="243"/>
|
||||
|
@ -50,7 +50,7 @@
|
||||
<message>
|
||||
<location filename="../src/libcalamaresui/viewpages/BlankViewStep.cpp" line="69"/>
|
||||
<source>Blank Page</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Lege pagina</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -192,7 +192,7 @@
|
||||
<message>
|
||||
<location filename="../src/libcalamaresui/ViewManager.cpp" line="179"/>
|
||||
<source>Calamares Initialization Failed</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Calamares Initialisatie mislukt</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libcalamaresui/ViewManager.cpp" line="180"/>
|
||||
@ -202,7 +202,7 @@
|
||||
<message>
|
||||
<location filename="../src/libcalamaresui/ViewManager.cpp" line="185"/>
|
||||
<source><br/>The following modules could not be loaded:</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation><br/>The volgende modules konden niet worden geladen:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libcalamaresui/ViewManager.cpp" line="277"/>
|
||||
@ -1244,7 +1244,7 @@ Het installatieprogramma zal afsluiten en alle wijzigingen zullen verloren gaan.
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="151"/>
|
||||
<source>Password is too weak</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Wachtwoord is te zwak</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="158"/>
|
||||
@ -1259,12 +1259,12 @@ Het installatieprogramma zal afsluiten en alle wijzigingen zullen verloren gaan.
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="164"/>
|
||||
<source>The password is the same as the old one</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Het wachtwoord is hetzelfde als het oude wachtwoord</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="166"/>
|
||||
<source>The password is a palindrome</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Het wachtwoord is een palindroom</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="168"/>
|
||||
@ -1274,12 +1274,12 @@ Het installatieprogramma zal afsluiten en alle wijzigingen zullen verloren gaan.
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="170"/>
|
||||
<source>The password is too similar to the old one</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Het wachtwoord lijkt te veel op het oude wachtwoord</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="172"/>
|
||||
<source>The password contains the user name in some form</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Het wachtwoord bevat de gebruikersnaam op een of andere manier</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="174"/>
|
||||
|
@ -9,7 +9,7 @@
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/BootInfoWidget.cpp" line="79"/>
|
||||
<source>This system was started with an <strong>EFI</strong> boot environment.<br><br>To configure startup from an EFI environment, this installer must deploy a boot loader application, like <strong>GRUB</strong> or <strong>systemd-boot</strong> on an <strong>EFI System Partition</strong>. This is automatic, unless you choose manual partitioning, in which case you must choose it or create it on your own.</source>
|
||||
<translation>这个系统从 <strong>EFI</strong> 引导环境启动。<br><br>目前市面上大多数的民用设备都使用 EFI,并同时与之使用 GPT 分区表。<br>要从 EFI 环境引导的话,本安装程序必须部署一个引导器(如 <strong>GRUB</strong> 或 <strong>systemd-boot</strong>)到 <strong>EFI 系统分区</strong>。这个步骤是自动的,除非您选择手动分区——此时您必须自行选择或创建。</translation>
|
||||
<translation>这个系统是从 <strong>EFI</strong> 引导环境启动的。<br><br>目前市面上大多数的民用设备都使用 EFI,并同时对硬盘使用 GPT 分区表分区。<br>您如果要从 EFI 环境引导这个系统的话,本安装程序必须安装一个引导器(如 <strong>GRUB</strong> 或 <strong>systemd-boot</strong>)到 <strong>EFI 分区</strong>。这个步骤将会由本安装程序自动执行,除非您选择自己创建分区——此时您必须选择让本安装程序自动创建EFI分区或您自己手动创建EFI分区。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/BootInfoWidget.cpp" line="91"/>
|
||||
@ -51,7 +51,7 @@
|
||||
<message>
|
||||
<location filename="../src/libcalamaresui/viewpages/BlankViewStep.cpp" line="69"/>
|
||||
<source>Blank Page</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>空白页</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -193,17 +193,17 @@
|
||||
<message>
|
||||
<location filename="../src/libcalamaresui/ViewManager.cpp" line="179"/>
|
||||
<source>Calamares Initialization Failed</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Calamares安装失败</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libcalamaresui/ViewManager.cpp" line="180"/>
|
||||
<source>%1 can not be installed. Calamares was unable to load all of the configured modules. This is a problem with the way Calamares is being used by the distribution.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>%1无法安装。 Calamares无法加载所有已配置的模块。这是分配使用Calamares的方式的问题。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libcalamaresui/ViewManager.cpp" line="185"/>
|
||||
<source><br/>The following modules could not be loaded:</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation><br/>无法加载以下模块:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libcalamaresui/ViewManager.cpp" line="277"/>
|
||||
@ -265,7 +265,7 @@ The installer will quit and all changes will be lost.</source>
|
||||
<message>
|
||||
<location filename="../src/libcalamaresui/ViewManager.cpp" line="284"/>
|
||||
<source>The installation is complete. Close the installer.</source>
|
||||
<translation>安装过程已完毕。请关闭安装器。</translation>
|
||||
<translation>安装已完成。请关闭安装程序。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libcalamaresui/ViewManager.cpp" line="160"/>
|
||||
@ -334,7 +334,7 @@ The installer will quit and all changes will be lost.</source>
|
||||
<message>
|
||||
<location filename="../src/modules/welcome/checker/CheckerWidget.cpp" line="174"/>
|
||||
<source>For best results, please ensure that this computer:</source>
|
||||
<translation>为了更好的体验,请确定这台电脑: </translation>
|
||||
<translation>为了更好的体验,请确保这台电脑: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/welcome/checker/CheckerWidget.cpp" line="202"/>
|
||||
@ -509,12 +509,12 @@ The installer will quit and all changes will be lost.</source>
|
||||
<message>
|
||||
<location filename="../src/libcalamares/utils/CommandList.cpp" line="128"/>
|
||||
<source>The command runs in the host environment and needs to know the root path, but no rootMountPoint is defined.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>该命令在主机环境中运行,且需要知道根路径,但没有定义root挂载点。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libcalamares/utils/CommandList.cpp" line="139"/>
|
||||
<source>The command needs to know the user's name, but no username is defined.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>命令行需要知道用户的名字,但用户名没有被设置</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -1665,7 +1665,7 @@ The installer will quit and all changes will be lost.</source>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/PartitionPage.ui" line="107"/>
|
||||
<source>Cre&ate</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>创建</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/PartitionPage.ui" line="114"/>
|
||||
@ -1690,12 +1690,12 @@ The installer will quit and all changes will be lost.</source>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/PartitionPage.cpp" line="195"/>
|
||||
<source>Can not create new partition</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>无法创建新分区</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/PartitionPage.cpp" line="196"/>
|
||||
<source>The partition table on %1 already has %2 primary partitions, and no more can be added. Please remove one primary partition and add an extended partition, instead.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>%1上的分区表已经有%2个主分区,并且不能再添加。请删除一个主分区并添加扩展分区。</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -1841,17 +1841,17 @@ The installer will quit and all changes will be lost.</source>
|
||||
<message>
|
||||
<location filename="../src/modules/preservefiles/PreserveFiles.cpp" line="83"/>
|
||||
<source>Saving files for later ...</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>保存文件以供日后使用</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/preservefiles/PreserveFiles.cpp" line="89"/>
|
||||
<source>No files configured to save for later.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>没有已保存且供日后使用的配置文件。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/preservefiles/PreserveFiles.cpp" line="145"/>
|
||||
<source>Not all of the configured files could be preserved.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>并不是所有配置文件都可以被保留</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
|
Binary file not shown.
@ -10,7 +10,7 @@ msgstr ""
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2018-06-18 07:46-0400\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: miku84, 2017\n"
|
||||
"Last-Translator: Adriaan de Groot <groot@kde.org>, 2018\n"
|
||||
"Language-Team: Hungarian (https://www.transifex.com/calamares/teams/20061/hu/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@ -20,7 +20,7 @@ msgstr ""
|
||||
|
||||
#: src/modules/umount/main.py:40
|
||||
msgid "Unmount file systems."
|
||||
msgstr ""
|
||||
msgstr "Fájlrendszerek leválasztása."
|
||||
|
||||
#: src/modules/dummypython/main.py:44
|
||||
msgid "Dummy python job."
|
||||
@ -47,12 +47,12 @@ msgstr "Csomagok telepítése."
|
||||
#, python-format
|
||||
msgid "Installing one package."
|
||||
msgid_plural "Installing %(num)d packages."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
msgstr[0] "Egy csomag telepítése."
|
||||
msgstr[1] "%(num)d csomag telepítése."
|
||||
|
||||
#: src/modules/packages/main.py:70
|
||||
#, python-format
|
||||
msgid "Removing one package."
|
||||
msgid_plural "Removing %(num)d packages."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
msgstr[0] "Egy csomag eltávolítása."
|
||||
msgstr[1] "%(num)d csomag eltávolítása."
|
||||
|
@ -145,6 +145,9 @@ qmlDirCandidates( bool assumeBuilddir )
|
||||
{
|
||||
if ( assumeBuilddir )
|
||||
qmlDirs << QDir::current().absoluteFilePath( "src/qml" ); // In build-dir
|
||||
if ( CalamaresUtils::haveExtraDirs() )
|
||||
for ( auto s : CalamaresUtils::extraDataDirs() )
|
||||
qmlDirs << ( s + QML );
|
||||
qmlDirs << CalamaresUtils::appDataDir().absoluteFilePath( QML );
|
||||
}
|
||||
|
||||
@ -164,6 +167,9 @@ settingsFileCandidates( bool assumeBuilddir )
|
||||
{
|
||||
if ( assumeBuilddir )
|
||||
settingsPaths << QDir::current().absoluteFilePath( settings );
|
||||
if ( CalamaresUtils::haveExtraDirs() )
|
||||
for ( auto s : CalamaresUtils::extraConfigDirs() )
|
||||
settingsPaths << ( s + settings );
|
||||
settingsPaths << CMAKE_INSTALL_FULL_SYSCONFDIR "/calamares/settings.conf"; // String concat
|
||||
settingsPaths << CalamaresUtils::appDataDir().absoluteFilePath( settings );
|
||||
}
|
||||
@ -182,6 +188,9 @@ brandingFileCandidates( bool assumeBuilddir, const QString& brandingFilename )
|
||||
{
|
||||
if ( assumeBuilddir )
|
||||
brandingPaths << ( QDir::currentPath() + QStringLiteral( "/src/" ) + brandingFilename );
|
||||
if ( CalamaresUtils::haveExtraDirs() )
|
||||
for ( auto s : CalamaresUtils::extraDataDirs() )
|
||||
brandingPaths << ( s + brandingFilename );
|
||||
brandingPaths << QDir( CMAKE_INSTALL_FULL_SYSCONFDIR "/calamares/" ).absoluteFilePath( brandingFilename );
|
||||
brandingPaths << CalamaresUtils::appDataDir().absoluteFilePath( brandingFilename);
|
||||
}
|
||||
|
@ -44,6 +44,8 @@ handle_args( CalamaresApplication& a )
|
||||
"Verbose output for debugging purposes (0-8).", "level" );
|
||||
QCommandLineOption configOption( QStringList{ "c", "config"},
|
||||
"Configuration directory to use, for testing purposes.", "config" );
|
||||
QCommandLineOption xdgOption( QStringList{"X", "xdg-config"},
|
||||
"Use XDG_{CONFIG,DATA}_DIRS as well." );
|
||||
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription( "Distribution-independent installer framework" );
|
||||
@ -53,6 +55,7 @@ handle_args( CalamaresApplication& a )
|
||||
parser.addOption( debugOption );
|
||||
parser.addOption( debugLevelOption );
|
||||
parser.addOption( configOption );
|
||||
parser.addOption( xdgOption );
|
||||
|
||||
parser.process( a );
|
||||
|
||||
@ -72,6 +75,8 @@ handle_args( CalamaresApplication& a )
|
||||
}
|
||||
if ( parser.isSet( configOption ) )
|
||||
CalamaresUtils::setAppDataDir( QDir( parser.value( configOption ) ) );
|
||||
if ( parser.isSet( xdgOption ) )
|
||||
CalamaresUtils::setXdgDirs();
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -59,6 +59,7 @@ handle_args( QCoreApplication& a )
|
||||
|
||||
parser.addOption( debugLevelOption );
|
||||
parser.addPositionalArgument( "module", "Path or name of module to run." );
|
||||
parser.addPositionalArgument( "config", "Path of job-config file to use.", "[config]");
|
||||
|
||||
parser.process( a );
|
||||
|
||||
@ -140,6 +141,8 @@ load_module( const ModuleConfig& moduleConfig )
|
||||
? moduleDirectory + '/' + name + ".conf"
|
||||
: moduleConfig.configFile() );
|
||||
|
||||
cDebug() << "Module" << moduleName << "job-configuration:" << configFile;
|
||||
|
||||
Calamares::Module* module = Calamares::Module::fromDescriptor(
|
||||
descriptor, name, configFile, moduleDirectory );
|
||||
|
||||
@ -158,7 +161,7 @@ main( int argc, char* argv[] )
|
||||
std::unique_ptr< Calamares::Settings > settings_p( new Calamares::Settings( QString(), true ) );
|
||||
std::unique_ptr< Calamares::JobQueue > jobqueue_p( new Calamares::JobQueue( nullptr ) );
|
||||
|
||||
cDebug() << "Calamares test module-loader" << module.moduleName();
|
||||
cDebug() << "Calamares module-loader testing" << module.moduleName();
|
||||
Calamares::Module* m = load_module( module );
|
||||
if ( !m )
|
||||
{
|
||||
@ -175,16 +178,27 @@ main( int argc, char* argv[] )
|
||||
return 1;
|
||||
}
|
||||
|
||||
cDebug() << "Module" << m->name() << m->typeString() << m->interfaceString();
|
||||
using TR = Logger::DebugRow<const char*, const QString&>;
|
||||
|
||||
cDebug() << "Module metadata"
|
||||
<< TR( "name", m->name() )
|
||||
<< TR( "type", m->typeString() )
|
||||
<< TR( "interface", m->interfaceString() );
|
||||
|
||||
cDebug() << "Job outputs:";
|
||||
Calamares::JobList jobList = m->jobs();
|
||||
unsigned int count = 1;
|
||||
for ( const auto& p : jobList )
|
||||
{
|
||||
cDebug() << count << p->prettyName();
|
||||
cDebug() << "Job #" << count << "name" << p->prettyName();
|
||||
Calamares::JobResult r = p->exec();
|
||||
if ( !r )
|
||||
cDebug() << count << ".. failed" << r;
|
||||
{
|
||||
using TR = Logger::DebugRow<QString, QString>;
|
||||
cDebug() << count << ".. failed"
|
||||
<< TR( "summary", r.message() )
|
||||
<< TR( "details", r.details() );
|
||||
}
|
||||
++count;
|
||||
}
|
||||
|
||||
|
@ -105,6 +105,19 @@ install( TARGETS calamares
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
)
|
||||
|
||||
if ( ECM_FOUND AND BUILD_TESTING )
|
||||
ecm_add_test(
|
||||
Tests.cpp
|
||||
TEST_NAME
|
||||
libcalamarestest
|
||||
LINK_LIBRARIES
|
||||
calamares
|
||||
Qt5::Core
|
||||
Qt5::Test
|
||||
)
|
||||
set_target_properties( libcalamarestest PROPERTIES AUTOMOC TRUE )
|
||||
endif()
|
||||
|
||||
# Make symlink lib/calamares/libcalamares.so to lib/libcalamares.so.VERSION so
|
||||
# lib/calamares can be used as module path for the Python interpreter.
|
||||
install( CODE "
|
||||
|
59
src/libcalamares/Tests.cpp
Normal file
59
src/libcalamares/Tests.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
/* === This file is part of Calamares - <https://github.com/calamares> ===
|
||||
*
|
||||
* Copyright 2018, Adriaan de Groot <groot@kde.org>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Tests.h"
|
||||
|
||||
#include "utils/Logger.h"
|
||||
|
||||
#include <QtTest/QtTest>
|
||||
|
||||
QTEST_GUILESS_MAIN( LibCalamaresTests )
|
||||
|
||||
LibCalamaresTests::LibCalamaresTests()
|
||||
{
|
||||
}
|
||||
|
||||
LibCalamaresTests::~LibCalamaresTests()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
LibCalamaresTests::initTestCase()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
LibCalamaresTests::testDebugLevels()
|
||||
{
|
||||
Logger::setupLogLevel( Logger::LOG_DISABLE );
|
||||
|
||||
QCOMPARE( Logger::logLevel(), static_cast<unsigned int>( Logger::LOG_DISABLE ) );
|
||||
|
||||
for ( unsigned int level = 0; level <= Logger::LOGVERBOSE ; ++level )
|
||||
{
|
||||
Logger::setupLogLevel( level );
|
||||
QCOMPARE( Logger::logLevel(), level );
|
||||
QVERIFY( Logger::logLevelEnabled( level ) );
|
||||
|
||||
for ( unsigned int xlevel = 0; xlevel <= Logger::LOGVERBOSE; ++xlevel )
|
||||
{
|
||||
QCOMPARE( Logger::logLevelEnabled( xlevel ), xlevel <= level );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
36
src/libcalamares/Tests.h
Normal file
36
src/libcalamares/Tests.h
Normal file
@ -0,0 +1,36 @@
|
||||
/* === This file is part of Calamares - <https://github.com/calamares> ===
|
||||
*
|
||||
* Copyright 2018, Adriaan de Groot <groot@kde.org>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TESTS_H
|
||||
#define TESTS_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class LibCalamaresTests : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
LibCalamaresTests();
|
||||
~LibCalamaresTests() override;
|
||||
|
||||
private Q_SLOTS:
|
||||
void initTestCase();
|
||||
void testDebugLevels();
|
||||
};
|
||||
|
||||
#endif
|
@ -49,6 +49,9 @@ static QTranslator* s_brandingTranslator = nullptr;
|
||||
static QTranslator* s_translator = nullptr;
|
||||
static QString s_translatorLocaleName;
|
||||
|
||||
static bool s_haveExtraDirs = false;
|
||||
static QStringList s_extraConfigDirs;
|
||||
static QStringList s_extraDataDirs;
|
||||
|
||||
static bool
|
||||
isWritableDir( const QDir& dir )
|
||||
@ -94,6 +97,46 @@ setAppDataDir( const QDir& dir )
|
||||
s_isAppDataDirOverridden = true;
|
||||
}
|
||||
|
||||
/* Split $ENV{@p name} on :, append to @p l, making sure each ends in / */
|
||||
static void
|
||||
mungeEnvironment( QStringList& l, const char *name )
|
||||
{
|
||||
for ( auto s : QString( qgetenv( name ) ).split(':') )
|
||||
if ( s.endsWith( '/' ) )
|
||||
l << s;
|
||||
else
|
||||
l << ( s + '/' );
|
||||
}
|
||||
|
||||
void
|
||||
setXdgDirs()
|
||||
{
|
||||
s_haveExtraDirs = true;
|
||||
mungeEnvironment( s_extraConfigDirs, "XDG_CONFIG_DIRS" );
|
||||
mungeEnvironment( s_extraDataDirs, "XDG_DATA_DIRS" );
|
||||
}
|
||||
|
||||
QStringList
|
||||
extraConfigDirs()
|
||||
{
|
||||
if ( s_haveExtraDirs )
|
||||
return s_extraConfigDirs;
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
QStringList
|
||||
extraDataDirs()
|
||||
{
|
||||
if ( s_haveExtraDirs )
|
||||
return s_extraDataDirs;
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
bool
|
||||
haveExtraDirs()
|
||||
{
|
||||
return s_haveExtraDirs && ( !s_extraConfigDirs.isEmpty() || !s_extraDataDirs.isEmpty() );
|
||||
}
|
||||
|
||||
bool
|
||||
isAppDataDirOverridden()
|
||||
|
@ -79,6 +79,16 @@ namespace CalamaresUtils
|
||||
|
||||
DLLEXPORT void setQmlModulesDir( const QDir& dir );
|
||||
|
||||
/** @brief Setup extra config and data dirs from the XDG variables.
|
||||
*/
|
||||
DLLEXPORT void setXdgDirs();
|
||||
/** @brief Are any extra directories configured? */
|
||||
DLLEXPORT bool haveExtraDirs();
|
||||
/** @brief XDG_CONFIG_DIRS, each guaranteed to end with / */
|
||||
DLLEXPORT QStringList extraConfigDirs();
|
||||
/** @brief XDG_DATA_DIRS, each guaranteed to end with / */
|
||||
DLLEXPORT QStringList extraDataDirs();
|
||||
|
||||
/**
|
||||
* @brief removeDiacritics replaces letters with diacritics and ligatures with
|
||||
* alternative forms and digraphs.
|
||||
|
@ -55,6 +55,18 @@ setupLogLevel(unsigned int level)
|
||||
s_threshold = level + 1; // Comparison is < in log() function
|
||||
}
|
||||
|
||||
bool
|
||||
logLevelEnabled(unsigned int level)
|
||||
{
|
||||
return level < s_threshold;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
logLevel()
|
||||
{
|
||||
return s_threshold > 0 ? s_threshold - 1 : 0;
|
||||
}
|
||||
|
||||
static void
|
||||
log( const char* msg, unsigned int debugLevel, bool toDisk = true )
|
||||
{
|
||||
|
@ -89,6 +89,12 @@ namespace Logger
|
||||
*/
|
||||
DLLEXPORT void setupLogLevel( unsigned int level );
|
||||
|
||||
/** @brief Return the configured log-level. */
|
||||
DLLEXPORT unsigned int logLevel();
|
||||
|
||||
/** @brief Would the given @p level really be logged? */
|
||||
DLLEXPORT bool logLevelEnabled( unsigned int level );
|
||||
|
||||
/**
|
||||
* @brief Row-oriented formatted logging.
|
||||
*
|
||||
|
@ -145,8 +145,19 @@ moduleConfigurationCandidates( bool assumeBuildDir, const QString& moduleName, c
|
||||
paths << CalamaresUtils::appDataDir().absoluteFilePath( QString( "modules/%1" ).arg( configFileName ) );
|
||||
else
|
||||
{
|
||||
// If an absolute path is given, in debug mode, look for it
|
||||
// first. The case contains('/'), below, will add the absolute
|
||||
// path a second time, though.
|
||||
if ( assumeBuildDir && configFileName.startsWith( '/' ) )
|
||||
paths << configFileName;
|
||||
if ( assumeBuildDir )
|
||||
paths << QDir().absoluteFilePath(QString( "src/modules/%1/%2" ).arg( moduleName ).arg( configFileName ) );
|
||||
if ( assumeBuildDir && configFileName.contains( '/' ) )
|
||||
paths << QDir().absoluteFilePath( configFileName );
|
||||
|
||||
if ( CalamaresUtils::haveExtraDirs() )
|
||||
for ( auto s : CalamaresUtils::extraConfigDirs() )
|
||||
paths << ( s + QString( "modules/%1" ).arg( configFileName ) );
|
||||
|
||||
paths << QString( "/etc/calamares/modules/%1" ).arg( configFileName );
|
||||
paths << CalamaresUtils::appDataDir().absoluteFilePath( QString( "modules/%1" ).arg( configFileName ) );
|
||||
@ -168,6 +179,7 @@ Module::loadConfigurationFile( const QString& configFileName ) //throws YAML::Ex
|
||||
YAML::Node doc = YAML::Load( ba.constData() );
|
||||
if ( doc.IsNull() )
|
||||
{
|
||||
cDebug() << "Found empty module configuration" << path;
|
||||
// Special case: empty config files are valid,
|
||||
// but aren't a map.
|
||||
return;
|
||||
@ -178,14 +190,13 @@ Module::loadConfigurationFile( const QString& configFileName ) //throws YAML::Ex
|
||||
return;
|
||||
}
|
||||
|
||||
cDebug() << "Loaded module configuration" << path;
|
||||
m_configurationMap = CalamaresUtils::yamlMapToVariant( doc ).toMap();
|
||||
m_emergency = m_maybe_emergency
|
||||
&& m_configurationMap.contains( EMERGENCY )
|
||||
&& m_configurationMap[ EMERGENCY ].toBool();
|
||||
return;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,10 +8,7 @@ calamares_add_plugin( contextualprocess
|
||||
SHARED_LIB
|
||||
)
|
||||
|
||||
if( ECM_FOUND )
|
||||
find_package( Qt5 COMPONENTS Test REQUIRED )
|
||||
include( ECMAddTests )
|
||||
|
||||
if( ECM_FOUND AND BUILD_TESTING )
|
||||
ecm_add_test(
|
||||
Tests.cpp
|
||||
ContextualProcessJob.cpp # Builds it a second time
|
||||
|
Binary file not shown.
@ -8,9 +8,9 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-09-04 08:16-0400\n"
|
||||
"POT-Creation-Date: 2018-06-18 07:46-0400\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: Mingcong Bai <jeffbai@aosc.xyz>, 2017\n"
|
||||
"Last-Translator: soenggam <senggemg@gmail.com>, 2017\n"
|
||||
"Language-Team: Chinese (China) (https://www.transifex.com/calamares/teams/20061/zh_CN/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@ -24,7 +24,7 @@ msgstr "按我按我!"
|
||||
|
||||
#: src/modules/dummypythonqt/main.py:94
|
||||
msgid "A new QLabel."
|
||||
msgstr "一个平淡无奇的 QLabel。"
|
||||
msgstr "一个新的QLabel。"
|
||||
|
||||
#: src/modules/dummypythonqt/main.py:97
|
||||
msgid "Dummy PythonQt ViewStep"
|
||||
|
41
src/modules/fsresizer/CMakeLists.txt
Normal file
41
src/modules/fsresizer/CMakeLists.txt
Normal file
@ -0,0 +1,41 @@
|
||||
find_package( KPMcore 3.3 )
|
||||
find_package( Qt5 REQUIRED DBus ) # Needed for KPMCore
|
||||
find_package( KF5 REQUIRED I18n WidgetsAddons ) # Needed for KPMCore
|
||||
|
||||
if ( KPMcore_FOUND )
|
||||
include_directories( ${KPMCORE_INCLUDE_DIR} )
|
||||
include_directories( ${PROJECT_BINARY_DIR}/src/libcalamares )
|
||||
|
||||
# The PartitionIterator is a small class, and it's easiest -- but also a
|
||||
# gross hack -- to just compile it again from the partition module tree.
|
||||
calamares_add_plugin( fsresizer
|
||||
TYPE job
|
||||
EXPORT_MACRO PLUGINDLLEXPORT_PRO
|
||||
SOURCES
|
||||
ResizeFSJob.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/modules/partition/core/PartitionIterator.cpp
|
||||
LINK_PRIVATE_LIBRARIES
|
||||
kpmcore
|
||||
calamares
|
||||
SHARED_LIB
|
||||
)
|
||||
|
||||
if( ECM_FOUND AND BUILD_TESTING )
|
||||
ecm_add_test(
|
||||
Tests.cpp
|
||||
TEST_NAME
|
||||
fsresizertest
|
||||
LINK_LIBRARIES
|
||||
${CALAMARES_LIBRARIES}
|
||||
calamares
|
||||
calamares_job_fsresizer # From above
|
||||
${YAMLCPP_LIBRARY}
|
||||
Qt5::Core
|
||||
Qt5::Test
|
||||
)
|
||||
set_target_properties( fsresizertest PROPERTIES AUTOMOC TRUE )
|
||||
target_include_directories(fsresizertest PRIVATE /usr/local/include )
|
||||
endif()
|
||||
else()
|
||||
calamares_skip_module( "fsresizer (missing suitable KPMcore)" )
|
||||
endif()
|
347
src/modules/fsresizer/ResizeFSJob.cpp
Normal file
347
src/modules/fsresizer/ResizeFSJob.cpp
Normal file
@ -0,0 +1,347 @@
|
||||
/* === This file is part of Calamares - <https://github.com/calamares> ===
|
||||
*
|
||||
* Copyright 2018, Adriaan de Groot <groot@kde.org>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ResizeFSJob.h"
|
||||
|
||||
#include <QProcess>
|
||||
#include <QDateTime>
|
||||
#include <QThread>
|
||||
|
||||
#include <kpmcore/backend/corebackend.h>
|
||||
#include <kpmcore/backend/corebackendmanager.h>
|
||||
#include <kpmcore/core/device.h>
|
||||
#include <kpmcore/core/partition.h>
|
||||
#include <kpmcore/ops/resizeoperation.h>
|
||||
#include <kpmcore/util/report.h>
|
||||
|
||||
#include "CalamaresVersion.h"
|
||||
#include "JobQueue.h"
|
||||
#include "GlobalStorage.h"
|
||||
|
||||
#include "utils/CalamaresUtils.h"
|
||||
#include "utils/Logger.h"
|
||||
#include "utils/Units.h"
|
||||
|
||||
#include "modules/partition/core/PartitionIterator.h"
|
||||
|
||||
ResizeFSJob::RelativeSize::RelativeSize()
|
||||
: m_value( 0 )
|
||||
, m_unit( None )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
template<int N>
|
||||
void matchUnitSuffix(
|
||||
const QString& s,
|
||||
const char ( &suffix )[N],
|
||||
ResizeFSJob::RelativeSize::Unit matchedUnit,
|
||||
int& value,
|
||||
ResizeFSJob::RelativeSize::Unit& unit
|
||||
)
|
||||
{
|
||||
if ( s.endsWith( suffix ) )
|
||||
{
|
||||
value = s.left( s.length() - N + 1 ).toInt();
|
||||
unit = matchedUnit;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ResizeFSJob::RelativeSize::RelativeSize( const QString& s )
|
||||
: m_value( 0 )
|
||||
, m_unit( None )
|
||||
{
|
||||
matchUnitSuffix( s, "%", Percent, m_value, m_unit );
|
||||
matchUnitSuffix( s, "MiB", Absolute, m_value, m_unit );
|
||||
|
||||
if ( ( unit() == Percent ) && ( value() > 100 ) )
|
||||
{
|
||||
cDebug() << "Percent value" << value() << "is not valid.";
|
||||
m_value = 0;
|
||||
m_unit = None;
|
||||
}
|
||||
|
||||
if ( !m_value )
|
||||
m_unit = None;
|
||||
}
|
||||
|
||||
qint64
|
||||
ResizeFSJob::RelativeSize::apply( qint64 totalSectors, qint64 sectorSize )
|
||||
{
|
||||
if ( !isValid() )
|
||||
return -1;
|
||||
if ( sectorSize < 1 )
|
||||
return -1;
|
||||
|
||||
switch ( m_unit )
|
||||
{
|
||||
case None:
|
||||
return -1;
|
||||
case Absolute:
|
||||
return CalamaresUtils::MiBtoBytes( value() ) / sectorSize;
|
||||
case Percent:
|
||||
if ( value() == 100 )
|
||||
return totalSectors; // Common-case, avoid futzing around
|
||||
else
|
||||
return totalSectors * value() / 100;
|
||||
}
|
||||
|
||||
// notreached
|
||||
return -1;
|
||||
}
|
||||
|
||||
qint64
|
||||
ResizeFSJob::RelativeSize::apply( Device* d )
|
||||
{
|
||||
return apply( d->totalLogical(), d->logicalSize() );
|
||||
}
|
||||
|
||||
ResizeFSJob::ResizeFSJob( QObject* parent )
|
||||
: Calamares::CppJob( parent )
|
||||
, m_required( false )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ResizeFSJob::~ResizeFSJob()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
ResizeFSJob::prettyName() const
|
||||
{
|
||||
return tr( "Resize Filesystem Job" );
|
||||
}
|
||||
|
||||
ResizeFSJob::PartitionMatch
|
||||
ResizeFSJob::findPartition( CoreBackend* backend )
|
||||
{
|
||||
using DeviceList = QList< Device* >;
|
||||
DeviceList devices = backend->scanDevices( false );
|
||||
cDebug() << "ResizeFSJob found" << devices.count() << "devices.";
|
||||
for ( DeviceList::iterator dev_it = devices.begin(); dev_it != devices.end(); ++dev_it )
|
||||
{
|
||||
if ( ! ( *dev_it ) )
|
||||
continue;
|
||||
cDebug() << "ResizeFSJob found" << ( *dev_it )->deviceNode();
|
||||
for ( auto part_it = PartitionIterator::begin( *dev_it ); part_it != PartitionIterator::end( *dev_it ); ++part_it )
|
||||
{
|
||||
cDebug() << ".." << ( *part_it )->mountPoint() << "on" << ( *part_it )->deviceNode();
|
||||
if ( ( !m_fsname.isEmpty() && ( *part_it )->mountPoint() == m_fsname ) ||
|
||||
( !m_devicename.isEmpty() && ( *part_it )->deviceNode() == m_devicename ) )
|
||||
{
|
||||
cDebug() << ".. matched configuration dev=" << m_devicename << "fs=" << m_fsname;
|
||||
return PartitionMatch( *dev_it, *part_it );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cDebug() << "No match for configuration dev=" << m_devicename << "fs=" << m_fsname;
|
||||
return PartitionMatch( nullptr, nullptr );
|
||||
}
|
||||
|
||||
/** @brief Returns the last sector the matched partition should occupy.
|
||||
*
|
||||
* Returns a sector number. Returns -1 if something is wrong (e.g.
|
||||
* can't resize at all, or missing data). Returns 0 if the resize
|
||||
* won't fit because it doesn't satisfy the settings for atleast
|
||||
* and size (or won't grow at all because the partition is blocked
|
||||
* by occupied space after it).
|
||||
*/
|
||||
qint64
|
||||
ResizeFSJob::findGrownEnd( ResizeFSJob::PartitionMatch m )
|
||||
{
|
||||
if ( !m.first || !m.second )
|
||||
return -1; // Missing device data
|
||||
if ( !ResizeOperation::canGrow( m.second ) )
|
||||
return -1; // Operation is doomed
|
||||
if ( !m_size.isValid() )
|
||||
return -1; // Must have a grow-size
|
||||
|
||||
cDebug() << "Containing device size" << m.first->totalLogical();
|
||||
qint64 last_available = m.first->totalLogical() - 1; // Numbered from 0
|
||||
qint64 last_currently = m.second->lastSector();
|
||||
cDebug() << "Growing partition" << m.second->firstSector() << '-' << last_currently;
|
||||
|
||||
for ( auto part_it = PartitionIterator::begin( m.first ); part_it != PartitionIterator::end( m.first ); ++part_it )
|
||||
{
|
||||
qint64 next_start = ( *part_it )->firstSector();
|
||||
qint64 next_end = ( *part_it )->lastSector();
|
||||
if ( next_start > next_end )
|
||||
{
|
||||
cWarning() << "Corrupt partition has end" << next_end << " < start" << next_start;
|
||||
std::swap( next_start, next_end );
|
||||
}
|
||||
if ( ( *part_it )->roles().has( PartitionRole::Unallocated ) )
|
||||
{
|
||||
cDebug() << ".. ignoring unallocated" << next_start << '-' << next_end;
|
||||
continue;
|
||||
}
|
||||
cDebug() << ".. comparing" << next_start << '-' << next_end;
|
||||
if ( ( next_start > last_currently ) && ( next_start < last_available ) )
|
||||
{
|
||||
cDebug() << " .. shrunk last available to" << next_start;
|
||||
last_available = next_start - 1; // Before that one starts
|
||||
}
|
||||
}
|
||||
|
||||
if ( !( last_available > last_currently ) )
|
||||
{
|
||||
cDebug() << "Partition cannot grow larger.";
|
||||
return 0;
|
||||
}
|
||||
|
||||
qint64 expand = last_available - last_currently; // number of sectors
|
||||
if ( m_atleast.isValid() )
|
||||
{
|
||||
qint64 required = m_atleast.apply( m.first );
|
||||
if ( expand < required )
|
||||
{
|
||||
cDebug() << ".. need to expand by" << required << "but only" << expand << "is available.";
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
qint64 wanted = m_size.apply( expand, m.first->logicalSize() );
|
||||
if ( wanted < expand )
|
||||
{
|
||||
cDebug() << ".. only growing by" << wanted << "instead of full" << expand;
|
||||
last_available -= ( expand - wanted );
|
||||
}
|
||||
|
||||
return last_available;
|
||||
}
|
||||
|
||||
|
||||
Calamares::JobResult
|
||||
ResizeFSJob::exec()
|
||||
{
|
||||
if ( !isValid() )
|
||||
return Calamares::JobResult::error(
|
||||
tr( "Invalid configuration" ),
|
||||
tr( "The file-system resize job has an invalid configuration and will not run." ) );
|
||||
|
||||
// Get KPMCore
|
||||
auto backend_p = CoreBackendManager::self()->backend();
|
||||
if ( backend_p )
|
||||
cDebug() << "KPMCore backend @" << ( void* )backend_p << backend_p->id() << backend_p->version();
|
||||
else
|
||||
{
|
||||
cDebug() << "No KPMCore backend loaded yet";
|
||||
QByteArray backendName = qgetenv( "KPMCORE_BACKEND" );
|
||||
if ( !CoreBackendManager::self()->load( backendName.isEmpty() ? CoreBackendManager::defaultBackendName() : backendName ) )
|
||||
{
|
||||
cWarning() << "Could not load KPMCore backend.";
|
||||
return Calamares::JobResult::error(
|
||||
tr( "KPMCore not Available" ),
|
||||
tr( "Calamares cannot start KPMCore for the file-system resize job." ) );
|
||||
}
|
||||
|
||||
backend_p = CoreBackendManager::self()->backend();
|
||||
}
|
||||
if ( !backend_p )
|
||||
{
|
||||
cWarning() << "Could not load KPMCore backend (2).";
|
||||
return Calamares::JobResult::error(
|
||||
tr( "KPMCore not Available" ),
|
||||
tr( "Calamares cannot start KPMCore for the file-system resize job." ) );
|
||||
}
|
||||
backend_p->initFSSupport(); // Might not be enough, see below
|
||||
|
||||
// Now get the partition and FS we want to work on
|
||||
PartitionMatch m = findPartition( backend_p );
|
||||
if ( !m.first || !m.second )
|
||||
return Calamares::JobResult::error(
|
||||
tr( "Resize Failed" ),
|
||||
!m_fsname.isEmpty() ? tr( "The filesystem %1 could not be found in this system, and cannot be resized." ).arg( m_fsname )
|
||||
: tr( "The device %1 could not be found in this system, and cannot be resized." ).arg( m_devicename ) );
|
||||
|
||||
m.second->fileSystem().init(); // Initialize support for specific FS
|
||||
if ( !ResizeOperation::canGrow( m.second ) )
|
||||
{
|
||||
cDebug() << "canGrow() returned false.";
|
||||
return Calamares::JobResult::error(
|
||||
tr( "Resize Failed" ),
|
||||
!m_fsname.isEmpty() ? tr( "The filesystem %1 cannot be resized." ).arg( m_fsname )
|
||||
: tr( "The device %1 cannot be resized." ).arg( m_devicename ) );
|
||||
}
|
||||
|
||||
qint64 new_end = findGrownEnd( m );
|
||||
cDebug() << "Resize from"
|
||||
<< m.second->firstSector() << '-' << m.second->lastSector()
|
||||
<< '(' << m.second->length() << ')'
|
||||
<< "to -" << new_end;
|
||||
|
||||
if ( new_end < 0 )
|
||||
return Calamares::JobResult::error(
|
||||
tr( "Resize Failed" ),
|
||||
!m_fsname.isEmpty() ? tr( "The filesystem %1 cannot be resized." ).arg( m_fsname )
|
||||
: tr( "The device %1 cannot be resized." ).arg( m_devicename ) );
|
||||
if ( new_end == 0 )
|
||||
{
|
||||
cWarning() << "Resize operation on" << m_fsname << m_devicename
|
||||
<< "skipped as not-useful.";
|
||||
if ( m_required )
|
||||
return Calamares::JobResult::error(
|
||||
tr( "Resize Failed" ),
|
||||
!m_fsname.isEmpty() ? tr( "The filesystem %1 must be resized, but cannot." ).arg( m_fsname )
|
||||
: tr( "The device %1 must be resized, but cannot" ).arg( m_fsname ) );
|
||||
|
||||
return Calamares::JobResult::ok();
|
||||
}
|
||||
|
||||
if ( ( new_end > 0 ) && ( new_end > m.second->lastSector() ) )
|
||||
{
|
||||
ResizeOperation op( *m.first, *m.second, m.second->firstSector(), new_end );
|
||||
Report op_report( nullptr );
|
||||
if ( op.execute( op_report ) )
|
||||
cDebug() << "Resize operation OK.";
|
||||
else
|
||||
{
|
||||
cDebug() << "Resize failed." << op_report.output();
|
||||
return Calamares::JobResult::error(
|
||||
tr( "Resize Failed" ),
|
||||
op_report.toText() );
|
||||
}
|
||||
}
|
||||
|
||||
return Calamares::JobResult::ok();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ResizeFSJob::setConfigurationMap( const QVariantMap& configurationMap )
|
||||
{
|
||||
m_fsname = configurationMap["fs"].toString();
|
||||
m_devicename = configurationMap["dev"].toString();
|
||||
|
||||
if ( m_fsname.isEmpty() && m_devicename.isEmpty() )
|
||||
{
|
||||
cWarning() << "No fs or dev configured for resize.";
|
||||
return;
|
||||
}
|
||||
|
||||
m_size = RelativeSize( configurationMap["size"].toString() );
|
||||
m_atleast = RelativeSize( configurationMap["atleast"].toString() );
|
||||
|
||||
m_required = CalamaresUtils::getBool( configurationMap, "required", false );
|
||||
}
|
||||
|
||||
CALAMARES_PLUGIN_FACTORY_DEFINITION( ResizeFSJobFactory, registerPlugin<ResizeFSJob>(); )
|
122
src/modules/fsresizer/ResizeFSJob.h
Normal file
122
src/modules/fsresizer/ResizeFSJob.h
Normal file
@ -0,0 +1,122 @@
|
||||
/* === This file is part of Calamares - <https://github.com/calamares> ===
|
||||
*
|
||||
* Copyright 2018, Adriaan de Groot <groot@kde.org>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef RESIZEFSJOB_H
|
||||
#define RESIZEFSJOB_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QVariantMap>
|
||||
|
||||
#include <CppJob.h>
|
||||
|
||||
#include <utils/PluginFactory.h>
|
||||
|
||||
#include <PluginDllMacro.h>
|
||||
|
||||
class CoreBackend; // From KPMCore
|
||||
class Device; // From KPMCore
|
||||
class Partition;
|
||||
|
||||
class PLUGINDLLEXPORT ResizeFSJob : public Calamares::CppJob
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
/** @brief Size expressions
|
||||
*
|
||||
* Sizes can be specified in MiB or percent (of the device they
|
||||
* are on). This class handles parsing of such strings from the
|
||||
* config file.
|
||||
*/
|
||||
class RelativeSize
|
||||
{
|
||||
public:
|
||||
RelativeSize();
|
||||
RelativeSize( const QString& );
|
||||
|
||||
enum Unit
|
||||
{
|
||||
None,
|
||||
Percent,
|
||||
Absolute
|
||||
};
|
||||
|
||||
int value() const { return m_value; }
|
||||
Unit unit() const { return m_unit; }
|
||||
|
||||
bool isValid() const
|
||||
{
|
||||
return ( unit() != None ) && ( value() > 0 );
|
||||
}
|
||||
|
||||
/** @brief Apply this size to the number of sectors @p totalSectors .
|
||||
*
|
||||
* Each sector has size @p sectorSize , for converting absolute
|
||||
* sizes in MiB to sector counts.
|
||||
*
|
||||
* For invalid sizes, returns -1.
|
||||
* For absolute sizes, returns the number of sectors needed.
|
||||
* For percent sizes, returns that percent of the number of sectors.
|
||||
*/
|
||||
qint64 apply( qint64 totalSectors, qint64 sectorSize );
|
||||
|
||||
/** @brief Apply this size to the given device.
|
||||
*
|
||||
* Equivalent to apply( d->totalLogical(), d->logicalSize() )
|
||||
*/
|
||||
qint64 apply( Device* d );
|
||||
|
||||
private:
|
||||
int m_value;
|
||||
Unit m_unit;
|
||||
} ;
|
||||
|
||||
explicit ResizeFSJob( QObject* parent = nullptr );
|
||||
virtual ~ResizeFSJob() override;
|
||||
|
||||
QString prettyName() const override;
|
||||
|
||||
Calamares::JobResult exec() override;
|
||||
|
||||
void setConfigurationMap( const QVariantMap& configurationMap ) override;
|
||||
|
||||
/** @brief Is the configuration of this job valid? */
|
||||
bool isValid() const
|
||||
{
|
||||
return ( !m_fsname.isEmpty() || !m_devicename.isEmpty() ) &&
|
||||
m_size.isValid();
|
||||
}
|
||||
|
||||
private:
|
||||
RelativeSize m_size;
|
||||
RelativeSize m_atleast;
|
||||
QString m_fsname; // Either this, or devicename, is set, not both
|
||||
QString m_devicename;
|
||||
bool m_required;
|
||||
|
||||
using PartitionMatch = QPair<Device*, Partition*>;
|
||||
/** @brief Find the configured FS using KPMCore @p backend */
|
||||
PartitionMatch findPartition( CoreBackend* backend );
|
||||
|
||||
/** @brief Return a new end-sector for the given dev-part pair. */
|
||||
qint64 findGrownEnd( PartitionMatch );
|
||||
};
|
||||
|
||||
CALAMARES_PLUGIN_FACTORY_DECLARATION( ResizeFSJobFactory )
|
||||
|
||||
#endif // RESIZEFSJOB_H
|
126
src/modules/fsresizer/Tests.cpp
Normal file
126
src/modules/fsresizer/Tests.cpp
Normal file
@ -0,0 +1,126 @@
|
||||
/* === This file is part of Calamares - <https://github.com/calamares> ===
|
||||
*
|
||||
* Copyright 2017-2018, Adriaan de Groot <groot@kde.org>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Tests.h"
|
||||
|
||||
#include "GlobalStorage.h"
|
||||
#include "JobQueue.h"
|
||||
#include "Settings.h"
|
||||
|
||||
#include "utils/Logger.h"
|
||||
#include "utils/YamlUtils.h"
|
||||
|
||||
#include <yaml-cpp/yaml.h>
|
||||
|
||||
#include <QtTest/QtTest>
|
||||
|
||||
#include <QFileInfo>
|
||||
#include <QStringList>
|
||||
|
||||
#define private public
|
||||
#include "ResizeFSJob.h"
|
||||
#undef private
|
||||
|
||||
QTEST_GUILESS_MAIN( FSResizerTests )
|
||||
|
||||
FSResizerTests::FSResizerTests()
|
||||
{
|
||||
}
|
||||
|
||||
FSResizerTests::~FSResizerTests()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
FSResizerTests::initTestCase()
|
||||
{
|
||||
}
|
||||
|
||||
void FSResizerTests::testConfigurationRobust()
|
||||
{
|
||||
ResizeFSJob j;
|
||||
|
||||
// Empty config
|
||||
j.setConfigurationMap( QVariantMap() );
|
||||
QVERIFY( j.m_fsname.isEmpty() );
|
||||
QVERIFY( j.m_devicename.isEmpty() );
|
||||
QCOMPARE( j.m_size.unit(), ResizeFSJob::RelativeSize::None );
|
||||
QCOMPARE( j.m_atleast.unit(), ResizeFSJob::RelativeSize::None );
|
||||
|
||||
// Config is missing fs and dev, so it isn't valid
|
||||
YAML::Node doc0 = YAML::Load( R"(---
|
||||
size: 100%
|
||||
atleast: 600MiB
|
||||
)" );
|
||||
j.setConfigurationMap( CalamaresUtils::yamlMapToVariant( doc0 ).toMap() );
|
||||
QVERIFY( j.m_fsname.isEmpty() );
|
||||
QVERIFY( j.m_devicename.isEmpty() );
|
||||
QCOMPARE( j.m_size.unit(), ResizeFSJob::RelativeSize::None );
|
||||
QCOMPARE( j.m_atleast.unit(), ResizeFSJob::RelativeSize::None );
|
||||
QCOMPARE( j.m_size.value(), 0 );
|
||||
QCOMPARE( j.m_atleast.value(), 0 );
|
||||
}
|
||||
|
||||
void FSResizerTests::testConfigurationValues()
|
||||
{
|
||||
ResizeFSJob j;
|
||||
|
||||
// Check both
|
||||
YAML::Node doc0 = YAML::Load( R"(---
|
||||
fs: /
|
||||
size: 100%
|
||||
atleast: 600MiB
|
||||
)" );
|
||||
j.setConfigurationMap( CalamaresUtils::yamlMapToVariant( doc0 ).toMap() );
|
||||
QVERIFY( !j.m_fsname.isEmpty() );
|
||||
QVERIFY( j.m_devicename.isEmpty() );
|
||||
QCOMPARE( j.m_size.unit(), ResizeFSJob::RelativeSize::Percent );
|
||||
QCOMPARE( j.m_atleast.unit(), ResizeFSJob::RelativeSize::Absolute );
|
||||
QCOMPARE( j.m_size.value(), 100 );
|
||||
QCOMPARE( j.m_atleast.value(), 600 );
|
||||
|
||||
// Silly config
|
||||
doc0 = YAML::Load( R"(---
|
||||
fs: /
|
||||
dev: /dev/m00
|
||||
size: 72 MiB
|
||||
atleast: 127 %
|
||||
)" );
|
||||
j.setConfigurationMap( CalamaresUtils::yamlMapToVariant( doc0 ).toMap() );
|
||||
QVERIFY( !j.m_fsname.isEmpty() );
|
||||
QVERIFY( !j.m_devicename.isEmpty() );
|
||||
QCOMPARE( j.m_size.unit(), ResizeFSJob::RelativeSize::Absolute );
|
||||
QCOMPARE( j.m_atleast.unit(), ResizeFSJob::RelativeSize::Percent );
|
||||
QCOMPARE( j.m_size.value(), 72 );
|
||||
QCOMPARE( j.m_atleast.value(), 127 );
|
||||
|
||||
// Silly config
|
||||
doc0 = YAML::Load( R"(---
|
||||
fs: /
|
||||
# dev: /dev/m00
|
||||
size: 71MiB
|
||||
# atleast: 127%
|
||||
)" );
|
||||
j.setConfigurationMap( CalamaresUtils::yamlMapToVariant( doc0 ).toMap() );
|
||||
QVERIFY( !j.m_fsname.isEmpty() );
|
||||
QVERIFY( j.m_devicename.isEmpty() );
|
||||
QCOMPARE( j.m_size.unit(), ResizeFSJob::RelativeSize::Absolute );
|
||||
QCOMPARE( j.m_atleast.unit(), ResizeFSJob::RelativeSize::None );
|
||||
QCOMPARE( j.m_size.value(), 71 );
|
||||
QCOMPARE( j.m_atleast.value(), 0 );
|
||||
}
|
39
src/modules/fsresizer/Tests.h
Normal file
39
src/modules/fsresizer/Tests.h
Normal file
@ -0,0 +1,39 @@
|
||||
/* === This file is part of Calamares - <https://github.com/calamares> ===
|
||||
*
|
||||
* Copyright 2018, Adriaan de Groot <groot@kde.org>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TESTS_H
|
||||
#define TESTS_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class FSResizerTests : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
FSResizerTests();
|
||||
~FSResizerTests() override;
|
||||
|
||||
private Q_SLOTS:
|
||||
void initTestCase();
|
||||
// Can handle missing values
|
||||
void testConfigurationRobust();
|
||||
// Can parse % and MiB values
|
||||
void testConfigurationValues();
|
||||
};
|
||||
|
||||
#endif
|
49
src/modules/fsresizer/fsresizer.conf
Normal file
49
src/modules/fsresizer/fsresizer.conf
Normal file
@ -0,0 +1,49 @@
|
||||
# Module that resizes a single FS to fill the entire (rest) of
|
||||
# a device. This is used in OEM situations where an image is
|
||||
# flashed onto an SD card (or similar) and used to boot a device,
|
||||
# after which the FS should expand to fill the SD card.
|
||||
#
|
||||
# Example: a distro produces a 6GiB large image that is
|
||||
# written to an 8GiB SD card; the FS should expand to take
|
||||
# advantage of the unused 2GiB. The FS should expand much
|
||||
# more if the same image is written to a 16GiB card.
|
||||
---
|
||||
|
||||
# Which FS needs to be grown? Choose one way to identify it:
|
||||
# - *fs* names a mount point which should already be mounted
|
||||
# in the system.
|
||||
# - *dev* names a device
|
||||
fs: /
|
||||
# dev: /dev/mmcblk0p1
|
||||
|
||||
# How much of the total remaining space should the FS use?
|
||||
# The only sensible amount is "all of it". The value is
|
||||
# in percent, so set it to 100. Perhaps a fixed size is
|
||||
# needed (that would be weird though, since you don't know
|
||||
# how big the card is), use MiB as suffix in that case.
|
||||
# If missing, then it's assumed to be 0, and no resizing
|
||||
# will happen.
|
||||
#
|
||||
# Percentages apply to **available space**.
|
||||
size: 100%
|
||||
|
||||
# Resizing might not be worth it, though. Set the minimum
|
||||
# that it must grow; if it cannot grow that much, the
|
||||
# resizing is skipped. Can be in percentage or absolute
|
||||
# size, as above. If missing, then it's assumed to be 0,
|
||||
# which means resizing is always worthwhile.
|
||||
#
|
||||
# If *atleast* is not zero, then the setting *required*,
|
||||
# below, becomes relevant.
|
||||
#
|
||||
# Percentages apply to **total device size**.
|
||||
#atleast: 1000MiB
|
||||
|
||||
# When *atleast* is not zero, then the resize may be
|
||||
# recommended (the default) or **required**. If the
|
||||
# resize is required and cannot be carried out (because
|
||||
# there's not enough space), then that is a fatal
|
||||
# error for the installer. By default, resize is only
|
||||
# recommended and it is not an error for no resize to be
|
||||
# carried out.
|
||||
required: false
|
@ -65,6 +65,8 @@ SetKeyboardLayoutJob::prettyName() const
|
||||
QString
|
||||
SetKeyboardLayoutJob::findConvertedKeymap( const QString& convertedKeymapPath ) const
|
||||
{
|
||||
cDebug() << "Looking for converted keymap in" << convertedKeymapPath;
|
||||
|
||||
// No search path supplied, assume the distribution does not provide
|
||||
// converted keymaps
|
||||
if ( convertedKeymapPath.isEmpty() )
|
||||
@ -76,8 +78,7 @@ SetKeyboardLayoutJob::findConvertedKeymap( const QString& convertedKeymapPath )
|
||||
if ( convertedKeymapDir.exists( name + ".map" )
|
||||
|| convertedKeymapDir.exists( name + ".map.gz" ) )
|
||||
{
|
||||
cDebug() << "Found converted keymap" << name;
|
||||
|
||||
cDebug() << ".. Found converted keymap" << name;
|
||||
return name;
|
||||
}
|
||||
|
||||
@ -88,6 +89,8 @@ SetKeyboardLayoutJob::findConvertedKeymap( const QString& convertedKeymapPath )
|
||||
QString
|
||||
SetKeyboardLayoutJob::findLegacyKeymap() const
|
||||
{
|
||||
cDebug() << "Looking for legacy keymap in QRC";
|
||||
|
||||
int bestMatching = 0;
|
||||
QString name;
|
||||
|
||||
@ -137,7 +140,7 @@ SetKeyboardLayoutJob::findLegacyKeymap() const
|
||||
// The best matching entry so far, then let's save that
|
||||
if ( matching >= qMax( bestMatching, 1 ) )
|
||||
{
|
||||
cDebug() << "Found legacy keymap" << mapping[0]
|
||||
cDebug() << ".. Found legacy keymap" << mapping[0]
|
||||
<< "with score" << matching;
|
||||
|
||||
if ( matching > bestMatching )
|
||||
|
@ -6,6 +6,9 @@
|
||||
# This is the version from 534644b7be7b240eb0fbbe06e20cbecbe8206767,
|
||||
# committed 2015-01-22 01:07:24 .
|
||||
#
|
||||
# Updates:
|
||||
# - 2018-09-26 Added "Austrian" keyboard (de at). Issue #1035
|
||||
#
|
||||
# Generated from system-config-keyboard's model list
|
||||
# consolelayout xlayout xmodel xvariant xoptions
|
||||
sg ch pc105 de_nodeadkeys terminate:ctrl_alt_bksp
|
||||
@ -14,8 +17,8 @@ mk-utf mk,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scrol
|
||||
trq tr pc105 - terminate:ctrl_alt_bksp
|
||||
uk gb pc105 - terminate:ctrl_alt_bksp
|
||||
is-latin1 is pc105 - terminate:ctrl_alt_bksp
|
||||
at de pc105 - terminate:ctrl_alt_bksp
|
||||
de de pc105 - terminate:ctrl_alt_bksp
|
||||
de at pc105 - terminate:ctrl_alt_bksp
|
||||
la-latin1 latam pc105 - terminate:ctrl_alt_bksp
|
||||
us us pc105+inet - terminate:ctrl_alt_bksp
|
||||
ko kr pc105 - terminate:ctrl_alt_bksp
|
||||
|
@ -1,9 +1,3 @@
|
||||
find_package(ECM ${ECM_VERSION} NO_MODULE)
|
||||
if( ECM_FOUND AND BUILD_TESTING )
|
||||
include( ECMAddTests )
|
||||
find_package( Qt5 COMPONENTS Core Test REQUIRED )
|
||||
endif()
|
||||
|
||||
# When debugging the timezone widget, add this debugging definition
|
||||
# to have a debugging-friendly timezone widget, debug logging,
|
||||
# and no intrusive timezone-setting while clicking around.
|
||||
|
@ -134,7 +134,7 @@ def run():
|
||||
if os.path.exists(target_locale_gen_bak):
|
||||
shutil.copy2(target_locale_gen_bak, target_locale_gen)
|
||||
libcalamares.utils.debug("Restored backup {!s} -> {!s}"
|
||||
.format(target_locale_gen_bak).format(target_locale_gen))
|
||||
.format(target_locale_gen_bak, target_locale_gen))
|
||||
|
||||
# run locale-gen if detected; this *will* cause an exception
|
||||
# if the live system has locale.gen, but the target does not:
|
||||
|
@ -113,28 +113,32 @@ QList< Device* > getDevices( DeviceType which, qint64 minimumSize )
|
||||
|
||||
// Remove the device which contains / from the list
|
||||
for ( DeviceList::iterator it = devices.begin(); it != devices.end(); )
|
||||
if ( ! ( *it ) ||
|
||||
( *it )->deviceNode().startsWith( "/dev/zram" )
|
||||
if ( !( *it ) )
|
||||
{
|
||||
cDebug() << " .. Skipping nullptr device";
|
||||
it = erase( devices, it);
|
||||
}
|
||||
else if ( ( *it )->deviceNode().startsWith( "/dev/zram" )
|
||||
)
|
||||
{
|
||||
cDebug() << " .. Removing zram" << it;
|
||||
it = erase(devices, it );
|
||||
it = erase( devices, it );
|
||||
|
||||
}
|
||||
else if ( writableOnly && hasRootPartition( *it ) )
|
||||
{
|
||||
cDebug() << " .. Removing device with root filesystem (/) on it" << it;
|
||||
it = erase(devices, it );
|
||||
it = erase( devices, it );
|
||||
}
|
||||
else if ( writableOnly && isIso9660( *it ) )
|
||||
{
|
||||
cDebug() << " .. Removing device with iso9660 filesystem (probably a CD) on it" << it;
|
||||
it = erase(devices, it );
|
||||
it = erase( devices, it );
|
||||
}
|
||||
else if ( (minimumSize >= 0) && !( (*it)->capacity() > minimumSize ) )
|
||||
{
|
||||
cDebug() << " .. Removing too-small" << it;
|
||||
it = erase(devices, it );
|
||||
it = erase( devices, it );
|
||||
}
|
||||
else
|
||||
++it;
|
||||
|
@ -509,18 +509,8 @@ PartitionCoreModule::jobs() const
|
||||
lst << info->jobs;
|
||||
devices << info->device.data();
|
||||
}
|
||||
cDebug() << "Creating FillGlobalStorageJob with bootLoader path" << m_bootLoaderInstallPath;
|
||||
lst << Calamares::job_ptr( new FillGlobalStorageJob( devices, m_bootLoaderInstallPath ) );
|
||||
|
||||
|
||||
QStringList jobsDebug;
|
||||
foreach ( auto job, lst )
|
||||
jobsDebug.append( job->prettyName() );
|
||||
|
||||
cDebug() << "PartitionCodeModule has been asked for jobs. About to return:";
|
||||
for ( const auto item: jobsDebug )
|
||||
cDebug() << " .." << item;
|
||||
|
||||
return lst;
|
||||
}
|
||||
|
||||
@ -573,9 +563,9 @@ PartitionCoreModule::dumpQueue() const
|
||||
cDebug() << "# Queue:";
|
||||
for ( auto info : m_deviceInfos )
|
||||
{
|
||||
cDebug() << " .. Device:" << info->device->name();
|
||||
cDebug() << "## Device:" << info->device->name();
|
||||
for ( auto job : info->jobs )
|
||||
cDebug() << " .." << job->prettyName();
|
||||
cDebug() << "-" << job->prettyName();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
* along with Calamares. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <core/PartitionIterator.h>
|
||||
#include "PartitionIterator.h"
|
||||
|
||||
// KPMcore
|
||||
#include <kpmcore/core/device.h>
|
||||
|
@ -1161,6 +1161,13 @@ force_uncheck(QButtonGroup* grp, PrettyRadioButton* button)
|
||||
grp->setExclusive( true );
|
||||
}
|
||||
|
||||
static inline QDebug&
|
||||
operator <<( QDebug& s, PartitionIterator& it )
|
||||
{
|
||||
s << ( ( *it ) ? ( *it )->deviceNode() : QString( "<null device>" ) );
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief ChoicePage::setupActions happens every time a new Device* is selected in the
|
||||
* device picker. Sets up the text and visibility of the partitioning actions based
|
||||
@ -1174,6 +1181,9 @@ ChoicePage::setupActions()
|
||||
OsproberEntryList osproberEntriesForCurrentDevice =
|
||||
getOsproberEntriesForDevice( currentDevice );
|
||||
|
||||
cDebug() << "Setting up actions for" << currentDevice->deviceNode()
|
||||
<< "with" << osproberEntriesForCurrentDevice.count() << "entries.";
|
||||
|
||||
if ( currentDevice->partitionTable() )
|
||||
m_deviceInfoWidget->setPartitionTableType( currentDevice->partitionTable()->type() );
|
||||
else
|
||||
@ -1190,18 +1200,30 @@ ChoicePage::setupActions()
|
||||
#ifdef WITH_KPMCOREGT33
|
||||
if ( currentDevice->type() == Device::Type::SoftwareRAID_Device &&
|
||||
static_cast< SoftwareRAID* >(currentDevice)->status() == SoftwareRAID::Status::Inactive )
|
||||
{
|
||||
cDebug() << ".. part of an inactive RAID device";
|
||||
isInactiveRAID = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
for ( auto it = PartitionIterator::begin( currentDevice );
|
||||
it != PartitionIterator::end( currentDevice ); ++it )
|
||||
{
|
||||
if ( PartUtils::canBeResized( *it ) )
|
||||
{
|
||||
cDebug() << ".. contains resizable" << it;
|
||||
atLeastOneCanBeResized = true;
|
||||
}
|
||||
if ( PartUtils::canBeReplaced( *it ) )
|
||||
{
|
||||
cDebug() << ".. contains replacable" << it;
|
||||
atLeastOneCanBeReplaced = true;
|
||||
}
|
||||
if ( (*it)->isMounted() )
|
||||
{
|
||||
cDebug() << ".. contains mounted" << it;
|
||||
atLeastOneIsMounted = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( osproberEntriesForCurrentDevice.count() == 0 )
|
||||
@ -1318,7 +1340,12 @@ ChoicePage::setupActions()
|
||||
if ( !atLeastOneIsMounted && !isInactiveRAID )
|
||||
m_eraseButton->show(); // None mounted
|
||||
else
|
||||
{
|
||||
cDebug() << "Erase button suppressed"
|
||||
<< "mount?" << atLeastOneIsMounted
|
||||
<< "raid?" << isInactiveRAID;
|
||||
force_uncheck( m_grp, m_eraseButton );
|
||||
}
|
||||
|
||||
bool isEfi = PartUtils::isEfiSystem();
|
||||
bool efiSystemPartitionFound = !m_core->efiSystemPartitions().isEmpty();
|
||||
|
@ -20,6 +20,8 @@
|
||||
|
||||
#include "jobs/CreatePartitionTableJob.h"
|
||||
|
||||
#include "core/PartitionIterator.h"
|
||||
|
||||
#include "utils/Logger.h"
|
||||
|
||||
// KPMcore
|
||||
@ -65,6 +67,14 @@ CreatePartitionTableJob::prettyStatusMessage() const
|
||||
}
|
||||
|
||||
|
||||
static inline QDebug&
|
||||
operator <<( QDebug& s, PartitionIterator& it )
|
||||
{
|
||||
s << ( ( *it ) ? ( *it )->deviceNode() : QString( "<null device>" ) );
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
Calamares::JobResult
|
||||
CreatePartitionTableJob::exec()
|
||||
{
|
||||
@ -73,33 +83,28 @@ CreatePartitionTableJob::exec()
|
||||
|
||||
PartitionTable* table = m_device->partitionTable();
|
||||
cDebug() << "Creating new partition table of type" << table->typeName()
|
||||
<< " - Uncommitted yet: " << table;
|
||||
<< ", uncommitted yet:";
|
||||
|
||||
QProcess lsblk;
|
||||
lsblk.setProgram( "lsblk" );
|
||||
lsblk.setProcessChannelMode( QProcess::MergedChannels );
|
||||
lsblk.start();
|
||||
lsblk.waitForFinished();
|
||||
if ( Logger::logLevelEnabled( Logger::LOGDEBUG ) )
|
||||
{
|
||||
for ( auto it = PartitionIterator::begin( table );
|
||||
it != PartitionIterator::end( table ); ++it )
|
||||
cDebug() << *it;
|
||||
|
||||
QByteArray byte = lsblk.readAllStandardOutput();
|
||||
QStringList lines = QString(byte).split(("\n"),QString::SkipEmptyParts);
|
||||
cDebug() << "CreatePartitionTableJob asked for lsblk output:";
|
||||
QProcess lsblk;
|
||||
lsblk.setProgram( "lsblk" );
|
||||
lsblk.setProcessChannelMode( QProcess::MergedChannels );
|
||||
lsblk.start();
|
||||
lsblk.waitForFinished();
|
||||
cDebug() << "lsblk:\n" << lsblk.readAllStandardOutput();
|
||||
|
||||
for (const auto line: lines)
|
||||
cDebug() << " .." << line;
|
||||
|
||||
QProcess mount;
|
||||
mount.setProgram( "mount" );
|
||||
mount.setProcessChannelMode( QProcess::MergedChannels );
|
||||
mount.start();
|
||||
mount.waitForFinished();
|
||||
|
||||
QByteArray mbyte = mount.readAllStandardOutput();
|
||||
QStringList mlines = QString(mbyte).split(("\n"),QString::SkipEmptyParts);
|
||||
cDebug() << "CreatePartitionTableJob asked for mount output:";
|
||||
|
||||
for (const auto mline: mlines)
|
||||
cDebug() << " .." << mline;
|
||||
QProcess mount;
|
||||
mount.setProgram( "mount" );
|
||||
mount.setProcessChannelMode( QProcess::MergedChannels );
|
||||
mount.start();
|
||||
mount.waitForFinished();
|
||||
cDebug() << "mount:\n" << mount.readAllStandardOutput();
|
||||
}
|
||||
|
||||
CreatePartitionTableOperation op(*m_device, table);
|
||||
op.setStatus(Operation::StatusRunning);
|
||||
|
@ -56,9 +56,12 @@ findPartitionUuids( QList < Device* > devices )
|
||||
QString path = p->partitionPath();
|
||||
QString uuid = p->fileSystem().readUUID( p->partitionPath() );
|
||||
hash.insert( path, uuid );
|
||||
cDebug() << ".. added path=" << path << "UUID=" << uuid;
|
||||
}
|
||||
}
|
||||
cDebug() << hash;
|
||||
|
||||
if ( hash.isEmpty() )
|
||||
cDebug() << ".. no UUIDs found.";
|
||||
return hash;
|
||||
}
|
||||
|
||||
@ -90,10 +93,16 @@ mapForPartition( Partition* partition, const QString& uuid )
|
||||
dynamic_cast< FS::luks& >( partition->fileSystem() ).innerFS() )
|
||||
map[ "fs" ] = dynamic_cast< FS::luks& >( partition->fileSystem() ).innerFS()->name();
|
||||
map[ "uuid" ] = uuid;
|
||||
cDebug() << partition->partitionPath()
|
||||
<< "mtpoint:" << PartitionInfo::mountPoint( partition )
|
||||
<< "fs:" << map[ "fs" ] << '(' << map[ "fsName" ] << ')'
|
||||
<< uuid;
|
||||
|
||||
// Debugging for inside the loop in createPartitionList(),
|
||||
// so indent a bit
|
||||
Logger::CLog deb = cDebug();
|
||||
using TR = Logger::DebugRow<const char *const, const QString&>;
|
||||
deb << " .. mapping for" << partition->partitionPath() << partition->deviceNode()
|
||||
<< TR( "mtpoint:", PartitionInfo::mountPoint( partition ) )
|
||||
<< TR( "fs:", map[ "fs" ].toString() )
|
||||
<< TR( "fsname", map[ "fsName" ].toString() )
|
||||
<< TR( "uuid", uuid );
|
||||
|
||||
if ( partition->roles().has( PartitionRole::Luks ) )
|
||||
{
|
||||
@ -104,7 +113,7 @@ mapForPartition( Partition* partition, const QString& uuid )
|
||||
map[ "luksMapperName" ] = luksFs->mapperName().split( "/" ).last();
|
||||
map[ "luksUuid" ] = getLuksUuid( partition->partitionPath() );
|
||||
map[ "luksPassphrase" ] = luksFs->passphrase();
|
||||
cDebug() << "luksMapperName:" << map[ "luksMapperName" ];
|
||||
deb << TR( "luksMapperName:", map[ "luksMapperName" ].toString() );
|
||||
}
|
||||
}
|
||||
|
||||
@ -215,9 +224,11 @@ FillGlobalStorageJob::createPartitionList() const
|
||||
cDebug() << "Writing to GlobalStorage[\"partitions\"]";
|
||||
for ( auto device : m_devices )
|
||||
{
|
||||
cDebug() << ".. partitions on" << device->deviceNode();
|
||||
for ( auto it = PartitionIterator::begin( device );
|
||||
it != PartitionIterator::end( device ); ++it )
|
||||
{
|
||||
// Debug-logging is done when creating the map
|
||||
lst << mapForPartition( *it, hash.value( ( *it )->partitionPath() ) );
|
||||
}
|
||||
}
|
||||
|
@ -132,6 +132,10 @@ SetPartFlagsJob::prettyStatusMessage() const
|
||||
Calamares::JobResult
|
||||
SetPartFlagsJob::exec()
|
||||
{
|
||||
cDebug() << "Setting flags on" << m_device->deviceNode()
|
||||
<< "partition" << partition()->deviceNode()
|
||||
<< "to" << m_flags;
|
||||
|
||||
Report report ( nullptr );
|
||||
SetPartFlagsOperation op( *m_device, *partition(), m_flags );
|
||||
op.setStatus( Operation::StatusRunning );
|
||||
|
@ -1,6 +1,4 @@
|
||||
find_package( Qt5 COMPONENTS Gui Test REQUIRED )
|
||||
|
||||
include( ECMAddTests )
|
||||
find_package( Qt5 COMPONENTS Gui REQUIRED )
|
||||
|
||||
set( PartitionModule_SOURCE_DIR .. )
|
||||
|
||||
@ -23,13 +21,15 @@ include_directories(
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
||||
ecm_add_test( ${partitionjobtests_SRCS}
|
||||
TEST_NAME partitionjobtests
|
||||
LINK_LIBRARIES
|
||||
${CALAMARES_LIBRARIES}
|
||||
kpmcore
|
||||
Qt5::Core
|
||||
Qt5::Test
|
||||
)
|
||||
if( ECM_FOUND AND BUILD_TESTING )
|
||||
ecm_add_test( ${partitionjobtests_SRCS}
|
||||
TEST_NAME partitionjobtests
|
||||
LINK_LIBRARIES
|
||||
${CALAMARES_LIBRARIES}
|
||||
kpmcore
|
||||
Qt5::Core
|
||||
Qt5::Test
|
||||
)
|
||||
|
||||
set_target_properties( partitionjobtests PROPERTIES AUTOMOC TRUE )
|
||||
set_target_properties( partitionjobtests PROPERTIES AUTOMOC TRUE )
|
||||
endif()
|
||||
|
@ -4,6 +4,7 @@ calamares_add_plugin( preservefiles
|
||||
TYPE job
|
||||
EXPORT_MACRO PLUGINDLLEXPORT_PRO
|
||||
SOURCES
|
||||
permissions.cpp
|
||||
PreserveFiles.cpp
|
||||
LINK_PRIVATE_LIBRARIES
|
||||
calamares
|
||||
|
@ -18,6 +18,8 @@
|
||||
|
||||
#include "PreserveFiles.h"
|
||||
|
||||
#include "permissions.h"
|
||||
|
||||
#include "CalamaresVersion.h"
|
||||
#include "JobQueue.h"
|
||||
#include "GlobalStorage.h"
|
||||
@ -83,6 +85,38 @@ PreserveFiles::prettyName() const
|
||||
return tr( "Saving files for later ..." );
|
||||
}
|
||||
|
||||
static bool
|
||||
copy_file( const QString& source, const QString& dest )
|
||||
{
|
||||
QFile sourcef( source );
|
||||
if ( !sourcef.open( QFile::ReadOnly ) )
|
||||
{
|
||||
cWarning() << "Could not read" << source;
|
||||
return false;
|
||||
}
|
||||
|
||||
QFile destf( dest );
|
||||
if ( !destf.open( QFile::WriteOnly ) )
|
||||
{
|
||||
sourcef.close();
|
||||
cWarning() << "Could not open" << destf.fileName() << "for writing; could not copy" << source;
|
||||
return false;
|
||||
}
|
||||
|
||||
QByteArray b;
|
||||
do
|
||||
{
|
||||
b = sourcef.read( 1_MiB );
|
||||
destf.write( b );
|
||||
}
|
||||
while ( b.count() > 0 );
|
||||
|
||||
sourcef.close();
|
||||
destf.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Calamares::JobResult PreserveFiles::exec()
|
||||
{
|
||||
if ( m_items.isEmpty() )
|
||||
@ -96,7 +130,8 @@ Calamares::JobResult PreserveFiles::exec()
|
||||
for ( const auto& it : m_items )
|
||||
{
|
||||
QString source = it.source;
|
||||
QString dest = prefix + atReplacements( it.dest );
|
||||
QString bare_dest = atReplacements( it.dest );
|
||||
QString dest = prefix + bare_dest;
|
||||
|
||||
if ( it.type == ItemType::Log )
|
||||
source = Logger::logFile();
|
||||
@ -111,32 +146,29 @@ Calamares::JobResult PreserveFiles::exec()
|
||||
cWarning() << "Skipping unnamed source file for" << dest;
|
||||
else
|
||||
{
|
||||
QFile sourcef( source );
|
||||
if ( !sourcef.open( QFile::ReadOnly ) )
|
||||
if ( copy_file( source, dest ) )
|
||||
{
|
||||
cWarning() << "Could not read" << source;
|
||||
continue;
|
||||
if ( it.perm.isValid() )
|
||||
{
|
||||
auto s_p = CalamaresUtils::System::instance();
|
||||
|
||||
int r;
|
||||
|
||||
r = s_p->targetEnvCall( QStringList{ "chown", it.perm.username(), bare_dest } );
|
||||
if ( r )
|
||||
cWarning() << "Could not chown target" << bare_dest;
|
||||
|
||||
r = s_p->targetEnvCall( QStringList{ "chgrp", it.perm.group(), bare_dest } );
|
||||
if ( r )
|
||||
cWarning() << "Could not chgrp target" << bare_dest;
|
||||
|
||||
r = s_p->targetEnvCall( QStringList{ "chmod", it.perm.octal(), bare_dest } );
|
||||
if ( r )
|
||||
cWarning() << "Could not chmod target" << bare_dest;
|
||||
}
|
||||
|
||||
++count;
|
||||
}
|
||||
|
||||
QFile destf( dest );
|
||||
if ( !destf.open( QFile::WriteOnly ) )
|
||||
{
|
||||
sourcef.close();
|
||||
cWarning() << "Could not open" << destf.fileName() << "for writing; could not copy" << source;
|
||||
continue;
|
||||
}
|
||||
|
||||
QByteArray b;
|
||||
do
|
||||
{
|
||||
b = sourcef.read( 1_MiB );
|
||||
destf.write( b );
|
||||
}
|
||||
while ( b.count() > 0 );
|
||||
|
||||
sourcef.close();
|
||||
destf.close();
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
@ -160,6 +192,10 @@ void PreserveFiles::setConfigurationMap(const QVariantMap& configurationMap)
|
||||
return;
|
||||
}
|
||||
|
||||
QString defaultPermissions = configurationMap[ "perm" ].toString();
|
||||
if ( defaultPermissions.isEmpty() )
|
||||
defaultPermissions = QStringLiteral( "root:root:0400" );
|
||||
|
||||
QVariantList l = files.toList();
|
||||
unsigned int c = 0;
|
||||
for ( const auto& li : l )
|
||||
@ -168,7 +204,7 @@ void PreserveFiles::setConfigurationMap(const QVariantMap& configurationMap)
|
||||
{
|
||||
QString filename = li.toString();
|
||||
if ( !filename.isEmpty() )
|
||||
m_items.append( Item{ filename, filename, ItemType::Path } );
|
||||
m_items.append( Item{ filename, filename, Permissions( defaultPermissions ), ItemType::Path } );
|
||||
else
|
||||
cDebug() << "Empty filename for preservefiles, item" << c;
|
||||
}
|
||||
@ -181,6 +217,9 @@ void PreserveFiles::setConfigurationMap(const QVariantMap& configurationMap)
|
||||
( from == "log" ) ? ItemType::Log :
|
||||
( from == "config" ) ? ItemType::Config :
|
||||
ItemType::None;
|
||||
QString perm = map[ "perm" ].toString();
|
||||
if ( perm.isEmpty() )
|
||||
perm = defaultPermissions;
|
||||
|
||||
if ( dest.isEmpty() )
|
||||
{
|
||||
@ -192,7 +231,7 @@ void PreserveFiles::setConfigurationMap(const QVariantMap& configurationMap)
|
||||
}
|
||||
else
|
||||
{
|
||||
m_items.append( Item{ QString(), dest, t } );
|
||||
m_items.append( Item{ QString(), dest, Permissions( perm ), t } );
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -24,11 +24,11 @@
|
||||
#include <QVariantMap>
|
||||
|
||||
#include "CppJob.h"
|
||||
#include "PluginDllMacro.h"
|
||||
|
||||
#include "utils/PluginFactory.h"
|
||||
|
||||
#include "PluginDllMacro.h"
|
||||
|
||||
#include "permissions.h"
|
||||
|
||||
class PLUGINDLLEXPORT PreserveFiles : public Calamares::CppJob
|
||||
{
|
||||
@ -46,6 +46,7 @@ class PLUGINDLLEXPORT PreserveFiles : public Calamares::CppJob
|
||||
{
|
||||
QString source;
|
||||
QString dest;
|
||||
Permissions perm;
|
||||
ItemType type;
|
||||
} ;
|
||||
|
||||
|
75
src/modules/preservefiles/permissions.cpp
Normal file
75
src/modules/preservefiles/permissions.cpp
Normal file
@ -0,0 +1,75 @@
|
||||
/* === This file is part of Calamares - <https://github.com/calamares> ===
|
||||
*
|
||||
* Copyright (C) 2018 Scott Harvey <scott@spharvey.me>
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include "permissions.h"
|
||||
|
||||
Permissions::Permissions() :
|
||||
m_username(),
|
||||
m_group(),
|
||||
m_valid(false),
|
||||
m_value(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Permissions::Permissions(QString p) : Permissions()
|
||||
{
|
||||
parsePermissions(p);
|
||||
}
|
||||
|
||||
void Permissions::parsePermissions(const QString& p) {
|
||||
|
||||
QStringList segments = p.split(":");
|
||||
|
||||
if (segments.length() != 3) {
|
||||
m_valid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (segments[0].isEmpty() || segments[1].isEmpty()) {
|
||||
m_valid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
bool ok;
|
||||
int octal = segments[2].toInt(&ok, 8);
|
||||
if (!ok || octal == 0) {
|
||||
m_valid = false;
|
||||
return;
|
||||
} else {
|
||||
m_value = octal;
|
||||
}
|
||||
|
||||
// We have exactly three segments and the third is valid octal,
|
||||
// so we can declare the string valid and set the user and group names
|
||||
m_valid = true;
|
||||
m_username = segments[0];
|
||||
m_group = segments[1];
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
62
src/modules/preservefiles/permissions.h
Normal file
62
src/modules/preservefiles/permissions.h
Normal file
@ -0,0 +1,62 @@
|
||||
/* === This file is part of Calamares - <https://github.com/calamares> ===
|
||||
*
|
||||
* Copyright (C) 2018 Scott Harvey <scott@spharvey.me>
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PERMISSIONS_H
|
||||
#define PERMISSIONS_H
|
||||
|
||||
#include <QString>
|
||||
|
||||
/**
|
||||
* @brief The Permissions class takes a QString @p in the form of
|
||||
* <user>:<group>:<permissions>, checks it for validity, and makes the three
|
||||
* components available indivdually.
|
||||
*/
|
||||
class Permissions
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
/** @brief Constructor
|
||||
*
|
||||
* Splits the string @p at the colon (":") into separate elements for
|
||||
* <user>, <group>, and <value> (permissions), where <value> is returned as
|
||||
* an **octal** integer.
|
||||
*/
|
||||
Permissions(QString p);
|
||||
|
||||
/** @brief Default constructor of an invalid Permissions. */
|
||||
Permissions();
|
||||
|
||||
bool isValid() const { return m_valid; }
|
||||
QString username() const { return m_username; }
|
||||
QString group() const { return m_group; }
|
||||
int value() const { return m_value; }
|
||||
QString octal() const { return QString::number( m_value, 8 ); }
|
||||
|
||||
private:
|
||||
void parsePermissions(QString const &p);
|
||||
|
||||
QString m_username;
|
||||
QString m_group;
|
||||
bool m_valid;
|
||||
int m_value;
|
||||
|
||||
};
|
||||
|
||||
#endif // PERMISSIONS_H
|
@ -9,13 +9,18 @@
|
||||
# as the source).
|
||||
# - a map with a *dest* key. The *dest* value is a path interpreted in the
|
||||
# target system (if dontChroot is true, in the host system). Relative paths
|
||||
# are not recommended. There are two possible other keys in the map:
|
||||
# are not recommended. There are three possible other keys in the map:
|
||||
# - *from*, which must have one of the values, below; it is used to
|
||||
# preserve files whose pathname is known to Calamares internally.
|
||||
# - *src*, to refer to a path interpreted in the host system. Relative
|
||||
# paths are not recommended, and are interpreted relative to where
|
||||
# Calamares is being run.
|
||||
# Only one of the two other keys (either *from* or *src*) may be set.
|
||||
# - *perm*, is a colon-separated tuple of <user>:<group>:<mode>
|
||||
# where <mode> is in octal (e.g. 4777 for wide-open, 0400 for read-only
|
||||
# by owner). If set, the file's ownership and permissions are set to
|
||||
# those values within the target system; if not set, no permissions
|
||||
# are changed.
|
||||
# Only one of the two source keys (either *from* or *src*) may be set.
|
||||
#
|
||||
# The target filename is modified as follows:
|
||||
# - `@@ROOT@@` is replaced by the path to the target root (may be /)
|
||||
@ -32,5 +37,13 @@ files:
|
||||
- /etc/oem-information
|
||||
- from: log
|
||||
dest: /root/install.log
|
||||
perm: root:wheel:644
|
||||
- from: config
|
||||
dest: /root/install.cfg
|
||||
perm: root:wheel:400
|
||||
|
||||
# The *perm* key contains a default value to apply to all files listed
|
||||
# above that do not have a *perm* key of their own. If not set,
|
||||
# root:root:0400 (highly restrictive) is used.
|
||||
#
|
||||
# perm: "root:root:0400"
|
||||
|
@ -8,10 +8,7 @@ calamares_add_plugin( shellprocess
|
||||
SHARED_LIB
|
||||
)
|
||||
|
||||
if( ECM_FOUND )
|
||||
find_package( Qt5 COMPONENTS Test REQUIRED )
|
||||
include( ECMAddTests )
|
||||
|
||||
if( ECM_FOUND AND BUILD_TESTING )
|
||||
ecm_add_test(
|
||||
Tests.cpp
|
||||
TEST_NAME
|
||||
|
@ -87,7 +87,7 @@ int main(int argc, char** argv)
|
||||
if ( !doc.IsMap() )
|
||||
{
|
||||
cerr << "WARNING:" << filename << '\n';
|
||||
cerr << "WARNING: not-a-YAML-map\n";
|
||||
cerr << "WARNING: not-a-YAML-map (type=" << doc.Type() << ")\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,4 @@
|
||||
find_package(ECM ${ECM_VERSION} NO_MODULE)
|
||||
if( ECM_FOUND )
|
||||
include( ECMAddTests )
|
||||
endif()
|
||||
|
||||
find_package( Qt5 COMPONENTS Core Test REQUIRED )
|
||||
find_package( Qt5 COMPONENTS Core REQUIRED )
|
||||
find_package( Crypt REQUIRED )
|
||||
|
||||
# Add optional libraries here
|
||||
@ -44,7 +39,7 @@ calamares_add_plugin( users
|
||||
SHARED_LIB
|
||||
)
|
||||
|
||||
if( ECM_FOUND )
|
||||
if( ECM_FOUND AND BUILD_TESTING )
|
||||
ecm_add_test(
|
||||
PasswordTests.cpp
|
||||
SetPasswordJob.cpp
|
||||
|
Loading…
Reference in New Issue
Block a user