46 Commits

Author SHA1 Message Date
Adriaan de Groot
51e89e58dd CMake: bump version and requirements
Builds cleanly with Calamares 3.3.1
2024-01-12 23:15:55 +01:00
Adriaan de Groot
d8d5a1fb26 CMake: find Calamares first, then other bits 2024-01-09 23:10:38 +01:00
Adriaan de Groot
85f05e8121 Merge pull request #31 from Undef-a/wip/undef/fix-ftbfs
Fix failure to configure/build with newer CMake and Calamares 3.3.0
2024-01-09 23:06:45 +01:00
undef
c28c9b8114 Port modules to Calamares 3.3.0
Calamares 3.3.0 changed the import name and namespace of
CalamaresUtilsSystem and CalamaresUtilsGui.
2023-12-17 03:40:44 +00:00
undef
935f21ace5 CMakeLists: Copy KF CoreAddons and FeatureSummary imports from Calamares
Without these the package no-longer compiles with recent versions of
cmake.
2023-12-17 03:40:40 +00:00
demmm
6bd75570de Merge pull request #30 from Undef-a/wip/undef/librem5-screen
mobile: Ensure welcome screen fits on Librem5
2023-09-29 14:19:05 +02:00
undef
acdcdea668 mobile: Ensure welcome screen fits on Librem5
Now that the sizing has changed this line overhangs the screen.
2023-09-29 11:36:34 +00:00
Adriaan de Groot
edb405a4d1 Merge pull request #29 from Undef-a/wip/undef/fix-sizing-with-3.3.x
mobile: Adjust all sizes for Calamares 3.3.x
2023-09-28 23:03:26 +02:00
undef
3ad9c221d4 mobile: Adjust all sizes for Calamares 3.3.x
Element sizing in Calamares 3.3.x seems to have dramatically changed,
with for example a button that was previously fine at width 500 now
being huge to the point of causing the installer to overhang the screen.

This reduces the size of most elements such that they fit on a mobile
screen again.

Fixes: https://github.com/calamares/calamares/issues/2192
2023-09-28 08:56:44 +00:00
Adriaan de Groot
dc3550eccd CMake: post-release housekeeping
- Update CMake requirements to shut KF5 up
- Require the next Calamares main branch
- Bump to 1.4.0 version
2023-08-28 23:52:02 +02:00
Adriaan de Groot
fac16ac6a7 CMake: be more chatty about Calamares version used 2023-08-28 21:04:36 +02:00
Adriaan de Groot
a442ed8c12 CI: remove Linuxisms from release script 2023-08-28 20:34:32 +02:00
Adriaan de Groot
e08d687061 CI: update signing key 2023-08-28 00:33:12 +02:00
Adriaan de Groot
15f6369537 Changes: pre-release housekeeping 2023-08-28 00:31:50 +02:00
Adriaan de Groot
f01b4ed2f8 docs: drop mention of IRC, prefer Matrix for communication 2023-08-27 22:47:08 +02:00
Adriaan de Groot
ea762b0945 Merge pull request #26 from nmschulte/nms/fix-username-prompt
add usermod command about default username
2023-08-06 15:24:10 +02:00
Nathan Schulte
cae8acb4a4 custom username also changes the fullname/comment 2023-08-03 14:52:59 -05:00
Nathan Schulte
ae204d0108 change username before password 2023-07-19 20:49:48 -05:00
Nathan Schulte
a2fae600c4 add usermod command about default username
cmdUsermod supports changing the default username

in case any extra initial state needs updated, cmdUsermod can be amended to run additional commands
2023-07-11 01:29:32 -05:00
Adriaan de Groot
349acad491 Merge pull request #23 from Undef-a/calamares
mobile: Reflow confirm page to fit smaller screens
2023-07-01 22:58:31 +02:00
Adriaan de Groot
9b4c4876bc Merge pull request #24 from ollieparanoid/6-char-pass
mobile: change min pass length to 6 digits
2023-07-01 22:58:18 +02:00
Oliver Smith
cc02baed9a mobile: change min pass length to 6 digits
Require at least 6 characters instead of 8 and mention that digits can
also be used. Most users set something like a 6 digit number on their
lockscreen, it is even what we have by default in the postmarketOS
images when you don't use the installer. So requiring 8 in the installer
does not make sense.

Fixes: https://gitlab.com/postmarketOS/postmarketos-ondev/-/issues/62
2023-06-05 17:49:42 +02:00
undef
dfab089938 mobile: Reflow confirm page to fit smaller screens
When testing on the Librem5 this page hangs slightly off the screen,
causing the "Install" button to be only just selectable on the bottom
edge.

This slightly reflows the page such that on these smaller screens the
button is still in a selectable location.
2023-05-20 09:48:22 +00:00
Adriaan de Groot
2dd9a7ba8a Merge pull request #22 from nmschulte/nms/username-prompt-origin
[mobile] add username prompt, reservedUsernames config, minor cleanup
2023-02-24 22:34:35 +01:00
Nathan Schulte
82f31f3cd9 use reservedUsernames config 2023-02-20 01:24:40 -06:00
Nathan Schulte
c5b01a574d add reservedUsernames config 2023-02-20 01:24:40 -06:00
Nathan Schulte
bc4789d57f add username input field to user_pass module 2023-02-20 01:24:40 -06:00
Nathan Schulte
0962b98494 add username validation routine to mobile module 2022-09-22 00:55:24 -05:00
Nathan Schulte
108476c025 fix typo and cleanup code style 2022-09-22 00:55:24 -05:00
Adriaan de Groot
04a1bc9e2c Merge pull request #21 from demmm/calamares
[KaOS Branding] add navigation & sidebar examples
2022-08-07 14:19:14 +02:00
demmm
bff5e485f4 [KaOS Branding] add navigation & sidebar examples
both set to QML
navigation set vertical, progress set horizontal
include some updates
2022-08-04 18:55:01 +02:00
Adriaan de Groot
3c838436c2 [mobile] Increase timeout for PartitionJob: 10 min 2022-07-16 08:01:53 +02:00
Adriaan de Groot
644c9cf4f3 [unpackfsc] Improve tar support
Enable support for tar option in unpackfsc module for all compression algorithms
2022-07-16 08:00:33 +02:00
Oliver Smith
dcaa378ddd [mobile] Increase timeout for PartitionJob: 10 min
Increase the PartitionJob's timeout from 2 min to 10 min, as there was
an report of hitting the timeout with the PinePhone Pro's 128 GiB eMMC.

Related: https://gitlab.com/postmarketOS/pmaports/-/merge_requests/3280#note_1021536268
2022-07-11 08:25:55 +02:00
sravanpannala
14fd23dcef remove z option from tar so that it works with all 2022-07-06 17:56:28 -04:00
Adriaan de Groot
f4bc7052e0 [unpackfsc] Add (untested) tarball support 2022-05-17 12:30:28 +02:00
Adriaan de Groot
4f0f48d99d [unpackfsc] Unsquash is implemented 2022-05-17 12:21:52 +02:00
Adriaan de Groot
1344880f2e [unpackfsc] Add fsarchiver "fs" mode
- Add "restfs" suppotr for fsarchiver
- Apply coding style from Calamares
2022-05-17 12:12:30 +02:00
Adriaan de Groot
5704e146a0 Changes: pre-release housekeeping 2021-11-16 13:10:36 +01:00
Adriaan de Groot
85eb434b57 Merge branch 'fsarchiver' into calamares 2021-11-16 13:07:14 +01:00
Adriaan de Groot
4b2ea61aa3 [unpackfs] Document that fsarchiver uses savedir/restdir 2021-11-16 13:04:54 +01:00
Adriaan de Groot
39d25eef1c [unpackfsc] Reduce number of status updates in fsarchiver 2021-11-16 13:00:00 +01:00
Adriaan de Groot
e82d32fe66 [unpackfsc] Use restdir instead of restfs 2021-11-16 12:58:17 +01:00
Adriaan de Groot
a50ab49c22 [unpackfsc] Add test-configs for fsarchiver-unpack 2021-11-16 12:52:34 +01:00
Adriaan de Groot
a66ab99ce8 [unpackfsc] Report fsarchiver progress, too 2021-11-16 12:24:33 +01:00
Adriaan de Groot
c3170a9dfb Changes: post-release housekeeping 2021-11-16 12:12:21 +01:00
47 changed files with 1070 additions and 219 deletions

43
CHANGES
View File

@@ -6,6 +6,49 @@ This is the changelog for Calamares-Extensions. For each release, the major
changes and contributors are listed. Note that Calamares-Extensions does not
have a historical changelog -- this log starts with version 1.0.0.
# 1.3.2 (2023-08-28)
We skipped a couple of releases in the release-notes, then tagged
1.3.1 without a version bump or release-notes. So 1.3.2 brings us
back to "regular releases".
This release contains contributions from (alphabetically by first name):
- Anke Boersma
- Nathan Schulte
- Oliver Smith
- stravanpannala
- undef
Changes and new modules in this release:
- *mobile* Has new configuration options. (Thanks Nathan, Oliver)
- *unpackfsc* Uses a more portable invocation of tar. (Thanks sravanpannala)
# 1.2.1 (2021-11-16)
The 1.2.0 release had no release-notes for that version, and failed to
credit Anke and Otus.
Changes and new modules in this release:
- *unpackfsc* can use `fsarchiver` and unpack that, instead of squashfs;
a distro might choose one tool or the other. Currently, only *savedir* /
*restdir* mode (i.e. directories, not block-devices) are supported.
# 1.2.0 (2021-11-16)
This release contains contributions from (alphabetically by first name):
- Anke Boersma
- Otus9051
Changes and new modules in this release:
- *refind* is a new module that installs the rEFInd bootloader. It can
be used instead of the *bootloader* module from core Calamares. (Thanks Anke)
- *unpackfsc* is a new module that uses `unsquashfs` directly. This may
be faster or more convenient than the *unpackfs* module from core Calamares.
The configuration file supports only one entry, but is otherwise easy to
adapt from an existing `unpackfs.conf`.
# 1.1.2 (2021-05-14)
This release contains contributions from (alphabetically by first name):

View File

@@ -32,15 +32,18 @@
# In this repository, there is just one "group" to which USE_* applies:
# USE_os : operating-system-specific modules.
#
# There is a knob WITH_QT6 which can be used to build against Qt6 rather
# than Qt5. This must match what Calamares itself is built with.
#
### NOTES
#
# Call this CMake file in script mode, e.g. `cmake -P CMakeLists.txt`
# to print out version information. Use `cmake -DVERSION_STYLE=short`
# to get just the short versioning.
#
cmake_minimum_required(VERSION 3.3 FATAL_ERROR)
cmake_minimum_required(VERSION 3.16 FATAL_ERROR)
set( CALAMARES_EXTENSIONS_VERSION 1.2.0 )
set( CALAMARES_EXTENSIONS_VERSION 3.3.1 )
include( ${CMAKE_CURRENT_LIST_DIR}/CMakeModules/ExtendedVersion.cmake )
if ( CMAKE_SCRIPT_MODE_FILE )
@@ -60,12 +63,42 @@ set( CMAKE_CXX_STANDARD_REQUIRED ON )
# consumers by loading the developer's config from a build
# directory (which doesn't have the rest of the config
# installed inside it).
set( CALAMARES_VERSION_REQUIRED 3.2.46 )
set( CALAMARES_VERSION_REQUIRED 3.3.1 )
find_package(Calamares ${CALAMARES_VERSION_REQUIRED} NO_CMAKE_PACKAGE_REGISTRY)
if (NOT TARGET Calamares::calamares OR NOT TARGET Calamares::calamaresui)
find_package(Calamares ${CALAMARES_VERSION_REQUIRED} REQUIRED)
endif()
message(STATUS "Found Calamares version ${Calamares_VERSION}")
message(STATUS " libraries ${Calamares_LIB_DIRS}")
message(STATUS "")
### EXTRACTING DEPENDENCIES AND CONFIGURATION FROM CALAMARES
#
#
if(WITH_QT6)
set(kfname "KF6")
set(KF_VERSION 5.240) # KDE Neon weirdness
else()
message(STATUS "Building Calamares with Qt5")
set(kfname "KF5")
set(KF_VERSION 5.78)
# API that was deprecated before Qt 5.15 causes a compile error
add_compile_definitions(QT_DISABLE_DEPRECATED_BEFORE=0x050f00)
endif()
include( FeatureSummary )
find_package(${kfname}CoreAddons ${KF_VERSION} QUIET)
set_package_properties(
${kfname}CoreAddons
PROPERTIES
TYPE REQUIRED
DESCRIPTION "KDE Framework CoreAddons"
URL "https://api.kde.org/frameworks/"
PURPOSE "Essential Framework for AboutData and Macros"
)
### CMAKE SETUP
#
# Enable IN_LIST
@@ -119,6 +152,8 @@ calamares_add_module_subdirectory( modules/refind LIST_SKIPPED_MODULES )
calamares_add_module_subdirectory( modules/slowpython LIST_SKIPPED_MODULES ) # Python job
calamares_add_module_subdirectory( modules/unpackfsc LIST_SKIPPED_MODULES )
message(STATUS "Calamares extensions ${CALAMARES_EXTENSIONS_VERSION} for Calamares version ${Calamares_VERSION}")
# If modules cannot be built, they usually call a macro
# which builds a list of explanations; show that list.
calamares_explain_skipped_modules( ${LIST_SKIPPED_MODULES} )

View File

@@ -29,15 +29,12 @@ rules of decent behavior in both communities are pretty much the same).
GitHub Issues are **one** place for discussing Calamares and its extensions if there are concrete
problems or a new feature to discuss.
Issues are not a help channel.
Visit Matrix for help with configuration or compilation.
Regular Calamares development chit-chat happens in a [Matrix](https://matrix.org/)
room, `#calamares:kde.org`. The conversation is bridged with IRC
on [Libera.Chat](https://libera.chat/).
Responsiveness is best during the day
in Europe, but feel free to idle. If you use IRC, **DO NOT** ask-and-leave. Keep
that chat window open because it can easily take a few hours for
someone to notice a message.
room, `#calamares:kde.org`. Responsiveness is best during the day
in Europe, but feel free to idle.
Matrix is persistent, and we'll see your message eventually.
* [![Join us on Matrix](https://img.shields.io/badge/Matrix-%23calamares:kde.org-blue)](https://webchat.kde.org/#/room/%23calamares:kde.org)
* [![Chat on IRC](https://img.shields.io/badge/IRC-Libera.Chat%20%23calamares-green)](https://kiwiirc.com/client/irc.libera.chat/#calamares)

View File

@@ -40,7 +40,10 @@ and documentation for the framework that Calamares ships with.
(probably moreso than the default slideshow).
- [`kaos_branding/`](branding/kaos_branding/branding.desc)
is a copy of the KaOS branding component, which
has translations and a bunch of fancy graphics.
has translations and a bunch of fancy graphics for the
slideshow. Plus it includes examples of using different
QML options for a vertical navigation bar and horizontal
sidebar.
- [`samegame/` ](branding/default/branding.desc)
is a copy of the Qt Company "Same Game" QML demo. It
shows that **any** QML can be used for branding purposes.
@@ -217,15 +220,12 @@ The API is loosely documented in the
GitHub Issues are **one** place for discussing Calamares (and Calamares Extensions)
if there are concrete
problems or a new feature to discuss.
Issues are not a help channel.
Visit Matrix for help with configuration or compilation.
Regular Calamares development chit-chat happens in a [Matrix](https://matrix.org/)
room, `#calamares:kde.org`. The conversation is bridged with IRC
on [Libera.Chat](https://libera.chat/).
Responsiveness is best during the day
in Europe, but feel free to idle. If you use IRC, **DO NOT** ask-and-leave. Keep
that chat window open because it can easily take a few hours for
someone to notice a message.
room, `#calamares:kde.org`. Responsiveness is best during the day
in Europe, but feel free to idle.
Matrix is persistent, and we'll see your message eventually.
* [![Join us on Matrix](https://img.shields.io/badge/Matrix-%23calamares:kde.org-blue)](https://webchat.kde.org/#/room/%23calamares:kde.org)
* [![Chat on IRC](https://img.shields.io/badge/IRC-Libera.Chat%20%23calamares-green)](https://kiwiirc.com/client/irc.libera.chat/#calamares)

View File

@@ -0,0 +1,101 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2020 2022 Anke Boersma <demm@kaosx.us>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
*
*/
import io.calamares.core 1.0
import io.calamares.ui 1.0
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3
import QtQuick.Window 2.3
ApplicationWindow {
id: about
visible: true
width: 760
height: 400
title: qsTr("About Calamares")
property var appName: "Calamares"
property var appVersion: "3.3 RC"
Rectangle {
id: textArea
anchors.fill: parent
color: "#f2f2f2"
Column {
id: column
anchors.centerIn: parent
Rectangle {
width: 560
height: 250
radius: 10
border.width: 0
Text {
width: 400
height: 250
anchors.centerIn: parent
text: qsTr("<h1>%1</h1><br/>
<strong>%2<br/>
for %3</strong><br/><br/>
Copyright 2014-2017 Teo Mrnjavac &lt;teo@kde.org&gt;<br/>
Copyright 2017-2022 Adriaan de Groot &lt;groot@kde.org&gt;<br/>
Thanks to <a href='https://calamares.io/team/'>the Calamares team</a>
and the <a href=\"https://www.transifex.com/kaos/kaos/\">KaOS
translators team</a>.<br/><br/>
<a href='https://calamares.io/'>Calamares</a>
development is sponsored by <br/>
<a href='http://www.blue-systems.com/'>Blue Systems</a> -
Liberating Software." )
.arg(appName)
.arg(appVersion)
.arg(Branding.string(Branding.VersionedName))
onLinkActivated: Qt.openUrlExternally(link)
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.NoButton
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
}
font.pointSize: 10
anchors.verticalCenterOffset: 10
anchors.horizontalCenterOffset: 40
wrapMode: Text.WordWrap
}
Image {
id: image
x: 8
y: 12
height: 100
fillMode: Image.PreserveAspectFit
source: "squid.png"
}
}
}
Button {
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
icon.name: "window-close"
text: qsTr("Close")
hoverEnabled: true
onClicked: about.close();
}
}
}

View File

@@ -1,22 +1,32 @@
---
componentName: kaos
welcomeStyleCalamares: false
# Should the welcome image (productWelcome, below) be scaled
# up beyond its natural size?
welcomeExpandingLogo: true
windowExpanding: normal
windowSize: 920px,630px
windowPlacement: center
sidebar: qml,bottom
navigation: qml,right
strings:
productName: KaOS
shortProductName: KaOS
version: 2018.03
version: 2022.08
shortVersion: KaOS
versionedName: KaOS 2018.03
versionedName: KaOS 2022.08
shortVersionedName: KaOS 2018.03
bootloaderEntryName: KaOS
productUrl: https://kaosx.us/
supportUrl: https://kaosx.us/docs/
knownIssuesUrl: https://kaosx.us/pages/download/#known-issues
releaseNotesUrl: https://kaosx.us/pages/release_notes
donateUrl: https://kaosx.us/about/donors
images:
productLogo: "kaos.png"
@@ -27,6 +37,7 @@ slideshow: "show.qml"
slideshowAPI: 1
style:
sidebarBackground: "#bdc3c7"
sidebarText: "#1F1F1F"
sidebarTextSelect: "#3498DB"
SidebarBackground: "#bdc3c7"
SidebarText: "#1F1F1F"
SidebarTextCurrent: "#3498DB"
SidebarBackgroundCurrent: "#eff0f1"

View File

@@ -0,0 +1,224 @@
/* Sample of QML navigation.
SPDX-FileCopyrightText: 2020 Adriaan de Groot <groot@kde.org>
SPDX-FileCopyrightText: 2021 - 2022 Anke Boersma <demm@kaosx.us>
SPDX-License-Identifier: GPL-3.0-or-later
This navigation panel is for a "vertical" layout, with
mouse areas for next and previous and it includes the logo
plus About & Debug buttons.
*/
import io.calamares.ui 1.0
import io.calamares.core 1.0
import QtQuick 2.3
import QtQuick.Controls 2.10
import QtQuick.Layouts 1.3
Rectangle {
id: navigationBar;
color: Branding.styleString( Branding.SidebarBackground );
height: parent.height;
width:64;
ColumnLayout {
id: buttonBar
anchors.fill: parent;
spacing: 1
Image {
Layout.topMargin: 1;
Layout.bottomMargin:parent.height / 7;
Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
id: logo;
width: 62;
height: width; // square
source: "file:/" + Branding.imagePath(Branding.ProductLogo);
sourceSize.width: width;
sourceSize.height: height;
}
Rectangle {
id: backArea
Layout.fillWidth: true;
Layout.preferredHeight: parent.height / 7;
color: mouseBack.containsMouse ? "#e6e9ea" : "#d9dcde";
enabled: ViewManager.backEnabled;
visible: ViewManager.backAndNextVisible;
MouseArea {
id: mouseBack
anchors.fill: parent;
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
Text {
anchors.centerIn: parent
text: qsTr("Back")
color: Branding.styleString( !backArea.enabled ? Branding.SidebarBackground : (mouseBack.containsMouse ? Branding.SidebarTextCurrent : Branding.SidebarText ));
font.pointSize : 8
}
Image {
source: "pan-start-symbolic.svg"
anchors.centerIn: parent
anchors.verticalCenterOffset : 18
fillMode: Image.PreserveAspectFit
height: 32
opacity: backArea.enabled ? 1 : 0.2
}
onClicked: { ViewManager.back(); }
}
}
Rectangle {
id: nextArea
Layout.preferredHeight: parent.height / 7;
Layout.fillWidth: true
color: mouseNext.containsMouse ? "#f4f5f6" : "#e6e9ea";
enabled: ViewManager.nextEnabled;
visible: ViewManager.backAndNextVisible;
MouseArea {
id: mouseNext
anchors.fill: parent;
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
Text {
anchors.centerIn: parent
text: qsTr("Next")
color: Branding.styleString( !nextArea.enabled ? Branding.SidebarBackground : (mouseNext.containsMouse ? Branding.SidebarTextCurrent : Branding.SidebarText ));
font.pointSize : 8
}
Image {
source: "pan-end-symbolic.svg"
anchors.centerIn: parent
anchors.verticalCenterOffset : 18
fillMode: Image.PreserveAspectFit
height: 32
opacity: nextArea.enabled ? 1 : 0.2
}
onClicked: { ViewManager.next(); }
}
}
Rectangle {
id: cancelArea
height: parent.height / 7;
Layout.fillWidth: true
color: mouseCancel.containsMouse ? "#e6e9ea" : "#d9dcde";
/*
* The ViewManager has settings -- user-controlled via the
* branding component, and party based on program state --
* whether the quit button should be enabled and visible.
*
* QML navigation *should* follow this pattern, but can also
* add other qualifications. For instance, you may have a
* "finished" module that handles quit in its own way, and
* want to hide the quit button then. The ViewManager has a
* current step and a total count, so compare them:
*
* visible: ViewManager.quitVisible && ( ViewManager.currentStepIndex < ViewManager.rowCount()-1);
*/
enabled: ViewManager.quitEnabled;
visible: ViewManager.quitVisible && ( ViewManager.currentStepIndex < ViewManager.rowCount()-1);
ToolTip {
width: 59
visible: mouseCancel.containsMouse
timeout: 5000
delay: 1000
text: ViewManager.quitTooltip;
}
MouseArea {
id: mouseCancel
anchors.fill: parent;
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
Text {
anchors.centerIn: parent
text: qsTr("Cancel")
color: Branding.styleString( !cancelArea.enabled ? Branding.SidebarBackground : (mouseCancel.containsMouse ? Branding.SidebarTextCurrent : Branding.SidebarText ));
font.pointSize : 8
}
Image {
source: "draw-rectangle.svg"
anchors.centerIn: parent
anchors.verticalCenterOffset : 18
fillMode: Image.PreserveAspectFit
height: 9
opacity: cancelArea.enabled ? 1 : 0.2
}
onClicked: { ViewManager.quit(); }
}
}
Item {
Layout.fillHeight: true;
}
Rectangle {
id: debugArea
Layout.fillWidth: true;
height: 35
Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
color: Branding.styleString( mouseAreaDebug.containsMouse ? Branding.SidebarBackgroundCurrent : Branding.SidebarBackground);
visible: debug.enabled
MouseArea {
id: mouseAreaDebug
anchors.fill: parent;
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
Text {
anchors.centerIn: parent
text: qsTr("Debug")
color: Branding.styleString( mouseAreaDebug.containsMouse ? Branding.SidebarTextCurrent : Branding.SidebarBackground );
font.pointSize : 8
}
onClicked: debug.toggle()
}
}
Rectangle {
id: aboutArea
Layout.fillWidth: true;
height: 35
Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
color: Branding.styleString( mouseAreaAbout.containsMouse ? Branding.SidebarBackgroundCurrent : Branding.SidebarBackground);
visible: true
MouseArea {
id: mouseAreaAbout
anchors.fill: parent;
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
Text {
anchors.centerIn: parent
text: qsTr("About")
ToolTip {
visible: mouseAreaAbout.containsMouse
delay: 1000
text: qsTr("Info about Calamares")
}
color: Branding.styleString( mouseAreaAbout.containsMouse ? Branding.SidebarTextCurrent : Branding.SidebarBackgroundCurrent );
font.pointSize : 8
}
property variant window;
onClicked: {
var component = Qt.createComponent("about.qml");
window = component.createObject();
window.show();
}
}
}
}
}

View File

@@ -0,0 +1,72 @@
/* Sample of QML progress tree.
SPDX-FileCopyrightText: 2020 Adriaan de Groot <groot@kde.org>
SPDX-FileCopyrightText: 2021 - 2022 Anke Boersma <demm@kaosx.us>
SPDX-License-Identifier: GPL-3.0-or-later
The progress tree (actually a list) is "horizontal" in this example,
with the steps going to the right.
*/
import io.calamares.ui 1.0
import io.calamares.core 1.0
import QtQuick 2.3
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.15
Rectangle {
id: sideBar;
color: Branding.styleString( Branding.SidebarBackground );
height: 48;
width: parent.width
RowLayout {
anchors.fill: parent;
spacing: 2;
Item {
Layout.fillHeight: true;
}
Repeater {
model: ViewManager
Rectangle {
Layout.leftMargin: 0;
Layout.fillWidth: true;
Layout.alignment: Qt.AlignTop;
height: 42;
radius: 0;
color: Branding.styleString( index == ViewManager.currentStepIndex ? Branding.SidebarBackgroundCurrent : Branding.SidebarBackground );
Text {
anchors.verticalCenter: parent.verticalCenter;
anchors.horizontalCenter: parent.horizontalCenter
x: parent.x + 12;
color: Branding.styleString( index == ViewManager.currentStepIndex ? Branding.SidebarTextCurrent : Branding.SidebarText );
text: display;
font.pointSize : index == ViewManager.currentStepIndex ? 10 : 9
}
Rectangle {
height: 2
width: 800
anchors.bottom: parent.bottom;
border.color: Branding.styleString(ViewManager.currentStepIndex === index ? Branding.SidebarTextCurrent : (ViewManager.currentStepIndex >= index ? Branding.SidebarTextCurrent : Branding.SidebarBackgroundCurrent))
border.width: 3
Image {
source: "pan-up-symbolic.svg"
id: image
anchors.verticalCenter: parent.verticalCenter;
anchors.verticalCenterOffset : -3
x: parent.x + 35;
fillMode: Image.PreserveAspectFit
height: 32
visible: index == ViewManager.currentStepIndex ? true : false
}
}
}
}
}
}

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 22"><path d="m2 1034.36v16h16v-16z" fill="#566060" transform="translate(1-1031.36)"/></svg>

After

Width:  |  Height:  |  Size: 147 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 292 KiB

After

Width:  |  Height:  |  Size: 106 KiB

View File

@@ -0,0 +1,15 @@
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<svg height="16" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" version="1.1" width="16" xmlns="http://www.w3.org/2000/svg" enable-background="new">
<metadata id="metadata90"/>
<defs id="defs7386">
<linearGradient id="linearGradient5606" osb:paint="solid">
<stop id="stop5608"/>
</linearGradient>
<filter inkscape:collect="always" color-interpolation-filters="sRGB" id="filter7554">
<feBlend inkscape:collect="always" id="feBlend7556" in2="BackgroundImage" mode="darken"/>
</filter>
</defs>
<g inkscape:groupmode="layer" id="layer12" inkscape:label="actions" transform="translate(-445.0002,-129)">
<path inkscape:connector-curvature="0" d="m 451.0002,142 5,-5 -5,-5 z" id="path6412" sodipodi:nodetypes="cccc" fill="#555555"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 896 B

View File

@@ -0,0 +1,15 @@
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<svg height="16" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" version="1.1" width="16" xmlns="http://www.w3.org/2000/svg" enable-background="new">
<metadata id="metadata90"/>
<defs id="defs7386">
<linearGradient id="linearGradient5606" osb:paint="solid">
<stop id="stop5608"/>
</linearGradient>
<filter inkscape:collect="always" color-interpolation-filters="sRGB" id="filter7554">
<feBlend inkscape:collect="always" id="feBlend7556" in2="BackgroundImage" mode="darken"/>
</filter>
</defs>
<g inkscape:groupmode="layer" id="layer12" inkscape:label="actions" transform="translate(-425.0002,-129)">
<path inkscape:connector-curvature="0" d="m 435.0002,142 -5,-5 5,-5 z" id="path6400-8" sodipodi:nodetypes="cccc" fill="#555555"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 898 B

View File

@@ -0,0 +1,15 @@
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<svg height="16" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" version="1.1" width="16" xmlns="http://www.w3.org/2000/svg" enable-background="new">
<metadata id="metadata90"/>
<defs id="defs7386">
<linearGradient id="linearGradient5606" osb:paint="solid">
<stop id="stop5608"/>
</linearGradient>
<filter inkscape:collect="always" color-interpolation-filters="sRGB" id="filter7554">
<feBlend inkscape:collect="always" id="feBlend7556" in2="BackgroundImage" mode="darken"/>
</filter>
</defs>
<g inkscape:groupmode="layer" id="layer12" inkscape:label="actions" transform="translate(-465.0002,-129.00001)">
<path inkscape:connector-curvature="0" d="m 478.0002,139 -5,-5 -5,5 z" id="path6418" sodipodi:nodetypes="cccc" fill="#3498DB"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 902 B

View File

@@ -1,6 +1,7 @@
/* === This file is part of Calamares - <https://github.com/calamares> ===
*
* Copyright 2015, Teo Mrnjavac <teo@kde.org>
* Copyright 2015-2018, Anke Boersma <demm@kaosx.us>
*
* Calamares is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -24,13 +25,12 @@ Presentation
id: presentation
Timer {
id: advanceTimer
interval: 5000
running: false
repeat: true
onTriggered: presentation.goToNextSlide()
}
Slide {
anchors.fill: parent
@@ -38,7 +38,7 @@ Presentation
id: background
source: "1.svg"
anchors.fill: parent
Text {
anchors.centerIn: parent
anchors.verticalCenterOffset: 0
@@ -96,15 +96,15 @@ Presentation
anchors.horizontalCenterOffset: -100
font.pixelSize: parent.width *.015
color: 'white'
text: qsTr("The default Office Suite is Calligra.<br/>"+
"LibreOffice is available in the repositories. <br/>")
text: qsTr("The default Office Suite is LibreOffice.<br/>"+
"Calligra is available in the repositories. <br/>")
wrapMode: Text.WordWrap
width: 450
horizontalAlignment: Text.AlignLeft
}
}
}
Slide {
anchors.fill: parent
@@ -120,7 +120,7 @@ Presentation
font.pixelSize: parent.width *.015
color: 'white'
text: qsTr("Qt/KDE specific internet applications include the <br/>"+
"Qupzilla web-browser and kde-telepathy for <br/>"+
"Falkon web-browser and kde-telepathy for <br/>"+
"chat and Instant Messaging. <br/>")
wrapMode: Text.WordWrap
width: 450
@@ -128,7 +128,7 @@ Presentation
}
}
}
Slide {
anchors.fill: parent
@@ -150,7 +150,7 @@ Presentation
}
}
}
Slide {
anchors.fill: parent
@@ -172,6 +172,4 @@ Presentation
}
}
}
Component.onCompleted: advanceTimer.running = true
}

View File

@@ -10,7 +10,7 @@
# NOTE: this is largely a copy of the release script for Calamares,
# with not-applicable parts (such as translation-freeze) either
# commented-out, or skipped with if(false).
# NOTE: this script contains Linuxisms (in particular, expects GNU mktemp(1))
# NOTE: this script may contain Linuxisms
#
# This attempts to perform the different steps of the RELEASE.md
# document automatically. It's not tested on other machines or
@@ -93,7 +93,7 @@ fi
### Setup
#
#
BUILDDIR=$(mktemp -d --suffix=-build --tmpdir=.)
BUILDDIR=$(mktemp -d -p . -t build.XXXXX)
### Build with default compiler
#
@@ -148,7 +148,7 @@ test -n "$V" || { echo "Could not obtain version in $BUILDDIR ." ; exit 1 ; }
# This is the signing key ID associated with the GitHub account adriaandegroot,
# which is used to create all "verified" tags in the Calamares repo.
#
KEY_ID="CFDDC96F12B1915C"
KEY_ID="328D742D8807A435"
git tag -u "$KEY_ID" -m "Release v$V" "v$V" || { echo "Could not sign tag v$V." ; exit 1 ; }
### Create the tarball
@@ -167,7 +167,7 @@ gpg -s -u $KEY_ID --detach --armor $TAR_FILE # Sign the tarball
#
#
D=$(date +%Y%m%d-%H%M%S)
TMPDIR=$(mktemp -d --suffix="-calamares-$D")
TMPDIR=$(mktemp -d -p . -t calamares.XXXXX)
test -d "$TMPDIR" || { echo "Could not create tarball-build directory." ; exit 1 ; }
tar xzf "$TAR_FILE" -C "$TMPDIR" || { echo "Could not unpack tarball." ; exit 1 ; }
test -d "$TMPDIR/$TAR_V" || { echo "Tarball did not contain source directory." ; exit 1 ; }

View File

@@ -18,7 +18,7 @@ Config::Config( QObject* parent )
void
Config::setConfigurationMap( const QVariantMap& cfgMap )
{
using namespace CalamaresUtils;
using namespace Calamares;
if ( getBool( cfgMap, "bogus", false ) )
{
@@ -30,6 +30,13 @@ Config::setConfigurationMap( const QVariantMap& cfgMap )
m_device = getString( cfgMap, "device", "(unknown)" );
m_userInterface = getString( cfgMap, "userInterface", "(unknown)" );
m_version = getString( cfgMap, "version", "(unknown)" );
m_reservedUsernames = getStringList( cfgMap, "reservedUsernames", QStringList { "adm", "at ", "bin", "colord",
"cron", "cyrus", "daemon", "ftp", "games", "geoclue", "guest", "halt", "lightdm", "lp", "mail", "man",
"messagebus", "news", "nobody", "ntp", "operator", "polkitd", "postmaster", "pulse", "root", "shutdown",
"smmsp", "squid", "sshd", "sync", "uucp", "vpopmail", "xfs" } );
// ensure m_cmdUsermod matches m_username
m_username = getString( cfgMap, "username", "user" );
m_userPasswordNumeric = getBool( cfgMap, "userPasswordNumeric", true );
@@ -54,6 +61,8 @@ Config::setConfigurationMap( const QVariantMap& cfgMap )
m_cmdInternalStoragePrepare = getString( cfgMap, "cmdInternalStoragePrepare", "ondev-internal-storage-prepare" );
m_cmdPasswd = getString( cfgMap, "cmdPasswd", "passwd" );
m_cmdUsermod = getString( cfgMap, "cmdUsermod", "xargs -I{} -n1 usermod -m -d /home/{} -l {} -c {} user");
m_cmdSshdEnable = getString( cfgMap, "cmdSshdEnable", "systemctl enable sshd.service" );
m_cmdSshdDisable = getString( cfgMap, "cmdSshdDisable", "systemctl disable sshd.service" );
m_cmdSshdUseradd = getString( cfgMap, "cmdSshdUseradd", "useradd -G wheel -m" );
@@ -68,6 +77,7 @@ Config::createJobs()
/* Put users job in queue (should run after unpackfs) */
Calamares::Job* j = new UsersJob( m_featureSshd,
m_cmdPasswd,
m_cmdUsermod,
cmdSshd,
m_cmdSshdUseradd,
m_isSshEnabled,
@@ -132,6 +142,13 @@ Config::runPartitionJobThenLeave( bool b )
}
}
void
Config::setUsername( const QString& username )
{
m_username = username;
emit usernameChanged( m_username );
}
void
Config::setUserPassword( const QString& userPassword )
{

View File

@@ -20,8 +20,11 @@ class Config : public QObject
Q_PROPERTY( QString userInterface READ userInterface CONSTANT FINAL )
Q_PROPERTY( QString version READ version CONSTANT FINAL )
/* reserved usernames (user_pass, ssh_credentials )*/
Q_PROPERTY( QStringList reservedUsernames READ reservedUsernames CONSTANT FINAL )
/* default user */
Q_PROPERTY( QString username READ username CONSTANT FINAL )
Q_PROPERTY( QString username READ username WRITE setUsername NOTIFY usernameChanged )
Q_PROPERTY( QString userPassword READ userPassword WRITE setUserPassword NOTIFY userPasswordChanged )
Q_PROPERTY( bool userPasswordNumeric READ userPasswordNumeric CONSTANT FINAL )
@@ -72,13 +75,17 @@ public:
QString userInterface() const { return m_userInterface; }
QString version() const { return m_version; }
/* default user */
/* reserved usernames (user_pass, ssh_credentials) */
QStringList reservedUsernames() const { return m_reservedUsernames; };
/* user */
QString username() const { return m_username; }
QString userPassword() const { return m_userPassword; }
void setUsername( const QString& username );
void setUserPassword( const QString& userPassword );
bool userPasswordNumeric() const { return m_userPasswordNumeric; }
/* ssh server + credetials */
/* ssh server + credentials */
bool featureSshd() { return m_featureSshd; }
QString sshdUsername() const { return m_sshdUsername; }
QString sshdPassword() const { return m_sshdPassword; }
@@ -120,6 +127,7 @@ public:
/* users job */
QString cmdPasswd() const { return m_cmdPasswd; }
QString cmdUsermod() const { return m_cmdUsermod; }
QString cmdSshdEnable() const { return m_cmdSshdEnable; }
QString cmdSshdDisable() const { return m_cmdSshdDisable; }
QString cmdSshdUseradd() const { return m_cmdSshdUseradd; }
@@ -135,6 +143,9 @@ private:
QString m_userInterface;
QString m_version;
/* reserved usernames (user_pass, ssh_credentials) */
QStringList m_reservedUsernames;
/* default user */
QString m_username;
QString m_userPassword;
@@ -172,6 +183,7 @@ private:
/* users job */
QString m_cmdPasswd;
QString m_cmdUsermod;
QString m_cmdSshdEnable;
QString m_cmdSshdDisable;
QString m_cmdSshdUseradd;
@@ -181,6 +193,7 @@ signals:
/* default user */
void userPasswordChanged( QString userPassword );
void usernameChanged( QString username );
/* ssh server + credentials */
void sshdUsernameChanged( QString sshdUsername );

View File

@@ -5,7 +5,7 @@
#include "GlobalStorage.h"
#include "JobQueue.h"
#include "Settings.h"
#include "utils/CalamaresUtilsSystem.h"
#include "utils/System.h"
#include "utils/Logger.h"
#include <QDir>
@@ -75,7 +75,7 @@ Calamares::JobResult
PartitionJob::exec()
{
using namespace Calamares;
using namespace CalamaresUtils;
using namespace Calamares;
using namespace std;
const QString pathMount = "/mnt/install";
@@ -118,7 +118,7 @@ PartitionJob::exec()
const QString pathRoot = "/";
ProcessResult res
= System::runCommand( System::RunLocation::RunInHost, args, pathRoot, stdInput, chrono::seconds( 120 ) );
= System::runCommand( System::RunLocation::RunInHost, args, pathRoot, stdInput, chrono::seconds( 600 ) );
if ( res.getExitCode() )
{
return JobResult::error( "Command failed:<br><br>"

View File

@@ -5,7 +5,7 @@
#include "GlobalStorage.h"
#include "JobQueue.h"
#include "Settings.h"
#include "utils/CalamaresUtilsSystem.h"
#include "utils/System.h"
#include "utils/Logger.h"
#include <QDir>
@@ -14,6 +14,7 @@
UsersJob::UsersJob( bool featureSshd,
const QString& cmdPasswd,
const QString& cmdUsermod,
const QString& cmdSshd,
const QString& cmdSshdUseradd,
bool isSshEnabled,
@@ -24,6 +25,7 @@ UsersJob::UsersJob( bool featureSshd,
: Calamares::Job()
, m_featureSshd( featureSshd )
, m_cmdPasswd( cmdPasswd )
, m_cmdUsermod( cmdUsermod )
, m_cmdSshd( cmdSshd )
, m_cmdSshdUseradd( cmdSshdUseradd )
, m_isSshEnabled( isSshEnabled )
@@ -45,13 +47,15 @@ Calamares::JobResult
UsersJob::exec()
{
using namespace Calamares;
using namespace CalamaresUtils;
using namespace Calamares;
using namespace std;
QList< QPair< QStringList, QString > > commands = {
{ { "sh", "-c", m_cmdPasswd + " " + m_username }, m_password + "\n" + m_password + "\n" },
{ { "sh", "-c", m_cmdUsermod }, m_username + "\n" }
};
commands.append( { { "sh", "-c", m_cmdPasswd + " " + m_username }, m_password + "\n" + m_password + "\n" } );
if ( m_featureSshd )
{
commands.append( { { "sh", "-c", m_cmdSshd }, QString() } );

View File

@@ -10,6 +10,7 @@ class UsersJob : public Calamares::Job
public:
UsersJob( bool featureSshd,
const QString& cmdPasswd,
const QString& cmdUsermod,
const QString& cmdSshd,
const QString& cmdSshdUseradd,
bool isSshEnabled,
@@ -26,6 +27,7 @@ public:
private:
bool m_featureSshd;
QString m_cmdPasswd;
QString m_cmdUsermod;
QString m_cmdSshd;
QString m_cmdSshdUseradd;
bool m_isSshEnabled;

View File

@@ -22,7 +22,7 @@ Item {
id: mainText
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: 30
anchors.topMargin: 10
wrapMode: Text.WordWrap
text: "To protect your data in case your device gets stolen," +
@@ -33,15 +33,15 @@ Item {
" boot your device or access any data on it. Make sure that" +
" you don't lose this password!"
width: 500
width: 200
}
Button {
id: firstButton
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: mainText.bottom
anchors.topMargin: 40
width: 500
anchors.topMargin: 10
width: 200
text: qsTr("Enable")
onClicked: {
@@ -53,8 +53,8 @@ Item {
Button {
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: firstButton.bottom
anchors.topMargin: 40
width: 500
anchors.topMargin: 10
width: 200
text: qsTr("Disable")
onClicked: {

View File

@@ -36,7 +36,7 @@ Item {
anchors.horizontalCenter: parent.horizontalCenter
anchors.topMargin: 50
width: 500
width: 200
}
TextField {
@@ -49,8 +49,8 @@ Item {
text: config.fdePassword
anchors.horizontalCenter: parent.horizontalCenter
anchors.topMargin: 50
width: 500
anchors.topMargin: 10
width: 200
}
Text {
@@ -59,15 +59,15 @@ Item {
visible: false
anchors.horizontalCenter: parent.horizontalCenter
anchors.topMargin: 50
width: 500
anchors.topMargin: 10
width: 200
wrapMode: Text.WordWrap
}
Button {
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: errorText.bottom
anchors.topMargin: 40
width: 500
anchors.topMargin: 10
width: 200
text: qsTr("Continue")
onClicked: {

View File

@@ -22,21 +22,21 @@ Item {
id: mainText
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: 30
anchors.topMargin: 10
wrapMode: Text.WordWrap
text: "Select the filesystem for root partition. If unsure, leave the default."
width: 500
width: 200
}
ComboBox {
id: fsTypeCB
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: mainText.bottom
anchors.topMargin: 40
width: 500
height: 60
anchors.topMargin: 10
width: 150
height: 30
editable: false
model: config.fsList
/* Save the current state on selection so it is there when the back button is pressed */
@@ -47,8 +47,8 @@ Item {
Button {
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: fsTypeCB.bottom
anchors.topMargin: 40
width: 500
anchors.topMargin: 10
width: 200
text: qsTr("Continue")
onClicked: {

View File

@@ -22,13 +22,13 @@ Item {
id: mainText
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: 30
anchors.topMargin: 10
wrapMode: Text.WordWrap
text: (function() {
var ret = "Once you hit 'install', the installation will begin." +
" It will typically take a few minutes. Do not power off the" +
" device until it is done.<br><br>";
" device until it is done.<br>";
if (config.installFromExternalToInternal) {
ret += "<b>After the installation, your device will shutdown" +
@@ -44,15 +44,15 @@ Item {
return ret;
}())
width: 500
width: 200
}
Button {
id: firstButton
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: mainText.bottom
anchors.topMargin: 40
width: 500
anchors.topMargin: 10
width: 200
text: qsTr("Install")
onClicked: navFinish()

View File

@@ -22,7 +22,7 @@ Item {
id: mainText
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: 30
anchors.topMargin: 10
wrapMode: Text.WordWrap
text: "The installation was started from an external storage medium." +
@@ -32,15 +32,15 @@ Item {
"<br>" +
"Where would you like to install " + config.osName + "?"
width: 500
width: 200
}
Button {
id: firstButton
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: mainText.bottom
anchors.topMargin: 40
width: 500
anchors.topMargin: 10
width: 200
text: qsTr("Internal (eMMC)")
onClicked: {
@@ -52,8 +52,8 @@ Item {
Button {
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: firstButton.bottom
anchors.topMargin: 40
width: 500
anchors.topMargin: 10
width: 200
text: qsTr("External (SD card)")
onClicked: {

View File

@@ -22,21 +22,21 @@ Item {
id: mainText
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: 30
anchors.topMargin: 10
wrapMode: Text.WordWrap
text: "Are you sure that you want to overwrite the internal storage?" +
"<br><br>" +
"<b>All existing data on the device will be lost!</b>"
width: 500
width: 200
}
Button {
id: firstButton
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: mainText.bottom
anchors.topMargin: 40
width: 500
anchors.topMargin: 10
width: 200
text: qsTr("Yes")
onClicked: {
@@ -47,8 +47,8 @@ Item {
Button {
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: firstButton.bottom
anchors.topMargin: 40
width: 500
anchors.topMargin: 10
width: 200
text: qsTr("No")
onClicked: {

View File

@@ -26,8 +26,45 @@ bogus: true
# version: "(unknown)"
## Default username (for which the password will be set)
## Ensure also cmdUsermod command matches the default user, so it can be changed if desired.
# username: "user"
## reserved usernames (for user_pass username prompt and ssh_credentials)
# reservedUsernames:
# - adm
# - at
# - bin
# - colord
# - cron
# - cyrus
# - daemon
# - ftp
# - games
# - geoclue
# - guest
# - halt
# - lightdm
# - lp
# - mail
# - man
# - messagebus
# - news
# - nobody
# - ntp
# - operator
# - polkitd
# - postmaster
# - pulse
# - root
# - shutdown
# - smmsp
# - squid
# - sshd
# - sync
# - uucp
# - vpopmail
# - xfs
#######
### Target device information
#######
@@ -118,6 +155,10 @@ bogus: true
### Commands running in the target OS (chroot)
#######
## Change the username for the default user
## Stdin: username with \n
# cmdUsermod: "xargs -I{} -n1 usermod -m -d /home/{} -l {} -c {} user"
## Set the password for default user and sshd user
## Arguments: <username>
## Stdin: password twice, each time with \n

View File

@@ -77,7 +77,7 @@ Page
Rectangle {
id: mobileNavigation
width: parent.width
height: 60
height: 30
color: "#e6e4e1"
Layout.fillWidth: true
@@ -98,8 +98,8 @@ Page
text: "<"
background: Rectangle {
implicitWidth: 32
implicitHeight: 30
implicitWidth: 10
implicitHeight: 7
border.color: "#c1bab5"
border.width: 1
radius: 4
@@ -109,7 +109,7 @@ Page
onClicked: navBack()
}
Rectangle {
implicitHeight: 30
implicitHeight: 10
Layout.fillWidth: true
color: "#e6e4e1"
@@ -253,7 +253,7 @@ Page
return true;
}
/* Input validation: user-screens (user_pass, ssh_credentials) */
/* Input validation: user-screens (fde_pass, user_pass, ssh_credentials) */
function validatePin(userPin, userPinRepeat, errorText) {
var pin = userPin.text;
var repeat = userPinRepeat.text;
@@ -278,47 +278,12 @@ Page
return validationFailureClear(errorText);
}
function validateSshdUsername(username, errorText) {
function validateUsername(username, errorText, extraReservedUsernames = []) {
var name = username.text;
var reserved = [ /* FIXME: make configurable */
config.username,
"adm",
"at ",
"bin",
"colord",
"cron",
"cyrus",
"daemon",
"ftp",
"games",
"geoclue",
"guest",
"halt",
"lightdm",
"lp",
"mail",
"man",
"messagebus",
"news",
"nobody",
"ntp",
"operator",
"polkitd",
"postmaster",
"pulse",
"root",
"shutdown",
"smmsp",
"squid",
"sshd",
"sync",
"uucp",
"vpopmail",
"xfs",
]
var reserved = config.reservedUsernames.concat(extraReservedUsernames);
/* Validate characters */
for (var i=0; i<name.length; i++) {
for (var i = 0; i < name.length; i++) {
if (i) {
if (!name[i].match(/^[a-z0-9_-]$/))
return validationFailure(errorText,
@@ -335,16 +300,20 @@ Page
}
/* Validate against reserved usernames */
for (var i=0;i<reserved.length;i++) {
for (var i = 0; i < reserved.length; i++) {
if (name == reserved[i])
return validationFailure(errorText, "Username '" +
reserved[i] +
"' is reserved.")
"' is reserved.");
}
/* Passed */
return validationFailureClear(errorText);
}
function validateSshdUsername(username, errorText) {
return validateUsername(username, errorText, [config.username]);
}
function validateSshdPassword(password, passwordRepeat, errorText) {
var pass = password.text;
var repeat = passwordRepeat.text;
@@ -352,10 +321,10 @@ Page
if (pass == "")
return validationFailure(errorText);
if (pass.length < 8)
if (pass.length < 6)
return validationFailure(errorText,
"Too short: needs at least 8" +
" characters.");
"Too short: needs at least 6" +
" digits/characters.");
if (repeat == "")
return validationFailure(errorText);
@@ -365,8 +334,6 @@ Page
return validationFailureClear(errorText);
}
/* Input validation: fde_pass */
function check_chars(input) {
for (var i = 0; i < input.length; i++) {
if (allowed_chars.indexOf(input[i]) == -1)
@@ -407,10 +374,10 @@ Page
"\n" +
allowed_chars_multiline());
if (pass.length < 8)
if (pass.length < 6)
return validationFailure(errorText,
"Too short: needs at least 8" +
" characters.");
"Too short: needs at least 6" +
" digits/characters.");
if (repeat == "")
return validationFailure(errorText);

View File

@@ -7,7 +7,7 @@
<file>install_target.qml</file> <!-- install from external to internal? -->
<file>install_target_confirm.qml</file> <!-- overwrite internal storage? -->
<file>user_pass.qml</file> <!-- default user: password -->
<file>user_pass.qml</file> <!-- default user: username, password -->
<file>ssh_confirm.qml</file> <!-- sshd: enable or not? -->
<file>ssh_credentials.qml</file> <!-- sshd user: username, password -->
<file>fs_selection.qml</file> <!-- filesystem selection -->

View File

@@ -36,7 +36,7 @@ Item {
"More information:<br>" +
"https://postmarketos.org/ssh"
width: 500
width: 200
}
Button {
@@ -44,7 +44,7 @@ Item {
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: mainText.bottom
anchors.topMargin: 40
width: 500
width: 200
text: qsTr("Enable")
onClicked: {
@@ -57,7 +57,7 @@ Item {
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: firstButton.bottom
anchors.topMargin: 40
width: 500
width: 200
text: qsTr("Disable")
onClicked: {

View File

@@ -34,7 +34,7 @@ Item {
anchors.horizontalCenter: parent.horizontalCenter
anchors.topMargin: 50
width: 500
width: 200
}
Text {
@@ -45,7 +45,7 @@ Item {
anchors.horizontalCenter: parent.horizontalCenter
anchors.topMargin: 50
width: 500
width: 200
}
TextField {
@@ -59,7 +59,7 @@ Item {
anchors.horizontalCenter: parent.horizontalCenter
anchors.topMargin: 50
width: 500
width: 200
}
TextField {
@@ -73,7 +73,7 @@ Item {
anchors.horizontalCenter: parent.horizontalCenter
anchors.topMargin: 50
width: 500
width: 200
}
Text {
@@ -84,13 +84,13 @@ Item {
anchors.horizontalCenter: parent.horizontalCenter
anchors.topMargin: 50
width: 500
width: 200
}
Button {
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: errorTextPassword.bottom
anchors.topMargin: 40
width: 500
width: 200
text: qsTr("Continue")
onClicked: {

View File

@@ -12,16 +12,18 @@ import QtQuick.Window 2.3
import QtQuick.VirtualKeyboard 2.1
Item {
property var placeholder: (config.userPasswordNumeric
property var passPlaceholder: (config.userPasswordNumeric
? "PIN"
: "Password")
property var hints: (config.userPasswordNumeric
? Qt.ImhDigitsOnly
: Qt.ImhPreferLowercase)
property var validateFunc: (config.userPasswordNumeric
property var validatePassFunc: (config.userPasswordNumeric
? validatePin
: validatePassword);
property var validateNameFunc: validateUsername;
anchors.left: parent.left
anchors.top: parent.top
@@ -30,10 +32,36 @@ Item {
height: parent.height
Text {
id: description
id: usernameDescription
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: 30
anchors.topMargin: 10
wrapMode: Text.WordWrap
text: (function() {
return "Set the username of your user. The default" +
" username is \"" + config.username + "\".";
}())
width: 200
}
TextField {
id: username
anchors.top: usernameDescription.bottom
placeholderText: qsTr("Username")
onTextChanged: validateNameFunc(username, errorText)
text: config.username
anchors.horizontalCenter: parent.horizontalCenter
anchors.topMargin: 10
width: 200
}
Text {
id: userPassDescription
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: username.bottom
anchors.topMargin: 10
wrapMode: Text.WordWrap
text: (function() {
@@ -48,15 +76,15 @@ Item {
}
}())
width: 500
width: 200
}
TextField {
id: userPass
anchors.top: description.bottom
placeholderText: qsTr(placeholder)
anchors.top: userPassDescription.bottom
placeholderText: qsTr(passPlaceholder)
echoMode: TextInput.Password
onTextChanged: validateFunc(userPass, userPassRepeat, errorText)
onTextChanged: validatePassFunc(userPass, userPassRepeat, errorText)
text: config.userPassword
/* Let the virtual keyboard change to digits only */
@@ -68,22 +96,22 @@ Item {
}
anchors.horizontalCenter: parent.horizontalCenter
anchors.topMargin: 50
width: 500
anchors.topMargin: 10
width: 200
}
TextField {
id: userPassRepeat
anchors.top: userPass.bottom
placeholderText: qsTr(placeholder + " (repeat)")
placeholderText: qsTr(passPlaceholder + " (repeat)")
inputMethodHints: hints
echoMode: TextInput.Password
onTextChanged: validateFunc(userPass, userPassRepeat, errorText)
onTextChanged: validatePassFunc(userPass, userPassRepeat, errorText)
text: config.userPassword
anchors.horizontalCenter: parent.horizontalCenter
anchors.topMargin: 50
width: 500
anchors.topMargin: 10
width: 200
}
Text {
@@ -93,20 +121,21 @@ Item {
wrapMode: Text.WordWrap
anchors.horizontalCenter: parent.horizontalCenter
anchors.topMargin: 50
width: 500
anchors.topMargin: 10
width: 200
}
Button {
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: errorText.bottom
anchors.topMargin: 40
width: 500
anchors.topMargin: 10
width: 200
text: qsTr("Continue")
onClicked: {
if (validateFunc(userPass, userPassRepeat, errorText)) {
if (validatePassFunc(userPass, userPassRepeat, errorText) && validateNameFunc(username, errorText)) {
config.userPassword = userPass.text;
config.username = username.text;
navNext();
}
}

View File

@@ -26,8 +26,8 @@ Page
id: logo
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: 50
height: 250
anchors.topMargin: 10
height: 50
fillMode: Image.PreserveAspectFit
source: "file:///usr/share/calamares/branding/default-mobile/logo.png"
}
@@ -35,11 +35,11 @@ Page
id: waitText
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: logo.bottom
anchors.topMargin: 150
anchors.topMargin: 50
wrapMode: Text.WordWrap
text: "Formatting and mounting target partition. This may" +
" take up to two minutes, please be patient."
width: 500
" take up to ten minutes, please be patient."
width: 200
}
}
}

View File

@@ -28,8 +28,8 @@ Page
id: logo
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: 50
height: 250
anchors.topMargin: 10
height: 50
fillMode: Image.PreserveAspectFit
source: "file:///usr/share/calamares/branding/default-mobile/logo.png"
}
@@ -37,7 +37,7 @@ Page
id: mainText
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: logo.bottom
anchors.topMargin: 50
anchors.topMargin: 10
horizontalAlignment: Text.AlignRight
text: "You are about to install<br>" +
"<b>" + config.osName +
@@ -46,16 +46,16 @@ Page
"<b>" + config.userInterface + "</b><br>" +
"architecture " +
"<b>" + config.arch + "</b><br>" +
"on your " +
"on your <br>" +
"<b>" + config.device + "</b><br>"
width: 500
width: 200
}
Button {
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: mainText.bottom
anchors.topMargin: 50
width: 500
anchors.topMargin: 10
width: 200
text: qsTr("Continue")
onClicked: navNext()

View File

@@ -9,6 +9,7 @@ calamares_add_plugin( unpackfsc
# The workers for differently-packed filesystems
Runners.cpp
FSArchiverRunner.cpp
TarballRunner.cpp
UnsquashRunner.cpp
SHARED_LIB
)

View File

@@ -14,11 +14,40 @@
#include <QProcess>
static constexpr const int chunk_size = 137;
static const QString&
toolName()
{
static const QString name = QStringLiteral( "fsarchiver" );
return name;
}
void
FSArchiverRunner::fsarchiverProgress( QString line )
{
m_since++;
// Typical line of output is this:
// -[00][ 99%][REGFILEM] /boot/thing
// 5 9 ^21
if ( m_since >= chunk_size && line.length() > 21 && line[ 5 ] == '[' && line[ 9 ] == '%' )
{
m_since = 0;
double p = double( line.mid( 6, 3 ).toInt() ) / 100.0;
const QString filename = line.mid( 22 );
Q_EMIT progress( p, filename );
}
}
Calamares::JobResult
FSArchiverRunner::run()
FSArchiverRunner::checkPrerequisites( QString& fsarchiverExecutable ) const
{
const QString toolName = QStringLiteral( "fsarchiver" );
if ( !checkToolExists( toolName(), fsarchiverExecutable ) )
{
return Calamares::JobResult::internalError(
tr( "Missing tools" ),
tr( "The <i>%1</i> tool is not installed on the system." ).arg( toolName() ),
Calamares::JobResult::MissingRequirements );
}
if ( !checkSourceExists() )
{
@@ -27,28 +56,62 @@ FSArchiverRunner::run()
tr( "The source archive <i>%1</i> does not exist." ).arg( m_source ),
Calamares::JobResult::InvalidConfiguration );
}
return Calamares::JobResult::ok();
}
QString fsarchiverExecutable;
if ( !checkToolExists( toolName, fsarchiverExecutable ) )
Calamares::JobResult
FSArchiverRunner::checkDestination( QString& destinationPath ) const
{
destinationPath = Calamares::System::instance()->targetPath( m_destination );
if ( destinationPath.isEmpty() )
{
return Calamares::JobResult::internalError(
tr( "Missing tools" ),
tr( "The <i>%1</i> tool is not installed on the system." ).arg( toolName ),
Calamares::JobResult::MissingRequirements );
tr( "Invalid fsarchiver configuration" ),
tr( "No destination could be found for <i>%1</i>." ).arg( m_destination ),
Calamares::JobResult::InvalidConfiguration );
}
Calamares::Utils::Runner r( { fsarchiverExecutable,
QStringLiteral( "-v" ),
QStringLiteral( "restfs" ),
m_source,
QStringLiteral( "id=0,dest=%1" ).arg( m_destination ) } );
r.setLocation( Calamares::Utils::RunLocation::RunInHost ).enableOutputProcessing();
connect( &r, &decltype( r )::output, this, &FSArchiverRunner::fsarchiverProgress );
return r.run().explainProcess( toolName, std::chrono::seconds( 0 ) );
return Calamares::JobResult::ok();
}
void
FSArchiverRunner::fsarchiverProgress( QString line )
Calamares::JobResult
FSArchiverDirRunner::run()
{
cDebug() << Logger::SubEntry << line;
QString fsarchiverExecutable;
if ( auto res = checkPrerequisites( fsarchiverExecutable ); !res )
{
return res;
}
QString destinationPath;
if ( auto res = checkDestination( destinationPath ); !res )
{
return res;
}
Calamares::Utils::Runner r(
{ fsarchiverExecutable, QStringLiteral( "-v" ), QStringLiteral( "restdir" ), m_source, destinationPath } );
r.setLocation( Calamares::Utils::RunLocation::RunInHost ).enableOutputProcessing();
connect( &r, &decltype( r )::output, this, &FSArchiverDirRunner::fsarchiverProgress );
return r.run().explainProcess( toolName(), std::chrono::seconds( 0 ) );
}
Calamares::JobResult
FSArchiverFSRunner::run()
{
QString fsarchiverExecutable;
if ( auto res = checkPrerequisites( fsarchiverExecutable ); !res )
{
return res;
}
QString destinationPath;
if ( auto res = checkDestination( destinationPath ); !res )
{
return res;
}
Calamares::Utils::Runner r(
{ fsarchiverExecutable, QStringLiteral( "-v" ), QStringLiteral( "restfs" ), m_source, destinationPath } );
r.setLocation( Calamares::Utils::RunLocation::RunInHost ).enableOutputProcessing();
connect( &r, &decltype( r )::output, this, &FSArchiverFSRunner::fsarchiverProgress );
return r.run().explainProcess( toolName(), std::chrono::seconds( 0 ) );
}

View File

@@ -12,16 +12,48 @@
#include "Runners.h"
/** @brief Base class for runners of FSArchiver
*
*/
class FSArchiverRunner : public Runner
{
Q_OBJECT
public:
using Runner::Runner;
Calamares::JobResult run() override;
protected Q_SLOTS:
void fsarchiverProgress( QString line );
protected:
/** @brief Checks prerequisites, sets full path of fsarchiver in @p executable
*/
Calamares::JobResult checkPrerequisites( QString& executable ) const;
Calamares::JobResult checkDestination( QString& destinationPath ) const;
int m_since = 0;
};
/** @brief Running FSArchiver in **dir** mode
*
*/
class FSArchiverDirRunner : public FSArchiverRunner
{
public:
using FSArchiverRunner::FSArchiverRunner;
Calamares::JobResult run() override;
};
/** @brief Running FSArchiver in **dir** mode
*
*/
class FSArchiverFSRunner : public FSArchiverRunner
{
public:
using FSArchiverRunner::FSArchiverRunner;
Calamares::JobResult run() override;
};
#endif

View File

@@ -9,7 +9,7 @@
#include "Runners.h"
#include <utils/CalamaresUtilsSystem.h>
#include <utils/System.h>
#include <utils/Logger.h>
#include <QFileInfo>
@@ -21,7 +21,7 @@ Runner::Runner( const QString& source, const QString& destination )
{
}
Runner::~Runner() {}
Runner::~Runner() { }
bool
Runner::checkSourceExists() const

View File

@@ -0,0 +1,86 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2022 Adriaan de Groot <groot@kde.org>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
*
*/
#include "TarballRunner.h"
#include <utils/Logger.h>
#include <utils/Runner.h>
#include <utils/String.h>
#include <QString>
static constexpr const int chunk_size = 107;
Calamares::JobResult
TarballRunner::run()
{
if ( !checkSourceExists() )
{
return Calamares::JobResult::internalError(
tr( "Invalid tarball configuration" ),
tr( "The source archive <i>%1</i> does not exist." ).arg( m_source ),
Calamares::JobResult::InvalidConfiguration );
}
const QString toolName = QStringLiteral( "tar" );
QString tarExecutable;
if ( !checkToolExists( toolName, tarExecutable ) )
{
return Calamares::JobResult::internalError(
tr( "Missing tools" ),
tr( "The <i>%1</i> tool is not installed on the system." ).arg( toolName ),
Calamares::JobResult::MissingRequirements );
}
const QString destinationPath = Calamares::System::instance()->targetPath( m_destination );
if ( destinationPath.isEmpty() )
{
return Calamares::JobResult::internalError(
tr( "Invalid tarball configuration" ),
tr( "No destination could be found for <i>%1</i>." ).arg( m_destination ),
Calamares::JobResult::InvalidConfiguration );
}
// Get the stats (number of inodes) from the FS
{
m_total = 0;
Calamares::Utils::Runner r( { tarExecutable, QStringLiteral( "-tf" ), m_source } );
r.setLocation( Calamares::Utils::RunLocation::RunInHost ).enableOutputProcessing();
QObject::connect( &r, &decltype( r )::output, [ & ]( QString line ) { m_total++; } );
/* ignored */ r.run();
}
if ( m_total <= 0 )
{
cWarning() << "No stats could be obtained from" << tarExecutable << "-tf" << m_source;
}
// Now do the actual unpack
{
m_processed = 0;
m_since = 0;
Calamares::Utils::Runner r(
{ tarExecutable, QStringLiteral( "-xpvf" ), m_source, QStringLiteral( "-C" ), destinationPath } );
r.setLocation( Calamares::Utils::RunLocation::RunInHost ).enableOutputProcessing();
connect( &r, &decltype( r )::output, this, &TarballRunner::tarballProgress );
return r.run().explainProcess( toolName, std::chrono::seconds( 0 ) );
}
}
void
TarballRunner::tarballProgress( QString line )
{
m_processed++;
m_since++;
if ( m_since > chunk_size )
{
m_since = 0;
double p = m_total > 0 ? ( double( m_processed ) / double( m_total ) ) : 0.5;
Q_EMIT progress( p, tr( "Tarball extract file %1" ).arg( line ) );
}
}

View File

@@ -0,0 +1,35 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2022 Adriaan de Groot <groot@kde.org>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
*
*/
#ifndef UNPACKFSC_TARBALLRUNNER_H
#define UNPACKFSC_TARBALLRUNNER_H
#include "Runners.h"
/** @brief Use (GNU) tar for extracting a filesystem
*
*/
class TarballRunner : public Runner
{
public:
using Runner::Runner;
Calamares::JobResult run() override;
protected Q_SLOTS:
void tarballProgress( QString line );
private:
// Progress reporting
int m_total = 0;
int m_processed = 0;
int m_since = 0;
};
#endif

View File

@@ -10,6 +10,7 @@
#include "UnpackFSCJob.h"
#include "FSArchiverRunner.h"
#include "TarballRunner.h"
#include "UnsquashRunner.h"
#include <utils/Logger.h>
@@ -30,9 +31,15 @@ typeNames()
{ "fsarchiver", T::FSArchive },
{ "fsarchive", T::FSArchive },
{ "fsa", T::FSArchive },
{ "fsa-dir", T::FSArchive },
{ "fsa-block", T::FSArchiveFS },
{ "fsa-fs", T::FSArchiveFS },
{ "squashfs", T::Squashfs },
{ "squash", T::Squashfs },
{ "unsquash", T::Squashfs },
{ "tar", T::Tarball },
{ "tarball", T::Tarball },
{ "tgz", T::Tarball },
};
// clang-format on
return names;
@@ -43,7 +50,7 @@ UnpackFSCJob::UnpackFSCJob( QObject* parent )
{
}
UnpackFSCJob::~UnpackFSCJob() {}
UnpackFSCJob::~UnpackFSCJob() { }
QString
UnpackFSCJob::prettyName() const
@@ -64,29 +71,38 @@ UnpackFSCJob::exec()
switch ( m_type )
{
case Type::FSArchive:
r = std::make_unique< FSArchiverRunner >( m_source, m_destination );
r = std::make_unique< FSArchiverDirRunner >( m_source, m_destination );
break;
case Type::FSArchiveFS:
r = std::make_unique< FSArchiverFSRunner >( m_source, m_destination );
break;
case Type::Squashfs:
r = std::make_unique< UnsquashRunner >( m_source, m_destination );
break;
case Type::Tarball:
r = std::make_unique< TarballRunner >( m_source, m_destination );
break;
case Type::None:
default:
cDebug() << "Nothing to do.";
return Calamares::JobResult::ok();
}
connect( r.get(), &Runner::progress, [=]( qreal percent, const QString& message ) {
m_progressMessage = message;
Q_EMIT progress( percent );
} );
connect( r.get(),
&Runner::progress,
[ = ]( qreal percent, const QString& message )
{
m_progressMessage = message;
Q_EMIT progress( percent );
} );
return r->run();
}
void
UnpackFSCJob::setConfigurationMap( const QVariantMap& map )
{
QString source = CalamaresUtils::getString( map, "source" );
QString sourceTypeName = CalamaresUtils::getString( map, "sourcefs" );
QString source = Calamares::getString( map, "source" );
QString sourceTypeName = Calamares::getString( map, "sourcefs" );
if ( source.isEmpty() || sourceTypeName.isEmpty() )
{
cWarning() << "Skipping item with bad source data:" << map;
@@ -99,7 +115,7 @@ UnpackFSCJob::setConfigurationMap( const QVariantMap& map )
cWarning() << "Skipping item with source type None";
return;
}
QString destination = CalamaresUtils::getString( map, "destination" );
QString destination = Calamares::getString( map, "destination" );
if ( destination.isEmpty() )
{
cWarning() << "Skipping item with empty destination";

View File

@@ -23,7 +23,9 @@ public:
{
None, /// << Invalid
FSArchive,
FSArchiveFS,
Squashfs,
Tarball,
};
explicit UnpackFSCJob( QObject* parent = nullptr );

View File

@@ -38,7 +38,7 @@ UnsquashRunner::run()
Calamares::JobResult::MissingRequirements );
}
const QString destinationPath = CalamaresUtils::System::instance()->targetPath( m_destination );
const QString destinationPath = Calamares::System::instance()->targetPath( m_destination );
if ( destinationPath.isEmpty() )
{
return Calamares::JobResult::internalError(
@@ -52,12 +52,15 @@ UnsquashRunner::run()
m_inodes = -1;
Calamares::Utils::Runner r( { unsquashExecutable, QStringLiteral( "-s" ), m_source } );
r.setLocation( Calamares::Utils::RunLocation::RunInHost ).enableOutputProcessing();
QObject::connect( &r, &decltype( r )::output, [&]( QString line ) {
if ( line.startsWith( "Number of inodes " ) )
{
m_inodes = line.split( ' ', SplitSkipEmptyParts ).last().toInt();
}
} );
QObject::connect( &r,
&decltype( r )::output,
[ & ]( QString line )
{
if ( line.startsWith( "Number of inodes " ) )
{
m_inodes = line.split( ' ', SplitSkipEmptyParts ).last().toInt();
}
} );
/* ignored */ r.run();
}
if ( m_inodes <= 0 )

View File

@@ -14,7 +14,6 @@
/** @brief Use Unsquash for extracting a filesystem
*
* NOTE: not implemented
*/
class UnsquashRunner : public Runner
{

View File

@@ -0,0 +1,2 @@
---
rootMountPoint: /tmp/fstest

View File

@@ -0,0 +1,4 @@
---
source: /tmp/src.fsa
sourcefs: fsarchive
destination: "/calasrc"

View File

@@ -2,7 +2,7 @@
# SPDX-License-Identifier: CC0-1.0
#
# Unpack a filesystem. Supported ways to "pack" the filesystem are:
# - fsarchiver
# - fsarchiver in *savedir/restdir* mode (directories, not block devices)
# - squashfs
#
# Configuration:
@@ -21,11 +21,19 @@
# - *sourcefs* the type of the source files; valid entries are
# - `none` (this entry is ignored; kind of useless)
# - `fsarchiver`
# Aliases of this are `fsarchive`, `fsa` and `fsa-dir`. Uses
# fsarchiver in "restdir" mode.
# - `fsarchiver-block`
# Aliases of this are `fsa-block` and `fsa-fs`. Uses fsarchiver
# in "restfs" mode.
# - `squashfs`
# Aliases of this are `squash` and `unsquash`.
# - `tar`
# - *destination* path relative to rootMountPoint (so in the target
# system) where this filesystem is unpacked. It may be an
# empty string, which effectively is / (the root) of the target
# system.
#
source: /data/rootfs.fsa
sourcefs: fsarchiver
destination: "/"