Compare commits
172 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
7730ac7b00
|
|||
|
bee59a2fb3
|
|||
|
00d34dfc49
|
|||
|
ac810f2ee3
|
|||
|
5592c57642
|
|||
|
8f6b8e7a95
|
|||
|
1826dbfead
|
|||
|
b7bf497cd6
|
|||
|
ae70926ed1
|
|||
|
aac3c8b59e
|
|||
|
260547f6b6
|
|||
|
730cfd697c
|
|||
|
292e3071c6
|
|||
|
8a90ef4794
|
|||
|
9c7f9b46c5
|
|||
|
bf8b29c975
|
|||
|
9c9891d98e
|
|||
|
de05361b28
|
|||
|
9e3a02d96d
|
|||
|
881f771ed1
|
|||
|
bc08f59e74
|
|||
|
e35b352a2a
|
|||
|
44b476e1d0
|
|||
|
f3feff4dc2
|
|||
|
d00bcd4144
|
|||
|
34bf7909ad
|
|||
|
50773635e8
|
|||
|
a75964e391
|
|||
|
7a44c4c291
|
|||
|
e25935fa75
|
|||
|
40d49cb9e2
|
|||
|
3a437a8bfe
|
|||
|
8e2fc2ec6a
|
|||
|
c7221247f2
|
|||
|
57f86ef5f7
|
|||
|
a9ba4be111
|
|||
|
6f5fc95e82
|
|||
|
680ee39e94
|
|||
|
ec442193f5
|
|||
|
a0fc2c1019
|
|||
|
9e62cedff0
|
|||
|
bfd43ff41a
|
|||
|
6fb48bd3a8
|
|||
|
61fa81dd24
|
|||
|
45ff906097
|
|||
|
2daac4a455
|
|||
|
d65f08cfad
|
|||
|
7268e7e23d
|
|||
|
d4bef2fe91
|
|||
|
a1255eb5c6
|
|||
|
cbdb386ba0
|
|||
|
4df4b2bff3
|
|||
|
73cf60e876
|
|||
|
07ff62af55
|
|||
|
22a95badcf
|
|||
|
a1adefe890
|
|||
|
1f465bf647
|
|||
|
ba2dc4637e
|
|||
|
ccdbdf4adf
|
|||
|
1c74b59459
|
|||
|
1cb48ce4e7
|
|||
|
17f9c79983
|
|||
|
3cdfdcfaeb
|
|||
|
9e59be79c3
|
|||
|
080a77c5e3
|
|||
|
7e40a565cc
|
|||
|
338f6b87ee
|
|||
|
4f4afec6b2
|
|||
|
640aa15af8
|
|||
|
73f73ff17e
|
|||
|
6c8e7c0f78
|
|||
|
5762f59d95
|
|||
|
affba77349
|
|||
|
87977ce8d7
|
|||
|
b5f00d8dd2
|
|||
|
349cc28d7d
|
|||
|
fc1bc218a4
|
|||
|
d399fc5fa6
|
|||
|
4d36e86f51
|
|||
|
a0f269cf90
|
|||
|
7831b537d7
|
|||
|
2c5f08330a
|
|||
|
a63021cde7
|
|||
|
b408c84a8c
|
|||
|
2a3824a991
|
|||
|
06121343e7
|
|||
|
3c12d9514c
|
|||
|
5f108c607b
|
|||
|
95eb6c15e0
|
|||
|
4a598c854a
|
|||
|
9f46b9bb1b
|
|||
|
14d138cae4
|
|||
|
8e2e74a227
|
|||
|
d0e431329d
|
|||
|
75113980f0
|
|||
|
4d123b6f5d
|
|||
|
a09278b63f
|
|||
|
dd71664b9e
|
|||
|
2aaf1cbfd5
|
|||
|
e20523470f
|
|||
|
c56db3de04
|
|||
|
81dfac3762
|
|||
|
43ecf7f54f
|
|||
|
96e5721ad8
|
|||
|
cef3b291d1
|
|||
|
6e59e1d4c4
|
|||
|
3a5efffc61
|
|||
|
53942aece0
|
|||
|
e98a8320fb
|
|||
|
038700e22d
|
|||
|
4857a9fda9
|
|||
|
289a70c10c
|
|||
|
8224a24d02
|
|||
|
0ab90857e5
|
|||
|
d6212deaa9
|
|||
|
754b6e8802
|
|||
|
053998d1c0
|
|||
|
218b0707a4
|
|||
|
7c11f53520
|
|||
|
be0844b50b
|
|||
|
24370461ea
|
|||
|
5d6d1c6db8
|
|||
|
23df7656e5
|
|||
|
a28a64310a
|
|||
|
7aa1276e2c
|
|||
|
9df1f444bc
|
|||
|
7fe54d0791
|
|||
|
4249282052
|
|||
|
5e66f99816
|
|||
|
35f77ba33d
|
|||
|
d8e67fe861
|
|||
|
68850f0ed2
|
|||
|
aa9cb13648
|
|||
|
8b7af60239
|
|||
|
ee0082baa1
|
|||
|
0b0fcd8ce4
|
|||
|
99006b9ede
|
|||
|
ff98a1e186
|
|||
|
7daca57714
|
|||
|
d409406fde
|
|||
|
0de970239f
|
|||
|
7d6bba42b2
|
|||
|
1184ba17d9
|
|||
|
d25ab9b4da
|
|||
|
2c9e4e6260
|
|||
|
9e3cca8efc
|
|||
|
fd3c2c998c
|
|||
|
e76db05206
|
|||
|
ee7a5fdaab
|
|||
|
a4e46a4309
|
|||
|
92bae9e4a6
|
|||
|
43c1053bd7
|
|||
|
3f83316fa8
|
|||
|
fc62c7e9c2
|
|||
|
4473f0eee7
|
|||
|
c6f066b0d9
|
|||
|
2420bf2404
|
|||
|
de9647a00d
|
|||
|
c412cd5d33
|
|||
|
05ae9c36c3
|
|||
|
98d47d497c
|
|||
|
a7a5055ee8
|
|||
|
1fa2c72ef7
|
|||
|
0d26227169
|
|||
|
241bd5c219
|
|||
|
40fd289a9f
|
|||
|
d1198b9d04
|
|||
|
c629e0f196
|
|||
|
f6ee07429b
|
|||
|
a9d4b9ac91
|
|||
|
d5e0069889
|
|||
|
0fb4c1bf5c
|
@@ -2,7 +2,3 @@ out/
|
|||||||
local-repo/
|
local-repo/
|
||||||
configs/baseline/airootfs/etc/systemd/system/multi-user.target.wants/
|
configs/baseline/airootfs/etc/systemd/system/multi-user.target.wants/
|
||||||
configs/releng/airootfs/etc/systemd/system/multi-user.target.wants/
|
configs/releng/airootfs/etc/systemd/system/multi-user.target.wants/
|
||||||
configs/baseline/airootfs/usr/lib/
|
|
||||||
configs/baseline/airootfs/usr/bin/
|
|
||||||
configs/baseline/airootfs/usr/include/
|
|
||||||
configs/baseline/airootfs/usr/share/calamares/branding/default/
|
|
||||||
|
|||||||
+16
-1
@@ -1,7 +1,22 @@
|
|||||||
===============
|
=======
|
||||||
|
Authors
|
||||||
|
=======
|
||||||
|
|
||||||
|
FWS
|
||||||
|
===
|
||||||
|
|
||||||
|
FWS is a fork of archiso. The FWS-specific work (build chain, installer
|
||||||
|
integration, package recipes under ``pkgbuilds/``) is © the FWS contributors,
|
||||||
|
distributed under ``GPL-3.0-or-later`` (see ``COPYRIGHT.md``).
|
||||||
|
|
||||||
|
* FWS contributors <suzuku295@gmail.com>
|
||||||
|
|
||||||
Archiso Authors
|
Archiso Authors
|
||||||
===============
|
===============
|
||||||
|
|
||||||
|
The build system (``mkarchiso``, profiles, man pages) derives from archiso and
|
||||||
|
retains the authorship of its original contributors:
|
||||||
|
|
||||||
* 2hexed <2hexed@protonmail.com>
|
* 2hexed <2hexed@protonmail.com>
|
||||||
* Aaron Griffin <aaron@archlinux.org>
|
* Aaron Griffin <aaron@archlinux.org>
|
||||||
* Adam Purkrt <adam@purkrt.net>
|
* Adam Purkrt <adam@purkrt.net>
|
||||||
|
|||||||
+42
-2
@@ -2,15 +2,41 @@
|
|||||||
Changelog
|
Changelog
|
||||||
#########
|
#########
|
||||||
|
|
||||||
[XX] - YYYY-MM-DD
|
[0.6.0] - 2026-07-07
|
||||||
=================
|
====================
|
||||||
|
|
||||||
Added
|
Added
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
- **Installateur Anaconda 45 porté sur Arch** (payload LiveOS) : page « Récapitulatif avant installation » avec bouton
|
||||||
|
Précédent, choix du bureau intégré (GNOME, KDE, XFCE, Hyprland, i3, CLI) avec compatibilité VR affichée, splash de
|
||||||
|
préparation alimenté en direct par les logs (diagnostic automatique en cas de blocage), garde-fou RAM (< 2 Go),
|
||||||
|
mécanisme de retry réseau pour l'installation du bureau (``fws-desktop-retry``).
|
||||||
|
- **Outillage FWS** : ``fws-hello`` (accueil 1er démarrage), ``fws-update`` + indicateur de mises à jour,
|
||||||
|
``fws-keys`` (raccourcis réels), ``fws-powermenu``, ``fws-about``, ``fws-vr-setup`` (SteamVR/ALVR/Monado),
|
||||||
|
``fws-proton-ge``, ``fws-setup-hardware`` (drivers GPU/VM/audio/Bluetooth), ``fws-dnd``.
|
||||||
|
- **Récupération système** (« point de restauration ») : application GTK ``fws-recovery-gui`` + moteur ``fws-recovery``
|
||||||
|
(GRUB, initramfs, pacman, chroot), accessible depuis le live (entrée de boot), le menu GRUB du système installé
|
||||||
|
(``fws-recovery.target``) et son menu d'applications (élévation polkit).
|
||||||
|
- **Swap zram** sur le live et le système installé (``zram-generator``).
|
||||||
|
- **firewalld** activé par défaut sur le système installé.
|
||||||
|
- Bureaux Hyprland et i3 à parité visuelle (waybar/polybar, wofi/rofi, Catppuccin Mocha), thème SDDM « fws »,
|
||||||
|
bannière GDM.
|
||||||
|
- **Choix du nom de machine à l'installation** : champ « Nom de machine » dans la page Utilisateur d'anaconda,
|
||||||
|
appliqué au système installé (``/etc/hostname``, repli ``fws``).
|
||||||
|
- **Script de build interactif** (``build-offi.sh``) : version (``major.minor.build``) et variante (``cli``, ``gnome``,
|
||||||
|
``kde``…) demandées sur l'hôte avant d'entrer dans le conteneur, ISO nommée
|
||||||
|
``fws-<version>-<variante>-<AAAA.MM.JJ>.iso``, logo FWS dans fastfetch.
|
||||||
|
|
||||||
Changed
|
Changed
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- **Branding FWS complet** : l'installateur s'annonce « FWS 0.6 » (variables ``ANACONDA_PRODUCT*``), splash FWS au menu
|
||||||
|
de boot BIOS (l'image Arch d'archiso est remplacée), ``/etc/issue`` sans version de noyau, filtres d'affichage
|
||||||
|
Fedora/Arch sur le splash et le journal de récupération.
|
||||||
|
- Toutes les entrées de boot plafonnent les workers udev bloqués (``udev.event_timeout=45``) ; le menu BIOS démarre
|
||||||
|
explicitement l'entrée FWS (``DEFAULT fws``).
|
||||||
|
- ``systemd-timesyncd`` explicitement activé sur le système installé pour éviter la dérive d'horloge (TLS, pacman).
|
||||||
- Use xz compression for the baseline profile's bootstrap tarball so that it has more differences when compared to the
|
- Use xz compression for the baseline profile's bootstrap tarball so that it has more differences when compared to the
|
||||||
releng profile.
|
releng profile.
|
||||||
- Match network interfaces by their type, instead of name, in systemd-networkd configuration.
|
- Match network interfaces by their type, instead of name, in systemd-networkd configuration.
|
||||||
@@ -21,12 +47,26 @@ Deprecated
|
|||||||
Fixed
|
Fixed
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
- Watchdog du splash qui affichait son diagnostic PAR-DESSUS l'installateur (il se désarme désormais dès que la GUI
|
||||||
|
d'anaconda est à l'écran, et mesure l'inactivité en itérations — insensible aux sauts d'horloge des VM).
|
||||||
|
- Gel de l'installateur sur machines à faible RAM (1 Go) : zram + avertissement préalable.
|
||||||
|
- Profils ``baseline``/``releng`` synchronisés (la fusion baseline-écrase-releng avait fait perdre ``firewalld``,
|
||||||
|
le cap udev et les entrées de boot FWS d'ISO précédentes).
|
||||||
|
- DNS du système installé (NetworkManager + systemd-resolved), hook ``lvm2`` dans l'initramfs, GRUB de secours
|
||||||
|
``--removable`` en UEFI.
|
||||||
|
- Disposition clavier dérivée de la locale complète et non de la seule langue : ``fr_CH`` donne désormais ``ch(fr)``
|
||||||
|
au lieu de ``fr``, appliqué à la console (``vconsole.conf``) et à X11 (via langtable) ; anaconda écrivait par
|
||||||
|
ailleurs un ``/etc/hostname`` vide sur le système installé.
|
||||||
|
- DNS dans le conteneur de build : ``podman run --network=host`` pour passer par la pile réseau de l'hôte
|
||||||
|
(corrige les timeouts avec firewalld/NAT).
|
||||||
- Use ``systemd-run`` to invoke ``curl`` with a transient service that depends on ``network-online.target`` since no
|
- Use ``systemd-run`` to invoke ``curl`` with a transient service that depends on ``network-online.target`` since no
|
||||||
services are currently pulling in ``network_online.target``.
|
services are currently pulling in ``network_online.target``.
|
||||||
|
|
||||||
Removed
|
Removed
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- ``configs/baseline/syslinux/syslinux-linux.cfg`` (label ``arch`` stock, orphelin et sans cap udev).
|
||||||
|
|
||||||
[87] - 2025-10-29
|
[87] - 2025-10-29
|
||||||
=================
|
=================
|
||||||
|
|
||||||
|
|||||||
+23
-2
@@ -2,8 +2,29 @@
|
|||||||
Contributing
|
Contributing
|
||||||
============
|
============
|
||||||
|
|
||||||
These are the contribution guidelines for archiso.
|
These are the contribution guidelines for **FWS**. FWS is a fork of `archiso
|
||||||
All contributions fall under the terms of the GPL-3.0-or-later (see `LICENSE <LICENSE>`_).
|
<https://gitlab.archlinux.org/archlinux/archiso>`_; the build-system parts
|
||||||
|
derived from archiso retain their original history and authorship (see
|
||||||
|
`AUTHORS.rst <AUTHORS.rst>`_).
|
||||||
|
|
||||||
|
Licensing of contributions (inbound = outbound)
|
||||||
|
===============================================
|
||||||
|
|
||||||
|
All contributions are accepted under the **same license as the project**,
|
||||||
|
``GPL-3.0-or-later`` (see `LICENSE <LICENSE>`_). By submitting a contribution you
|
||||||
|
agree that it is licensed under ``GPL-3.0-or-later`` and that you have the right
|
||||||
|
to submit it under that license.
|
||||||
|
|
||||||
|
Sign off every commit to certify the `Developer Certificate of Origin 1.1
|
||||||
|
<https://developercertificate.org/>`_:
|
||||||
|
|
||||||
|
.. code:: bash
|
||||||
|
|
||||||
|
git commit --signoff # adds a "Signed-off-by: Name <email>" trailer
|
||||||
|
|
||||||
|
For the full licensing, third-party and trademark picture, see `LICENSING.md
|
||||||
|
<LICENSING.md>`_, `THIRD-PARTY-LICENSES.md <THIRD-PARTY-LICENSES.md>`_ and
|
||||||
|
`TRADEMARKS.md <TRADEMARKS.md>`_.
|
||||||
|
|
||||||
Editorconfig
|
Editorconfig
|
||||||
============
|
============
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
# Droits d'auteur — FWS
|
||||||
|
|
||||||
|
`SPDX-License-Identifier: GPL-3.0-or-later`
|
||||||
|
|
||||||
|
FWS est une distribution Linux live/installable dérivée d'**Arch Linux**, dont le
|
||||||
|
système de construction est un fork d'**archiso**. Ce fichier identifie les
|
||||||
|
titulaires de droits sur le code **du dépôt** ; les logiciels **embarqués**
|
||||||
|
(Anaconda, paquets Python, paquets Arch de l'ISO…) restent la propriété de leurs
|
||||||
|
auteurs respectifs — voir [THIRD-PARTY-LICENSES.md](THIRD-PARTY-LICENSES.md).
|
||||||
|
|
||||||
|
## Code du dépôt (système de build FWS)
|
||||||
|
|
||||||
|
```
|
||||||
|
Copyright (C) 2026 Contributeurs FWS (« FWS contributors »)
|
||||||
|
Copyright (C) Arch Linux / Archiso Authors — voir AUTHORS.rst
|
||||||
|
```
|
||||||
|
|
||||||
|
Sont couverts par les droits FWS, sous **GPL-3.0-or-later** :
|
||||||
|
|
||||||
|
- les scripts de construction (`build.sh`, `build-offi.sh`, `setup-aur.sh`,
|
||||||
|
`scripts/`) ;
|
||||||
|
- les profils et overlays `configs/baseline/` et `configs/releng/` modifiés
|
||||||
|
par FWS ;
|
||||||
|
- les recettes de paquets `pkgbuilds/*/PKGBUILD` rédigées ou adaptées par FWS ;
|
||||||
|
- la documentation FWS (`README.md`, `environnement.md`, `docs/`).
|
||||||
|
|
||||||
|
Sont des œuvres d'**archiso** (Arch Linux), conservées sous **GPL-3.0-or-later** :
|
||||||
|
|
||||||
|
- `fws/mkarchiso`, `Makefile`, `man/`, `CHANGELOG.rst` et la structure de
|
||||||
|
profil héritée. Les auteurs originaux sont listés dans [AUTHORS.rst](AUTHORS.rst).
|
||||||
|
|
||||||
|
## Titulaire / entité
|
||||||
|
|
||||||
|
Le titulaire collectif est désigné ici par « Contributeurs FWS ». Si le projet
|
||||||
|
adopte une personne morale (association, société) ou un mainteneur nommé comme
|
||||||
|
titulaire de référence, remplacer « Contributeurs FWS » par cette entité dans
|
||||||
|
ce fichier et dans les en-têtes SPDX.
|
||||||
|
|
||||||
|
## Marques
|
||||||
|
|
||||||
|
Les noms et logos cités (Arch Linux, Red Hat, Fedora, Anaconda, Windows…) sont
|
||||||
|
des marques de leurs détenteurs respectifs. Voir [TRADEMARKS.md](TRADEMARKS.md).
|
||||||
|
|
||||||
|
## Résumé des licences
|
||||||
|
|
||||||
|
| Élément | Licence |
|
||||||
|
|---|---|
|
||||||
|
| Code du dépôt FWS (build, configs, PKGBUILDs, docs) | `GPL-3.0-or-later` |
|
||||||
|
| Texte de licence intégral | [LICENSE](LICENSE) |
|
||||||
|
| Logiciels tiers embarqués | licences propres — [THIRD-PARTY-LICENSES.md](THIRD-PARTY-LICENSES.md) |
|
||||||
|
| Attributions Apache/MIT/BSD | [NOTICE](NOTICE) |
|
||||||
|
| Politique de licences & obtention des sources | [LICENSING.md](LICENSING.md) |
|
||||||
|
| Marques & non-affiliation | [TRADEMARKS.md](TRADEMARKS.md) |
|
||||||
|
|
||||||
|
> **Avertissement.** Ces documents constituent une base de conformité FOSS
|
||||||
|
> sérieuse et de bonne foi, mais ne sont pas un avis juridique. Avant toute
|
||||||
|
> diffusion publique large ou commerciale, faites-les valider par un conseil
|
||||||
|
> spécialisé en propriété intellectuelle / open source — en particulier les
|
||||||
|
> points signalés ⚠ dans [THIRD-PARTY-LICENSES.md](THIRD-PARTY-LICENSES.md).
|
||||||
+103
@@ -0,0 +1,103 @@
|
|||||||
|
# Politique de licences & obtention des sources — FWS
|
||||||
|
|
||||||
|
`SPDX-License-Identifier: GPL-3.0-or-later`
|
||||||
|
|
||||||
|
## 1. Licence du projet
|
||||||
|
|
||||||
|
Le code du dépôt FWS (système de build, profils, overlays, PKGBUILD et docs
|
||||||
|
rédigés par FWS) est distribué sous **GNU General Public License v3.0 ou
|
||||||
|
ultérieure** (`GPL-3.0-or-later`). Cette licence est **héritée d'archiso**, dont
|
||||||
|
FWS est un fork : une œuvre dérivée d'archiso (GPL-3.0-or-later) ne peut être
|
||||||
|
redistribuée que sous GPL-3.0-or-later.
|
||||||
|
|
||||||
|
Texte intégral : [LICENSE](LICENSE).
|
||||||
|
|
||||||
|
Périmètre exact (couvert / hérité) : voir [COPYRIGHT.md](COPYRIGHT.md).
|
||||||
|
Logiciels embarqués (licences distinctes) : voir
|
||||||
|
[THIRD-PARTY-LICENSES.md](THIRD-PARTY-LICENSES.md).
|
||||||
|
|
||||||
|
## 2. En-têtes SPDX (recommandation)
|
||||||
|
|
||||||
|
Pour une traçabilité « béton », ajouter en tête de chaque fichier source rédigé
|
||||||
|
par FWS :
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
# SPDX-FileCopyrightText: 2026 Contributeurs FWS
|
||||||
|
```
|
||||||
|
|
||||||
|
(Les fichiers hérités d'archiso conservent leurs en-têtes d'origine.)
|
||||||
|
|
||||||
|
## 3. Obligation de fourniture des sources (GPL/LGPL)
|
||||||
|
|
||||||
|
FWS distribue des **binaires** couverts par la GPL/LGPL/AGPL : l'ISO
|
||||||
|
(`out/FWS-*.iso`) et les paquets (`local-repo/*.pkg.tar.zst`). La GPL impose de
|
||||||
|
fournir la **source correspondante** de ces binaires.
|
||||||
|
|
||||||
|
Pour FWS, la source correspondante est :
|
||||||
|
|
||||||
|
1. **le présent dépôt** (système de build, profils, recettes `pkgbuilds/`), et
|
||||||
|
2. **les tarballs amont** référencés par `source=()` dans chaque PKGBUILD
|
||||||
|
(téléchargés à l'identique depuis les URL listées dans
|
||||||
|
[THIRD-PARTY-LICENSES.md](THIRD-PARTY-LICENSES.md)), et
|
||||||
|
3. pour les paquets Arch agrégés dans l'ISO, **les sources publiées par Arch
|
||||||
|
Linux** pour chaque paquet (`pkgctl`/dépôts amont Arch).
|
||||||
|
|
||||||
|
### Offre écrite (GPLv3 §6 / GPLv2 §3b)
|
||||||
|
|
||||||
|
> Pour tout binaire couvert par la GPL/LGPL distribué dans une image ou un paquet
|
||||||
|
> FWS, le projet FWS s'engage à fournir, sur demande et pour une durée d'au moins
|
||||||
|
> trois (3) ans, la source correspondante complète sous une forme lisible par
|
||||||
|
> machine, soit via le dépôt public du projet, soit sur un support physique au
|
||||||
|
> coût de distribution.
|
||||||
|
>
|
||||||
|
> - **Dépôt public (source) :** https://github.com/You-re-like-Windows-a-bitch/fws
|
||||||
|
> - **Contact :** suzuku295@gmail.com
|
||||||
|
>
|
||||||
|
> *« FWS offers, for any GPL/LGPL-covered binary it distributes, to provide the
|
||||||
|
> complete corresponding source code, for at least three years, via the project
|
||||||
|
> repository (https://github.com/You-re-like-Windows-a-bitch/fws) or on physical
|
||||||
|
> media at cost. Contact: suzuku295@gmail.com. »*
|
||||||
|
|
||||||
|
> **Condition d'effectivité :** l'offre n'est réellement opposable que si le dépôt
|
||||||
|
> ci-dessus est **publiquement accessible** et contient `pkgbuilds/` (recettes +
|
||||||
|
> URL `source=()`). Tant que le dépôt reste privé, publier au minimum les sources
|
||||||
|
> correspondantes des binaires diffusés.
|
||||||
|
|
||||||
|
## 4. Reproductibilité
|
||||||
|
|
||||||
|
Le build honore `SOURCE_DATE_EPOCH` (cf. `profiledef.sh`, horodatages d'ISO et
|
||||||
|
de label) pour des reconstructions déterministes — utile pour prouver la
|
||||||
|
correspondance source/binaire.
|
||||||
|
|
||||||
|
## 5. Contributions
|
||||||
|
|
||||||
|
Les contributions entrantes sont acceptées sous la **même** licence que le
|
||||||
|
projet (« inbound = outbound », `GPL-3.0-or-later`), avec attestation d'origine
|
||||||
|
**DCO**. Voir [CONTRIBUTING.rst](CONTRIBUTING.rst).
|
||||||
|
|
||||||
|
## 6. Liste de contrôle conformité (avant release publique)
|
||||||
|
|
||||||
|
- [x] `LICENSE` (GPL-3.0-or-later) présent à la racine
|
||||||
|
- [x] `COPYRIGHT.md`, `NOTICE`, `THIRD-PARTY-LICENSES.md`, `TRADEMARKS.md` rédigés
|
||||||
|
- [x] Offre écrite §3 complétée avec URL (dépôt) + contact e-mail
|
||||||
|
- [x] `os-release` FWS livré — hook `zz-fws-os-release.hook` (le live ne s'annonce
|
||||||
|
plus « Arch Linux ») ; `motd` ne renvoie plus vers `archlinux.org`
|
||||||
|
- [ ] **Dépôt rendu publiquement accessible** (sinon l'offre écrite n'est pas
|
||||||
|
opposable) — action hors-code
|
||||||
|
- [x] Branding Red Hat/Fedora retiré de l'UI Anaconda : nom de produit **FWS**
|
||||||
|
via les variables `ANACONDA_PRODUCTNAME`/`ANACONDA_PRODUCTVERSION`
|
||||||
|
(exportées par le `.xinitrc` du live, lues depuis l'os-release FWS —
|
||||||
|
l'en-tête affiche « FWS 0.6 INSTALLATION ») ; visuel **Arch** du menu de
|
||||||
|
boot BIOS remplacé par un splash FWS ; le caractère « version modifiée
|
||||||
|
d'Anaconda » reste documenté ici et dans TRADEMARKS.md
|
||||||
|
- [ ] Décision tranchée sur `python-iso639` (AGPL-3.0-only) : garder ou remplacer
|
||||||
|
- [ ] Revue par un conseil FOSS (recommandé avant diffusion commerciale)
|
||||||
|
|
||||||
|
> Les étiquettes `license=` des PKGBUILD **présents dans `pkgbuilds/`** sont déjà
|
||||||
|
> en SPDX exact. Les libellés imprécis relevés (`satyr` → `GPL`, `python-pid` →
|
||||||
|
> `Apache`…) concernent des paquets de `local-repo/` **sans PKGBUILD dans ce
|
||||||
|
> dépôt** (construits depuis l'AUR) : à corriger à la source AUR, pas ici.
|
||||||
|
|
||||||
|
> **Ceci n'est pas un avis juridique.** Base de conformité de bonne foi au
|
||||||
|
> 2026-07-07.
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
FWS — Avis d'attribution / Attribution NOTICE
|
||||||
|
=============================================
|
||||||
|
|
||||||
|
FWS (« FWS contributors »), 2026.
|
||||||
|
Distribution Linux dérivée d'Arch Linux ; système de build dérivé d'archiso.
|
||||||
|
|
||||||
|
Ce fichier regroupe les attributions exigées par les licences permissives
|
||||||
|
(Apache-2.0, MIT, BSD) des composants redistribués par FWS. Il complète :
|
||||||
|
- LICENSE — GPL-3.0-or-later (projet)
|
||||||
|
- COPYRIGHT.md — droits d'auteur du dépôt
|
||||||
|
- THIRD-PARTY-LICENSES.md — inventaire complet & compatibilité
|
||||||
|
- TRADEMARKS.md — marques & non-affiliation
|
||||||
|
|
||||||
|
L'absence d'un composant ici ne vaut pas absence d'obligation : voir
|
||||||
|
THIRD-PARTY-LICENSES.md pour l'inventaire exhaustif et les avis GPL/LGPL/AGPL
|
||||||
|
(préservés dans /usr/share/licenses/<paquet>/ sur le système).
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
Base du dépôt
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
archiso — Copyright (C) Arch Linux / Archiso Authors (voir AUTHORS.rst)
|
||||||
|
GPL-3.0-or-later — https://gitlab.archlinux.org/archlinux/archiso
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
Composants sous Apache-2.0
|
||||||
|
(Apache-2.0 §4 : conservation des avis de droit d'auteur et de licence ;
|
||||||
|
ce NOTICE accompagne les œuvres redistribuées.)
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
requests-file (python-requests-file) — Copyright (C) David Shea
|
||||||
|
https://github.com/dashea/requests-file
|
||||||
|
requests-ftp (python-requests-ftp) — Copyright (C) Cory Benfield
|
||||||
|
https://github.com/Lukasa/requests-ftp
|
||||||
|
pid (python-pid) — Copyright (C) trbs and contributors
|
||||||
|
https://github.com/trbs/pid
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
Composants sous MIT
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
python-xkbregistry — Copyright (C) Stephen Early
|
||||||
|
https://github.com/sde1000/python-xkbregistry
|
||||||
|
WinBoat (winboat-bin) — Copyright (C) WinBoat authors (TibixDev)
|
||||||
|
https://www.winboat.app
|
||||||
|
langtable (python-langtable, partie MIT) — Copyright (C) Mike FABIAN
|
||||||
|
https://github.com/mike-fabian/langtable
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
Composants sous licence permissive de type BSD / custom
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
xmlrpc-c (libxmlrpc) — Copyright (C) les auteurs de xmlrpc-c
|
||||||
|
Licence permissive de type BSD (« custom ») — voir le source amont
|
||||||
|
https://xmlrpc-c.sourceforge.net/
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
Marques
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
Arch Linux, Red Hat, Fedora, Anaconda, Windows, Microsoft, GNOME, KDE,
|
||||||
|
Plasma, Xfce, Hyprland, GTK, Linux et WinBoat sont des marques de leurs
|
||||||
|
détenteurs respectifs. FWS n'est affilié à aucun d'eux. Voir TRADEMARKS.md.
|
||||||
@@ -1,85 +1,331 @@
|
|||||||
# FWS
|
# FWS
|
||||||
|
|
||||||
**FWS** est une distribution Linux live/installable basée sur **Arch Linux**, livrée sous forme d'ISO bootable BIOS/UEFI avec l'installeur graphique **Calamares** lancé automatiquement au démarrage.
|
**FWS** est une distribution Linux live/installable basée sur **Arch Linux**, pensée pour **remplacer Windows** : bureau prêt à l'emploi, jeux (Steam/Proton-GE), réalité virtuelle (SteamVR), compatibilité applicative (winboat/Wine) et outillage de maintenance intégré. L'installateur graphique est **Anaconda** (celui de Fedora/RHEL), **porté sur Arch** : payload LiveOS (copie du live sur le disque), spokes FWS (choix du bureau, récapitulatif avant installation), finalisation pacman/GRUB/mkinitcpio en `%post`.
|
||||||
|
|
||||||
Le projet est construit avec une chaîne `mkarchiso` adaptée pour fonctionner **depuis Windows via WSL** (Git Bash → WSL Arch), sans nécessiter de machine Linux dédiée.
|
Le projet est conçu pour être **construit depuis Windows via WSL** (les scripts détectent Git Bash et basculent automatiquement dans WSL), mais fonctionne aussi directement depuis une **Arch Linux native** ou depuis **toute distribution non-Arch (Fedora, Ubuntu…) via une bascule automatique dans un conteneur Arch podman**.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Aperçu
|
## Aperçu
|
||||||
|
|
||||||
- **Base** : Arch Linux (rolling release)
|
- **Base** : Arch Linux (rolling release)
|
||||||
- **Installeur** : Calamares (compilé depuis l'AUR, servi via un repo local pacman)
|
- **Installateur** : **Anaconda 45 porté sur Arch** — payload LiveOS (installe FWS, pas Fedora), page « Récapitulatif avant installation » avec bouton Précédent, choix du bureau intégré, **brandé FWS** (en-tête « FWS 0.6 INSTALLATION », via les variables `ANACONDA_PRODUCT*` exportées par le `.xinitrc`)
|
||||||
- **Affichage live** : Xorg + Openbox, lancement automatique de Calamares
|
- **Affichage live** : Xorg + Openbox + splash de préparation qui montre l'activité réelle d'anaconda (dernier log actif + chrono ; si rien ne bouge avant l'apparition de l'installateur, il le dit puis affiche un diagnostic complet — le watchdog se désarme dès que la GUI est à l'écran)
|
||||||
- **Boot** : BIOS (syslinux) + UEFI (systemd-boot)
|
- **Mémoire** : **4 Go recommandés** pour installer (2 Go minimum — swap **zram** intégré au live ET au système installé ; sous 2 Go le live avertit, à 1 Go sans zram l'installateur graphique gèle)
|
||||||
|
- **Bureaux installables** : GNOME, KDE Plasma, XFCE, **Hyprland** (Wayland — non compatible VR), **i3** (X11 — compatible VR/SteamVR), ou ligne de commande seule
|
||||||
|
- **Boot** : UEFI (systemd-boot) + BIOS (syslinux, splash **FWS**, `DEFAULT fws`) — entrées *normale*, *safe graphics (nomodeset)*, *Réparer FWS (recovery)* et *speech*
|
||||||
|
- **Récupération** : accessible depuis le live (entrée de boot), depuis le **menu GRUB du système installé** (« Réparer FWS ») et depuis son **menu d'applications** (« Récupération FWS », élévation polkit)
|
||||||
- **Compression** : squashfs (xz)
|
- **Compression** : squashfs (xz)
|
||||||
- **Build** : Windows + WSL (Arch) ou directement depuis Arch
|
|
||||||
|
|
||||||
## Prérequis
|
---
|
||||||
|
|
||||||
### Côté Windows
|
## Ce qu'il y a dans FWS
|
||||||
- Windows 10/11
|
|
||||||
- WSL 2 avec une distribution **Arch Linux** installée (`Arch`, `ArchLinux`, `ArchWSL`…)
|
|
||||||
- Git Bash (pour exécuter les scripts depuis Windows)
|
|
||||||
|
|
||||||
### Côté Arch (WSL ou natif)
|
### À l'installation
|
||||||
Les scripts installent automatiquement les paquets nécessaires (`archiso`, `base-devel`, `git`, `reflector`, `dos2unix`).
|
- **Choix du bureau** dans Anaconda, avec compatibilité VR affichée (i3 = SteamVR ✔ ; Hyprland = ✘)
|
||||||
|
- **Page récapitulative** avant toute écriture disque : config choisie (langue, clavier, fuseau, comptes, partitionnement, bureau, nom de machine) + matériel détecté (GPU, disques, virtualisation, réseau)
|
||||||
|
- **Automatique en fin d'install** : drivers GPU (NVIDIA/AMD/Intel), outils invité VM (VMware/VirtualBox/QEMU/Hyper-V), PipeWire + pavucontrol, Bluetooth (BlueZ + blueman), luminosité (brightnessctl), **pare-feu firewalld activé**, Steam + Wine + Monado + MangoHud + gamemode, clavier/locale, hostname, sudo pour l'utilisateur créé, branding FWS
|
||||||
|
|
||||||
## Démarrage rapide
|
### Sur le système installé (outillage `fws-*`)
|
||||||
|
| Commande | Rôle | Accès |
|
||||||
|
|---|---|---|
|
||||||
|
| `fws-hello` | Bienvenue au 1er démarrage (mise à jour, codecs, Proton-GE, VR, raccourcis) | auto au 1er login |
|
||||||
|
| `fws-update` | Mise à jour complète (pacman + cache + orphelins + flatpak) | bouton de la barre |
|
||||||
|
| `fws-keys` | Panneau des **raccourcis clavier réels** (lit la config Hyprland/i3) | `Super+K`, bouton ⌨ |
|
||||||
|
| `fws-powermenu` | Verrouiller / déconnexion / suspendre / redémarrer / éteindre | `Super+X`, bouton |
|
||||||
|
| `fws-about` | « À propos » : le projet FWS + infos système | menu d'applications |
|
||||||
|
| `fws-vr-setup` | Drivers/runtimes VR (Vive/Index → SteamVR natif ; Quest → ALVR ; Monado) | `Super+Shift+V` (i3), menu |
|
||||||
|
| `fws-proton-ge` | Installe/actualise Proton-GE pour Steam (vérif sha512) | fws-hello, terminal |
|
||||||
|
| `fws-recovery` | **Application GTK de réparation** : GRUB, initramfs, pacman, terminal chroot (moteur bash + repli console) | menu « Récupération FWS » de l'OS installé, entrée GRUB « Réparer FWS », entrée de boot du live |
|
||||||
|
|
||||||
|
### Hyprland & i3 : parité visuelle
|
||||||
|
Même identité Catppuccin Mocha (nuances de bleu) sur les deux : barre flottante arrondie (**waybar** / **polybar**) avec date+heure, indicateur de mises à jour, volume/réseau/CPU/RAM/luminosité/Bluetooth cliquables ; menus assortis (**wofi** / **rofi**) ; mêmes raccourcis (déclarés avec descriptions → `Super+K`) ; **Dolphin** en gestionnaire de fichiers ; thème **SDDM « fws »** maison (pur QtQuick, accent adapté au bureau ; GNOME garde GDM avec bannière FWS).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Environnement requis — INSTALLATION ULTRA PRÉCISE
|
||||||
|
|
||||||
|
### Côté Windows (machine hôte)
|
||||||
|
|
||||||
|
| Composant | Version / état requis | Commande de vérif |
|
||||||
|
|---|---|---|
|
||||||
|
| Windows | 10 (22H2+) ou 11 | `winver` |
|
||||||
|
| WSL | **WSL 2** (pas WSL 1) | `wsl --status` |
|
||||||
|
| Virtualisation CPU | Activée dans le BIOS (VT-x / AMD-V) | Gestionnaire des tâches → Performance → CPU → "Virtualisation : Activé" |
|
||||||
|
| Git for Windows | ≥ 2.40 (fournit Git Bash) | `git --version` |
|
||||||
|
| Espace disque libre | ≥ 25 GB sur la partition WSL | — |
|
||||||
|
| RAM | ≥ 8 GB (16 GB recommandés) | — |
|
||||||
|
|
||||||
|
#### 1. Activer WSL 2
|
||||||
|
|
||||||
|
Dans **PowerShell administrateur** :
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
wsl --install --no-distribution
|
||||||
|
wsl --set-default-version 2
|
||||||
|
wsl --update
|
||||||
|
```
|
||||||
|
|
||||||
|
Puis **redémarrer Windows**.
|
||||||
|
|
||||||
|
#### 2. Installer Arch Linux dans WSL
|
||||||
|
|
||||||
|
Arch n'est pas dans le store Microsoft. Installer **ArchWSL** :
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# Télécharger la dernière release
|
||||||
|
Invoke-WebRequest -Uri "https://github.com/yuk7/ArchWSL/releases/latest/download/Arch.zip" -OutFile "$env:TEMP\Arch.zip"
|
||||||
|
Expand-Archive "$env:TEMP\Arch.zip" -DestinationPath "$env:LOCALAPPDATA\ArchWSL"
|
||||||
|
& "$env:LOCALAPPDATA\ArchWSL\Arch.exe"
|
||||||
|
```
|
||||||
|
|
||||||
|
Au premier lancement, la distribution s'enregistre sous le nom **`Arch`** (ce nom est attendu par les scripts — il est paramétrable via `ARCH_WSL_DISTRO` si besoin).
|
||||||
|
|
||||||
|
Vérifier :
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
wsl -l -v
|
||||||
|
# Doit afficher :
|
||||||
|
# NAME STATE VERSION
|
||||||
|
# * Arch Stopped 2
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. Installer Git for Windows
|
||||||
|
|
||||||
|
Télécharger depuis https://git-scm.com/download/win et installer avec les options par défaut. **Git Bash** est inclus.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Côté WSL Arch (préparation système)
|
||||||
|
|
||||||
|
Le **premier lancement** de la WSL ouvre une session root. Effectuer une seule fois :
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 1. Préparation : compile Calamares depuis l'AUR, crée le repo local,
|
# 1. Initialiser le keyring (sinon pacman refuse tout install signé)
|
||||||
# patche pacman.conf et configure les services systemd (Xorg + autostart).
|
pacman-key --init
|
||||||
./setup-calamares.sh
|
pacman-key --populate archlinux
|
||||||
|
|
||||||
# 2. Build de l'ISO via mkarchiso (fusionne configs/releng + configs/baseline)
|
# 2. Mettre à jour le keyring AVANT toute autre opération
|
||||||
|
# (les WSL fraîches ont un keyring périmé)
|
||||||
|
pacman -Sy --noconfirm archlinux-keyring
|
||||||
|
|
||||||
|
# 3. Mise à jour complète du système
|
||||||
|
pacman -Syu --noconfirm
|
||||||
|
|
||||||
|
# 4. Vérifier que /tmp est bien un tmpfs (sinon mkarchiso lent)
|
||||||
|
mount | grep '/tmp'
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Note** : le script `setup-aur.sh` désactive automatiquement le sandbox landlock de pacman ≥ 7 (incompatible avec le kernel WSL) en ajoutant `DisableSandbox` dans `/etc/pacman.conf`. Tu n'as rien à faire.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Côté Arch Linux native (alternative)
|
||||||
|
|
||||||
|
Si tu build depuis une vraie Arch (pas WSL) :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo pacman -Syu
|
||||||
|
sudo pacman -S --needed base-devel git archiso reflector dos2unix
|
||||||
|
```
|
||||||
|
|
||||||
|
Les scripts détectent l'absence de WSL et s'exécutent en local. Il faut être **root** ou avoir `sudo` configuré.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Côté Fedora / Linux non-Arch (conteneur podman)
|
||||||
|
|
||||||
|
Sur une distribution **qui n'est pas Arch** (Fedora, Ubuntu, Debian…), les scripts
|
||||||
|
détectent l'hôte non-Arch et **se relancent automatiquement dans un conteneur Arch**
|
||||||
|
via podman. Tu n'as qu'à installer podman, puis lancer les scripts normalement.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Fedora
|
||||||
|
sudo dnf install -y podman
|
||||||
|
# Debian / Ubuntu
|
||||||
|
sudo apt install -y podman
|
||||||
|
|
||||||
|
# Puis, à la racine du repo, exactement comme sur Arch :
|
||||||
|
./setup-aur.sh
|
||||||
./build.sh
|
./build.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
L'ISO finale est générée dans `./out/`.
|
Détails utiles :
|
||||||
|
|
||||||
Les deux scripts détectent automatiquement s'ils sont lancés depuis **Git Bash** (et basculent dans WSL en root) ou directement depuis **WSL/Arch**.
|
- **podman rootful obligatoire** : les scripts préfixent `sudo podman` (rootless ne
|
||||||
|
gère pas les mounts/chroot de `mkarchiso`). `sudo` peut demander ton mot de passe.
|
||||||
|
- L'image utilisée est `docker.io/library/archlinux:latest`, pull explicite à chaque
|
||||||
|
run (le tag `latest` n'est pas re-résolu sinon).
|
||||||
|
- Le dépôt est monté **au même chemin absolu** dans le conteneur : l'ISO (`out/`) et
|
||||||
|
`local-repo/` reviennent directement sur l'hôte (re-`chown` automatique vers toi).
|
||||||
|
- Le cache pacman est conservé entre les runs dans le volume `fws-pacman-cache`.
|
||||||
|
- SELinux enforcing (Fedora) est géré par `--privileged` — rien à configurer.
|
||||||
|
|
||||||
## Structure du projet
|
> Pour forcer l'exécution **locale** (si tu es déjà sur Arch et que pacman est là),
|
||||||
|
> la bascule ne se déclenche pas : la détection exige `pacman` **et** un
|
||||||
|
> `ID`/`ID_LIKE` « arch » dans `/etc/os-release`.
|
||||||
|
|
||||||
| Chemin | Rôle |
|
---
|
||||||
|--------|------|
|
|
||||||
| `setup-calamares.sh` | Préparation one-shot : build Calamares (AUR), repo local, services systemd, autostart Xorg + Calamares |
|
|
||||||
| `build.sh` | Build de l'ISO via `mkarchiso` (utilisable depuis Git Bash ou WSL) |
|
|
||||||
| `configs/releng/` | Profil principal (base ArchISO releng) |
|
|
||||||
| `configs/baseline/` | Overlay FWS appliqué par-dessus `releng` (prioritaire) |
|
|
||||||
| `local-repo/` | Repo pacman local généré (Calamares + dépendances AUR) |
|
|
||||||
| `out/` | ISOs générées |
|
|
||||||
| `fws/mkarchiso` | Binaire `mkarchiso` embarqué (fork) |
|
|
||||||
|
|
||||||
## Séquence de boot de l'ISO
|
## Démarrage rapide
|
||||||
|
|
||||||
1. Démarrage de l'ISO FWS (BIOS ou UEFI)
|
Depuis **Git Bash sur Windows** (à la racine du repo) :
|
||||||
2. `systemd` → autologin root sur `tty1`
|
|
||||||
3. `xorg-start.service` → `Xorg :0`
|
```bash
|
||||||
4. `calamares.service` → `DISPLAY=:0 calamares`
|
# Étape 1 : compilation des paquets AUR (winboat) + PKGBUILD locaux
|
||||||
5. **Fallback** : si les services échouent, `.zprofile` relance Xorg + Openbox + Calamares manuellement
|
# (anaconda porté sur Arch + ses dépendances python)
|
||||||
|
# → crée local-repo/ avec les .pkg.tar.zst
|
||||||
|
./setup-aur.sh
|
||||||
|
|
||||||
|
# Étape 2 : build de l'ISO via mkarchiso
|
||||||
|
# → fusionne configs/releng + configs/baseline
|
||||||
|
# → injecte le repo local dans pacman.conf
|
||||||
|
# → sort l'ISO dans ./out/
|
||||||
|
./build.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
L'ISO finale est générée dans `./out/FWS-YYYY.MM.DD-x86_64.iso`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Ce que fait `setup-aur.sh` (étape par étape)
|
||||||
|
|
||||||
|
1. **Détection environnement** : si lancé depuis Git Bash, bascule dans `wsl.exe -d Arch -u root`.
|
||||||
|
2. **Patch pacman** : désactive landlock sur WSL (`DisableSandbox`).
|
||||||
|
3. **Refresh keyring** : `pacman-key --init && --populate archlinux`, mise à jour `archlinux-keyring`.
|
||||||
|
4. **`pacman -Syu`** complet (obligatoire — sinon `makepkg` plante sur les "conflicting files" lors des splits de paquets type `gcc-libs`).
|
||||||
|
5. **Install des outils de build** : `base-devel git`.
|
||||||
|
6. **Création d'un utilisateur `fwsbuild`** non-root avec `sudo` NOPASSWD (makepkg refuse de tourner en root).
|
||||||
|
7. **Clone + build AUR** : `winboat-bin` via `makepkg -s --noconfirm`, plus les PKGBUILD locaux de `pkgbuilds/` (anaconda, anaconda-widgets, pykickstart, blivet, python-meh patché…). Le build est **incrémental** : un paquet déjà présent dans `local-repo/` à la bonne version est sauté.
|
||||||
|
8. **Création du repo local** : `repo-add local-repo/fws-local.db.tar.gz`.
|
||||||
|
9. **Cleanup** : suppression de l'utilisateur `fwsbuild`.
|
||||||
|
|
||||||
|
**Durée** : quelques minutes en incrémental ; le premier build complet (anaconda + deps) est plus long.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Ce que fait `build.sh` (étape par étape)
|
||||||
|
|
||||||
|
1. **Détection environnement** : Git Bash → bascule dans WSL ; sinon exécution locale.
|
||||||
|
2. **Update miroirs** : `reflector --latest 10 --sort rate`.
|
||||||
|
3. **Install `archiso`**.
|
||||||
|
4. **Fusion configs** : `cp -ar configs/releng/* /tmp/fws-build/releng/` puis overlay `configs/baseline/*` par-dessus (baseline prioritaire).
|
||||||
|
5. **Activation NetworkManager** sur le live (symlink réel `multi-user.target.wants/`).
|
||||||
|
6. **Injection du repo local** : ajoute `[fws-local]` (`SigLevel = Optional TrustAll`) en tête de `pacman.conf`.
|
||||||
|
7. **`dos2unix`** sur l'arborescence (au cas où tu as édité depuis Windows).
|
||||||
|
8. **`mkarchiso -v -w /tmp/fws-build/work -o out/ /tmp/fws-build/releng`**.
|
||||||
|
9. **Cleanup** du workdir.
|
||||||
|
|
||||||
|
**Durée** : 5–15 minutes selon la machine et le cache pacman.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Test rapide en QEMU
|
## Test rapide en QEMU
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./scripts/run_archiso.sh -i out/fws-*.iso # BIOS
|
./scripts/run_archiso.sh -i out/FWS-*.iso # BIOS
|
||||||
./scripts/run_archiso.sh -u -i out/fws-*.iso # UEFI
|
./scripts/run_archiso.sh -u -i out/FWS-*.iso # UEFI
|
||||||
```
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Structure du projet
|
||||||
|
|
||||||
|
| Chemin | Rôle |
|
||||||
|
|---|---|
|
||||||
|
| `setup-aur.sh` | Build des paquets AUR (winboat) + PKGBUILD locaux, crée `local-repo/` |
|
||||||
|
| `build.sh` | Build de l'ISO via `mkarchiso` |
|
||||||
|
| `configs/releng/` | Profil principal (base ArchISO releng) |
|
||||||
|
| `configs/baseline/` | Overlay FWS (surcharge le profil releng) — **prioritaire** sur releng |
|
||||||
|
| `local-repo/` | Repo pacman local (généré par `setup-aur.sh`) |
|
||||||
|
| `out/` | ISOs générées |
|
||||||
|
| `fws/mkarchiso` | Binaire `mkarchiso` embarqué (fork) |
|
||||||
|
| `scripts/run_archiso.sh` | Lanceur QEMU |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Séquence de boot de l'ISO
|
||||||
|
|
||||||
|
1. Menu de boot : **installation** (défaut), **safe graphics** (`nomodeset`), **Réparer FWS** (`fws.recovery=1` → app GTK `fws-recovery-gui` via openbox, repli console `fws-recovery`), **speech**. Toutes les entrées plafonnent les workers udev bloqués (`udev.event_timeout=45`)
|
||||||
|
2. `systemd` → autologin root sur `tty1`
|
||||||
|
3. `.zprofile` → mode recovery si demandé, sinon `startx`
|
||||||
|
4. `.xinitrc` → Openbox + **garde-fou RAM** (avertissement sous 2 Go) + **splash « Préparation de l'installateur »** (label alimenté en direct par les logs anaconda ; à 4 min sans activité → diagnostic auto `/tmp/fws-stall.txt` ; le tout se désarme dès que la GUI d'anaconda apparaît), bind mount `/run/rootfsbase` (source du payload LiveOS), patch du hub Anaconda, **exports `ANACONDA_PRODUCT*`** (branding FWS), puis `dbus-run-session liveinst`
|
||||||
|
5. **Anaconda** : accueil → hub (langue, clavier, disque, utilisateur, **bureau FWS**) → « Commencer l'installation » → **page Récapitulatif** (bouton Précédent / Lancer l'installation) → installation → écran de réussite → extinction
|
||||||
|
6. En cas d'échec : écran de debug avec tous les logs (liveinst, %post chrooté, anaconda)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Personnalisation
|
## Personnalisation
|
||||||
|
|
||||||
- **Paquets** : éditer `configs/releng/packages.x86_64`
|
- **Paquets du live** : `configs/releng/packages.x86_64`
|
||||||
- **Overlay rootfs** : déposer les fichiers dans `configs/releng/airootfs/` ou `configs/baseline/airootfs/`
|
- **Paquets baseline** : `configs/baseline/packages.x86_64`
|
||||||
- **Modules / séquence Calamares** : `configs/baseline/airootfs/etc/calamares/`
|
- **Overlay rootfs** : `configs/releng/airootfs/` ou `configs/baseline/airootfs/`
|
||||||
- **Branding ISO** : `configs/releng/profiledef.sh` (`iso_name`, `iso_label`, `iso_publisher`…)
|
- **Kickstart de l'installateur** : `configs/releng/airootfs/usr/share/anaconda/interactive-defaults.ks` (payload LiveOS via `--liveinst` + tout le `%post` : bureaux, drivers, pare-feu, branding)
|
||||||
|
- **Spokes Anaconda FWS** : `configs/baseline/airootfs/usr/lib/python3.14/site-packages/pyanaconda/ui/gui/spokes/` (`fws_desktop.py`, `fws_recap.py`) + glades dans `usr/share/anaconda/ui/spokes/`
|
||||||
|
- **Configs bureaux & thèmes** : `configs/releng/airootfs/usr/local/share/fws/` (hyprland, i3, waybar, polybar, wofi, rofi, picom) et `usr/share/sddm/themes/fws/`
|
||||||
|
- **Outils fws-\*** : `configs/releng/airootfs/usr/local/bin/`
|
||||||
|
- **Récupération sur l'OS installé** : entrée GRUB générée par `configs/releng/airootfs/etc/grub.d/42_fws-recovery` → `fws-recovery.target` + `fws-recovery-boot.service` (`etc/systemd/system/`) ; lanceur `usr/local/share/applications/fws-recovery.desktop` + politique polkit `usr/share/polkit-1/actions/org.fws.recovery.policy`
|
||||||
|
- **Swap zram** (live + installé) : `configs/releng/airootfs/etc/systemd/zram-generator.conf` (paquet `zram-generator`)
|
||||||
|
- **Branding ISO** : `configs/releng/profiledef.sh` (`iso_name`, `iso_label`, `iso_publisher`) ; **visuel du menu BIOS** : `configs/releng/syslinux/splash.png` (PNG 8-bit) ; **nom/version affichés par l'installateur** : exports `ANACONDA_PRODUCTNAME`/`ANACONDA_PRODUCTVERSION` dans le `.xinitrc` (lus depuis l'os-release du live)
|
||||||
|
|
||||||
|
> ⚠ **Règle d'or de la fusion** : au build, `configs/baseline/*` est copié **par-dessus** `configs/releng/*` — tout fichier homonyme de baseline **écrase** celui de releng. Ça concerne notamment `profiledef.sh`, `packages.x86_64`, `pacman.conf`, `efiboot/loader/entries/01-archiso-linux.conf` et `syslinux/syslinux.cfg` : **toute modification d'un de ces fichiers doit être reportée dans les deux profils** (des divergences ont déjà fait perdre silencieusement `firewalld` et le cap `udev.event_timeout` d'une ISO ; un `syslinux-linux.cfg` stock orphelin côté baseline définissait aussi un label `arch` sans le cap — supprimé, et le menu BIOS pointe désormais explicitement sur `DEFAULT fws`). Vérifier avec :
|
||||||
|
> ```bash
|
||||||
|
> comm -12 <(cd configs/baseline && find . -type f | sort) <(cd configs/releng && find . -type f | sort)
|
||||||
|
> ```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Dépannage
|
## Dépannage
|
||||||
|
|
||||||
- **`pacman.conf introuvable`** : vérifier que `configs/releng/pacman.conf` existe.
|
| Symptôme | Cause / fix |
|
||||||
- **Calamares ne démarre pas dans l'ISO** : se logger en tty (autologin root) et lancer `journalctl -u xorg-start -u calamares`.
|
|---|---|
|
||||||
- **Erreurs de retours à la ligne** : `build.sh` lance `dos2unix` sur l'arborescence ; si vous éditez des fichiers depuis Windows, ce n'est pas un problème.
|
| `Aucune distribution WSL Arch joignable` | Aucune distro Arch n'est installée/joignable. Les scripts auto-détectent désormais toute distro dont le nom contient « arch » (via `wsl -l -q`) ; installe ArchWSL (nom `Arch`) ou `wsl --install -d archlinux`, ou force `ARCH_WSL_DISTRO=NomDeMaDistro`. |
|
||||||
- **`mkarchiso` échoue sur un paquet AUR** : relancer `./setup-calamares.sh` pour reconstruire le repo local.
|
| `WSL introuvable` | WSL n'est pas installé. PowerShell admin : `wsl --install`, puis installe une distro Arch. |
|
||||||
|
| `pacman: signature unknown trust` | Keyring périmé → `pacman -Sy --noconfirm archlinux-keyring` puis relancer. |
|
||||||
|
| `makepkg: conflicting files` | `pacman -Syu` incomplet avant le build. Relancer `setup-aur.sh`. |
|
||||||
|
| `mkarchiso` plante sur `[fws-local]` | Le repo local n'a pas été généré. Relancer `setup-aur.sh`. |
|
||||||
|
| Écran bleu 1-2 min au boot du live | Normal en VM : un worker udev traîne (plafonné à 45 s) — le splash « Préparation de l'installateur » l'indique. Attendre. |
|
||||||
|
| L'installateur semble figé / fenêtre blanche | Rendu logiciel en VM : la fenêtre Anaconda se peint lentement. Patienter quelques secondes. |
|
||||||
|
| Session Hyprland/i3 : fenêtres au contenu noir en VM | Compositing sur GPU virtuel — picom est auto-désactivé en VM (config FWS) ; si tu l'as réactivé, `pkill picom`. |
|
||||||
|
| Hyprland crash au lancement en VM | Géré : le wrapper `fws-hyprland` force le rendu logiciel (`kms_swrast`/llvmpipe) sous hyperviseur. Sur vrai GPU, rendu matériel normal. |
|
||||||
|
| Steam plante à l'install de SteamVR | En VM : `steam -cef-disable-gpu -cef-disable-gpu-compositing` (et la VR ne peut PAS marcher en VM — GPU/USB inaccessibles). |
|
||||||
|
| Icône Bluetooth absente / blueman en erreur | Pas d'adaptateur Bluetooth (cas VM) : le module de barre se cache et l'applet ne se lance pas — comportement voulu. |
|
||||||
|
| Le système installé ne boote plus | Menu GRUB → « **Réparer FWS (récupération du système)** » (boote l'initramfs fallback + l'app de réparation). Si GRUB lui-même est mort : booter l'ISO → entrée « **Réparer FWS (recovery)** ». |
|
||||||
|
| Réparer depuis le système installé (il boote encore) | Menu d'applications → « **Récupération FWS** » (mot de passe admin demandé une fois — polkit). |
|
||||||
|
| Réinstallation par-dessus une install existante | Le kickstart nettoie tout (`zerombr` + `clearpart --all`), mais en cas de comportement étrange au 2ᵉ passage, effacer/recréer le disque virtuel. |
|
||||||
|
| Boot BIOS | Fonctionne (résolu) : syslinux est sous `/boot/syslinux` de l'ISO (pas `/syslinux`), El-Torito BIOS + UEFI présents ; install BIOS complète validée en VM. Le menu BIOS démarre l'entrée FWS par défaut (`DEFAULT fws`). |
|
||||||
|
| Splash « Préparation de l'installateur » figé | **RAM insuffisante** (reproduit : gel à 1 Go, OK à 2 Go, aucun swap sur le live avant zram). En VM : allouer **4 Go** (le wizard VMware « Other 64-bit » n'en met que 1 !). Le live avertit désormais sous 2 Go, embarque un swap zram, et le splash affiche l'activité réelle d'anaconda (+ diagnostic auto si les logs ne bougent plus). |
|
||||||
|
| Dialogue « préparation bloquée : diagnostic » PAR-DESSUS l'installateur | Bug corrigé (ISO ≤ 2026-07-07 01:04) : le watchdog du splash se déclenchait alors qu'anaconda était à l'écran (logs silencieux = normal quand il attend l'utilisateur). Il se désarme désormais dès l'apparition de la GUI ; ferme le dialogue et continue, ou rebuild. |
|
||||||
|
| « Possibly missing firmware for module … » pendant une réparation Recovery | Avertissements `mkinitcpio` **normaux** : firmware de matériel exotique (SCSI/fibre channel…) absent de `linux-firmware`. Sans effet, sauf si tu possèdes ce matériel précis. Le journal Recovery l'explique désormais. |
|
||||||
|
| Recovery : « tout est grisé » | Corrigé : seul le sélecteur était désactivé (une seule installation détectée) mais toute l'app semblait morte ; il reste actif désormais. Les boutons d'action, eux, ont toujours été fonctionnels. |
|
||||||
|
| Retours à la ligne CRLF | `build.sh` lance `dos2unix` automatiquement, mais si tu modifies pendant le build, relancer. |
|
||||||
|
|
||||||
|
### Logs utiles
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Pendant le build
|
||||||
|
tail -f /tmp/fws-build/work/iso/arch/pkglist.x86_64.txt
|
||||||
|
|
||||||
|
# Dans le LIVE (Ctrl+Alt+F2, login root) — pendant/après l'installation
|
||||||
|
journalctl -b # système
|
||||||
|
cat /tmp/fws-liveinst.log # sortie complète de liveinst/anaconda
|
||||||
|
cat /tmp/anaconda.log # log principal anaconda
|
||||||
|
cat /tmp/fws-post-chroot.log # %post chrooté = grub-install/mkinitcpio
|
||||||
|
# En cas d'échec, l'écran de debug du live affiche déjà tout ça (zenity).
|
||||||
|
|
||||||
|
# Sur le système installé
|
||||||
|
cat /var/log/fws-post.log # trace complète du %post d'installation
|
||||||
|
journalctl -b # premier démarrage
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Variables d'environnement supportées
|
||||||
|
|
||||||
|
| Variable | Effet | Défaut |
|
||||||
|
|---|---|---|
|
||||||
|
| `ARCH_WSL_DISTRO` | Nom de la distro WSL Arch | `Arch` |
|
||||||
|
| `MSYS_NO_PATHCONV` | Désactive la conversion auto des chemins Git Bash | `1` (forcé dans les scripts) |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -87,6 +333,21 @@ Les deux scripts détectent automatiquement s'ils sont lancés depuis **Git Bash
|
|||||||
|
|
||||||
FWS est un fork de **[archiso](https://gitlab.archlinux.org/archlinux/archiso)** (Arch Linux), redistribué sous les termes de la **GPL-3.0-or-later**.
|
FWS est un fork de **[archiso](https://gitlab.archlinux.org/archlinux/archiso)** (Arch Linux), redistribué sous les termes de la **GPL-3.0-or-later**.
|
||||||
|
|
||||||
Voir [LICENSE](LICENSE) pour le texte complet, et [AUTHORS.rst](AUTHORS.rst) pour la liste des auteurs originaux d'archiso.
|
Les modifications spécifiques à FWS (scripts `build.sh`, `setup-aur.sh`, overlay `configs/baseline/`, intégration de l'installateur + Xorg autostart, chaîne de build WSL) sont également distribuées sous GPL-3.0-or-later.
|
||||||
|
|
||||||
Les modifications spécifiques à FWS (scripts `build.sh`, `setup-calamares.sh`, overlay `configs/baseline/`, intégration Calamares + Xorg autostart, chaîne de build WSL) sont également distribuées sous GPL-3.0-or-later.
|
### Base légale complète
|
||||||
|
|
||||||
|
| Document | Objet |
|
||||||
|
|---|---|
|
||||||
|
| [LICENSE](LICENSE) | Texte intégral GPL-3.0-or-later |
|
||||||
|
| [COPYRIGHT.md](COPYRIGHT.md) | Droits d'auteur du dépôt & périmètre |
|
||||||
|
| [LICENSING.md](LICENSING.md) | Politique de licences, **offre écrite GPL (sources)**, checklist release |
|
||||||
|
| [THIRD-PARTY-LICENSES.md](THIRD-PARTY-LICENSES.md) | Inventaire des logiciels tiers (Anaconda, deps…) & **analyse de compatibilité** |
|
||||||
|
| [TRADEMARKS.md](TRADEMARKS.md) | Marques & **non-affiliation** (Arch, Red Hat, Fedora, Anaconda, Windows…) |
|
||||||
|
| [NOTICE](NOTICE) | Attributions Apache/MIT/BSD |
|
||||||
|
| [AUTHORS.rst](AUTHORS.rst) | Auteurs FWS + auteurs originaux d'archiso |
|
||||||
|
| [CONTRIBUTING.rst](CONTRIBUTING.rst) | Contribuer (inbound = outbound, DCO) |
|
||||||
|
|
||||||
|
> ✅ **Déjà réglé** : offre écrite GPL (URL dépôt + contact), `os-release` FWS (le live ne s'annonce plus « Arch Linux », via hook pacman) et `motd` (plus de lien `archlinux.org`).
|
||||||
|
>
|
||||||
|
> ⚠️ **Reste avant diffusion publique** (détail dans [LICENSING.md](LICENSING.md) §6) : **rendre le dépôt public** (sinon l'offre GPL n'est pas opposable), retirer le branding Red Hat/Fedora de l'UI Anaconda lors de la migration, et **trancher sur `python-iso639`** (AGPL-3.0-only). **Ces documents ne sont pas un avis juridique.**
|
||||||
|
|||||||
@@ -0,0 +1,147 @@
|
|||||||
|
# Logiciels tiers & licences — FWS
|
||||||
|
|
||||||
|
Ce document est l'**inventaire de conformité** (« bill of materials ») des
|
||||||
|
logiciels tiers que FWS reconditionne, embarque ou redistribue. Il sert à
|
||||||
|
satisfaire les obligations d'**attribution** et de **préservation des avis de
|
||||||
|
licence** des licences GPL, LGPL, AGPL, Apache, MIT et BSD.
|
||||||
|
|
||||||
|
Trois familles de tiers :
|
||||||
|
|
||||||
|
1. **La base du dépôt** : FWS est un fork d'**archiso**.
|
||||||
|
2. **Les paquets construits/redistribués par FWS** (`pkgbuilds/` + `local-repo/`),
|
||||||
|
notamment l'installateur **Anaconda** et ses dépendances Python.
|
||||||
|
3. **L'ensemble des paquets Arch Linux** agrégés dans l'ISO live (chacun sous sa
|
||||||
|
propre licence ; l'avis de licence de chaque paquet est présent dans
|
||||||
|
`/usr/share/licenses/<paquet>/` sur le système installé/live).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Base du dépôt
|
||||||
|
|
||||||
|
| Composant | Rôle | SPDX | Détenteur | Source amont |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| **archiso** | système de build (mkarchiso, profils, man, Makefile) | `GPL-3.0-or-later` | Arch Linux / Archiso Authors | https://gitlab.archlinux.org/archlinux/archiso |
|
||||||
|
|
||||||
|
Auteurs originaux : voir [AUTHORS.rst](AUTHORS.rst).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Paquets construits / redistribués par FWS
|
||||||
|
|
||||||
|
Sources des recettes : `pkgbuilds/*/PKGBUILD`. Binaires : `local-repo/*.pkg.tar.zst`.
|
||||||
|
La **source correspondante** (au sens GPL/LGPL) de chacun est le tarball amont
|
||||||
|
référencé par `source=()` dans le PKGBUILD, plus le PKGBUILD lui-même.
|
||||||
|
|
||||||
|
| Paquet | Version | SPDX | Détenteur principal | Source amont |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| anaconda | 45.8 | `GPL-2.0-or-later` | Red Hat, Inc. & contributeurs Anaconda | https://github.com/rhinstaller/anaconda |
|
||||||
|
| anaconda-widgets | 45.8 | `GPL-2.0-or-later` | Red Hat, Inc. | https://github.com/rhinstaller/anaconda |
|
||||||
|
| pykickstart | 3.74 | `GPL-2.0-or-later` | Red Hat, Inc. | https://github.com/pykickstart/pykickstart |
|
||||||
|
| python-blivet | 3.13.2 | `LGPL-2.1-only` | Red Hat, Inc. | https://github.com/storaged-project/blivet |
|
||||||
|
| python-meh | 0.43 | `GPL-2.0-or-later` | Red Hat, Inc. | https://github.com/rhinstaller/python-meh |
|
||||||
|
| python-productmd | 1.50 | `LGPL-2.1-or-later` | Red Hat, Inc. / release-engineering | https://github.com/release-engineering/productmd |
|
||||||
|
| python-simpleline | 1.8 | `LGPL-3.0-or-later` | Red Hat, Inc. | https://github.com/rhinstaller/python-simpleline |
|
||||||
|
| python-requests-file | 2.1.0 | `Apache-2.0` | David Shea | https://github.com/dashea/requests-file |
|
||||||
|
| python-requests-ftp | 0.3.1 | `Apache-2.0` | Cory Benfield | https://github.com/Lukasa/requests-ftp |
|
||||||
|
| python-pid | 3.0.4 | `Apache-2.0` | trbs | https://github.com/trbs/pid |
|
||||||
|
| python-iso639 | 0.4.5 | **`AGPL-3.0-only`** ⚠ | Mikael Karlsson (noumar) | https://github.com/noumar/iso639 |
|
||||||
|
| python-langtable | 0.0.51 | `GPL-3.0-or-later AND MIT` | Mike FABIAN | https://github.com/mike-fabian/langtable |
|
||||||
|
| python-xkbregistry | 1.5 | `MIT` | Stephen Early | https://github.com/sde1000/python-xkbregistry |
|
||||||
|
| libreport | 2.17.15 | **`GPL-2.0-only`** ⚠ | Red Hat, Inc. (projet ABRT) | https://github.com/abrt/libreport |
|
||||||
|
| satyr | 0.43 | `GPL-2.0-or-later` | Red Hat, Inc. (projet ABRT) | https://github.com/abrt/satyr |
|
||||||
|
| libxmlrpc (xmlrpc-c) | 1.64.03 | `custom` (BSD-style permissive) | Auteurs xmlrpc-c | https://xmlrpc-c.sourceforge.net/ |
|
||||||
|
| winboat-bin | 0.9.0 | `MIT` | Auteurs WinBoat (TibixDev) | https://www.winboat.app |
|
||||||
|
|
||||||
|
> Les versions et identifiants SPDX ci-dessus proviennent des champs `license=`
|
||||||
|
> des PKGBUILD et des `.PKGINFO` des paquets de `local-repo/`. Quand le `.PKGINFO`
|
||||||
|
> portait une étiquette ancienne et imprécise (`GPL`, `Apache`), l'identifiant
|
||||||
|
> SPDX retenu est celui du dépôt amont (p. ex. `satyr` → `GPL-2.0-or-later`).
|
||||||
|
> **À corriger dans les PKGBUILD** pour des étiquettes SPDX exactes.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Paquets Arch Linux de l'ISO
|
||||||
|
|
||||||
|
L'ISO live agrège tout l'ensemble de paquets listé dans
|
||||||
|
`configs/releng/packages.x86_64` et `configs/baseline/packages.x86_64` (noyau
|
||||||
|
Linux, Xorg, Openbox, environnements de bureau, utilitaires…). Chaque paquet
|
||||||
|
conserve sa licence d'origine ; l'avis correspondant est fourni dans
|
||||||
|
`/usr/share/licenses/<paquet>/` sur le système. FWS ne revendique aucun droit
|
||||||
|
sur ces paquets.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Analyse de compatibilité des licences
|
||||||
|
|
||||||
|
**Licence effective du dépôt FWS : `GPL-3.0-or-later`** (imposée par la dérivation
|
||||||
|
d'archiso, lui-même GPL-3.0-or-later).
|
||||||
|
|
||||||
|
### 4.1 Principe d'agrégation (le cas général)
|
||||||
|
|
||||||
|
L'ISO et le dépôt de paquets sont des **agrégations** de programmes indépendants
|
||||||
|
(« mere aggregation », GPLv3 §5 / GPLv2 §2). Chaque paquet est distribué comme
|
||||||
|
une unité séparée (binaire `.pkg.tar.zst` distinct, processus distinct,
|
||||||
|
bibliothèque partagée distincte) et **conserve sa propre licence**. C'est
|
||||||
|
exactement le modèle juridique sous lequel Arch Linux, Debian et Fedora
|
||||||
|
distribuent des milliers de paquets de licences hétérogènes sur un même média.
|
||||||
|
À ce niveau, la compatibilité copyleft **n'est pas requise** : il n'y a pas
|
||||||
|
d'« œuvre combinée » unique.
|
||||||
|
|
||||||
|
### 4.2 Compatibilité au sein du runtime Anaconda
|
||||||
|
|
||||||
|
Anaconda charge plusieurs modules dans **un même processus Python** au moment de
|
||||||
|
l'exécution. Les licences en présence et leur compatibilité montante vers GPLv3 :
|
||||||
|
|
||||||
|
| Licence du composant | Compatible GPLv3 ? | Note |
|
||||||
|
|---|---|---|
|
||||||
|
| `GPL-2.0-or-later` (anaconda, meh, pykickstart, satyr…) | ✅ | la clause « or later » autorise l'usage en GPLv3 |
|
||||||
|
| `LGPL-2.1-only` (blivet) | ✅ | LGPL-2.1 §3 autorise la relicence en GPL ; usage dynamique |
|
||||||
|
| `LGPL-2.1-or-later` (productmd) | ✅ | montée vers (L)GPLv3 |
|
||||||
|
| `LGPL-3.0-or-later` (simpleline) | ✅ | sous-ensemble de GPLv3 |
|
||||||
|
| `Apache-2.0` (requests-file, requests-ftp, pid) | ✅ | compatible GPLv3 (sens unique) ; voir [NOTICE](NOTICE) |
|
||||||
|
| `MIT` (xkbregistry, winboat) | ✅ | permissive |
|
||||||
|
| `MIT`/`BSD-style` (langtable, libxmlrpc) | ✅ | permissive |
|
||||||
|
|
||||||
|
### 4.3 ⚠ Deux points à surveiller (signalés en bonne foi)
|
||||||
|
|
||||||
|
1. **`python-iso639` est `AGPL-3.0-only`.** L'AGPL est compatible avec GPLv3 via
|
||||||
|
la clause de compatibilité réciproque (GPLv3 §13 / AGPLv3 §13) : on peut
|
||||||
|
combiner du code AGPLv3 et GPLv3. La **clause réseau** de l'AGPL (mise à
|
||||||
|
disposition de la source aux utilisateurs distants d'un service réseau) est
|
||||||
|
en pratique **inerte** pour un installateur hors-ligne. **Cependant**, l'AGPL
|
||||||
|
est la licence la plus contaminante et beaucoup d'organisations l'interdisent
|
||||||
|
par politique interne. **Recommandation béton :** si l'AGPL n'est pas
|
||||||
|
souhaitée, remplacer `noumar/iso639` par une bibliothèque ISO-639 non-AGPL
|
||||||
|
(p. ex. `pycountry` — BSD, ou les données `iso-codes`), ce qui élimine le
|
||||||
|
sujet.
|
||||||
|
|
||||||
|
2. **`libreport` est `GPL-2.0-only`** (sans « or later »). GPL-2.0-**only** n'est
|
||||||
|
**pas** compatible en montée avec GPLv3/AGPLv3. Tant que `libreport` reste un
|
||||||
|
paquet **séparé** (bibliothèque partagée distincte, appelée via `python-meh`
|
||||||
|
qui importe `report`), on demeure dans le régime d'agrégation §4.1 — et c'est
|
||||||
|
la configuration que **Fedora elle-même distribue**. Le risque n'apparaîtrait
|
||||||
|
que si l'on **liait statiquement** `libreport` (GPLv2-only) avec un composant
|
||||||
|
AGPLv3-only/GPLv3-only dans un **seul binaire** : à éviter. En l'état (paquets
|
||||||
|
séparés), pas de conflit.
|
||||||
|
|
||||||
|
### 4.4 Verdict
|
||||||
|
|
||||||
|
En l'état (paquets séparés, agrégation sur ISO, modules Python chargés au
|
||||||
|
runtime), **la configuration est cohérente et alignée sur la pratique des
|
||||||
|
distributions majeures**. Les deux points ⚠ ci-dessus méritent une décision
|
||||||
|
explicite (garder / remplacer l'AGPL) et une revue par un juriste FOSS avant
|
||||||
|
diffusion commerciale.
|
||||||
|
|
||||||
|
> **Ceci n'est pas un avis juridique.** Analyse de bonne foi fondée sur les
|
||||||
|
> métadonnées de licence du dépôt à la date du 2026-06-17.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Préservation des avis
|
||||||
|
|
||||||
|
- Les textes de licence amont présents dans les sources sont conservés lors du
|
||||||
|
`package()` (pacman installe `LICENSE`/`COPYING` dans
|
||||||
|
`/usr/share/licenses/<paquet>/`).
|
||||||
|
- Les attributions requises par Apache-2.0 / MIT / BSD figurent dans [NOTICE](NOTICE).
|
||||||
|
- Aucun avis de droit d'auteur amont ne doit être retiré des sources ou binaires
|
||||||
|
redistribués.
|
||||||
+155
@@ -0,0 +1,155 @@
|
|||||||
|
# Marques & non-affiliation — FWS
|
||||||
|
|
||||||
|
FWS redistribue et modifie des logiciels portant des **marques** de tiers. Les
|
||||||
|
licences libres (GPL, LGPL, Apache…) accordent des droits sur le **code**, mais
|
||||||
|
**jamais** sur les **marques, noms et logos**. Ce document liste les marques
|
||||||
|
concernées et les déclarations de non-affiliation. Il vaut engagement du projet
|
||||||
|
à les respecter.
|
||||||
|
|
||||||
|
## Marque du projet
|
||||||
|
|
||||||
|
- **FWS** est le nom (marque non déposée) du présent projet, utilisé par les
|
||||||
|
Contributeurs FWS. Toute reprise du nom/logo FWS pour désigner une version
|
||||||
|
modifiée non officielle doit éviter de laisser croire à un aval du projet FWS.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Arch Linux
|
||||||
|
|
||||||
|
> **Arch Linux™** est une marque du projet Arch Linux. FWS est une distribution
|
||||||
|
> **dérivée indépendante**, *basée sur* Arch Linux. FWS **n'est ni affilié, ni
|
||||||
|
> sponsorisé, ni approuvé** par le projet Arch Linux. *« Arch Linux is a
|
||||||
|
> trademark of the Arch Linux project. FWS is an independent derivative and is
|
||||||
|
> not affiliated with, sponsored by, or endorsed by Arch Linux. »*
|
||||||
|
|
||||||
|
Engagements FWS :
|
||||||
|
|
||||||
|
- ne pas présenter FWS **comme étant** Arch Linux ;
|
||||||
|
- ne pas utiliser le **logo Arch Linux** comme logo de FWS ;
|
||||||
|
- usage **nominatif** uniquement (« basé sur Arch Linux », « compatible
|
||||||
|
paquets Arch ») ;
|
||||||
|
- respecter les recommandations Arch pour les dérivés
|
||||||
|
(https://wiki.archlinux.org/title/DeveloperWiki:TrademarkPolicy).
|
||||||
|
|
||||||
|
### ✅ Remédiation appliquée (le live ne s'annonce plus comme « Arch Linux »)
|
||||||
|
|
||||||
|
Le système live héritait de l'`os-release` du paquet `filesystem` d'Arch et
|
||||||
|
**s'annonçait comme « Arch Linux »** ; le `motd` renvoyait vers
|
||||||
|
`wiki.archlinux.org`. Corrigé :
|
||||||
|
|
||||||
|
- **`os-release` FWS** : fourni dans
|
||||||
|
`configs/releng/airootfs/usr/local/share/fws/os-release` et appliqué sur
|
||||||
|
`/usr/lib/os-release` par un **hook pacman PostTransaction**
|
||||||
|
(`configs/releng/airootfs/etc/pacman.d/hooks/zz-fws-os-release.hook`). On ne
|
||||||
|
peut pas poser le fichier directement dans l'overlay : `filesystem` possède ce
|
||||||
|
chemin et `mkarchiso` copie l'overlay **avant** pacstrap → conflit pacman
|
||||||
|
« exists in filesystem ». Le hook s'exécute après l'installation des paquets,
|
||||||
|
donc sans conflit, et est retiré du système final par
|
||||||
|
`zzzz99-remove-custom-hooks-from-airootfs.hook`.
|
||||||
|
- **`motd`** : ne référence plus `archlinux.org` ; pointe vers le dépôt FWS.
|
||||||
|
- **Menu de boot BIOS (2026-07-07)** : l'image de fond `syslinux/splash.png`
|
||||||
|
héritée d'archiso affichait le **logo Arch Linux plein écran** — remplacée
|
||||||
|
par un visuel FWS original (générique, sans logo tiers).
|
||||||
|
- **Bannière de login (`/etc/issue`)** : `\S (\l)` — affiche le `PRETTY_NAME`
|
||||||
|
FWS, sans la version du noyau (dont le suffixe `-archN`).
|
||||||
|
- **Textes utilisateur** : `fws-about` dit « distribution Linux » ; le splash
|
||||||
|
de préparation et le journal de l'app Récupération remplacent à l'affichage
|
||||||
|
les mentions « Arch Linux »/« Fedora » issues des logs d'outils tiers (les
|
||||||
|
identifiants techniques réels — `archlinux-keyring`, miroirs — restent
|
||||||
|
intacts : usage nominatif fonctionnel).
|
||||||
|
|
||||||
|
> Note technique : `ID=fws` + `ID_LIKE=arch` préserve la détection « famille
|
||||||
|
> Arch » des outils tiers (et satisfait les checks `^ID(_LIKE)?=.*arch` de
|
||||||
|
> `build.sh`/`setup-aur.sh`, qui portent de toute façon sur l'hôte de build).
|
||||||
|
> Si la migration Anaconda révèle un composant testant `ID=arch` en dur, basculer
|
||||||
|
> transitoirement le hook sur `ID=arch` tout en gardant `NAME`/`PRETTY_NAME` FWS.
|
||||||
|
> Le suffixe `-archN` de `uname -r` vient du binaire du noyau Arch : usage
|
||||||
|
> nominatif inévitable sans recompiler le kernel.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Red Hat & Fedora
|
||||||
|
|
||||||
|
> **Red Hat®** et **Fedora®** sont des marques déposées de **Red Hat, Inc.**
|
||||||
|
> L'installateur **Anaconda** est développé par Red Hat. FWS distribue une
|
||||||
|
> **version MODIFIÉE** d'Anaconda (portée sur Arch, payload LiveOS), **non
|
||||||
|
> officielle**, **non fournie ni approuvée** par Red Hat ou le projet Fedora.
|
||||||
|
> *« This product includes a modified version of Anaconda. Red Hat and Fedora
|
||||||
|
> are trademarks of Red Hat, Inc. This is an unofficial build, not provided or
|
||||||
|
> endorsed by Red Hat or the Fedora Project. »*
|
||||||
|
|
||||||
|
Engagements FWS :
|
||||||
|
|
||||||
|
- ne pas utiliser les marques Red Hat / Fedora pour suggérer un aval ;
|
||||||
|
- **marquer clairement Anaconda comme modifié** (la GPL exige d'identifier les
|
||||||
|
versions modifiées ; la politique de marque Red Hat exige de ne pas faire
|
||||||
|
passer une version modifiée pour officielle) ;
|
||||||
|
- **recommandation béton :** retirer tout **logo / nom de produit Red Hat ou
|
||||||
|
Fedora** de l'interface de l'installateur si présent, et y afficher
|
||||||
|
« Installateur FWS (basé sur Anaconda) ».
|
||||||
|
|
||||||
|
### ✅ Remédiation appliquée (2026-07-07 — l'installateur s'annonce « FWS »)
|
||||||
|
|
||||||
|
Sans `/.buildstamp`, Anaconda s'annonçait « ANACONDA BLUESKY INSTALLATION » et
|
||||||
|
ses logs parlent de Fedora. `pyanaconda/core/product.py` donne priorité aux
|
||||||
|
variables d'environnement : le `.xinitrc` du live exporte
|
||||||
|
`ANACONDA_PRODUCTNAME`/`ANACONDA_PRODUCTVERSION` (depuis l'os-release FWS) et
|
||||||
|
`ANACONDA_ISFINAL=true` → l'en-tête et l'accueil affichent **« FWS 0.6 »**. Le
|
||||||
|
splash de préparation filtre en outre les mentions Fedora des lignes de log
|
||||||
|
affichées. Les mentions profondes dans les **logs techniques** (fichiers
|
||||||
|
`/tmp/*.log`, écrans de debug) sont conservées volontairement : identification
|
||||||
|
loyale du composant amont (version modifiée d'Anaconda), utile au diagnostic.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Anaconda — désambiguïsation
|
||||||
|
|
||||||
|
> Le nom **« Anaconda »** désigne ici **l'installateur de Red Hat/Fedora**
|
||||||
|
> (https://github.com/rhinstaller/anaconda). Il **n'a aucun rapport** avec
|
||||||
|
> **Anaconda®**, marque déposée d'**Anaconda, Inc.** (la distribution Python /
|
||||||
|
> data-science). FWS n'utilise ni ne distribue le produit d'Anaconda, Inc.
|
||||||
|
|
||||||
|
À mentionner dans la doc utilisateur pour éviter toute confusion.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Windows & Microsoft
|
||||||
|
|
||||||
|
> **Windows®** et **Microsoft®** sont des marques de **Microsoft Corporation**.
|
||||||
|
> FWS embarque **WinBoat** (MIT), qui permet d'exécuter des applications Windows
|
||||||
|
> sous Linux. FWS et WinBoat **ne sont ni affiliés, ni approuvés** par Microsoft.
|
||||||
|
> Exécuter des applications Windows requiert vos **propres licences Windows
|
||||||
|
> valides** ; FWS ne fournit aucun logiciel ni licence Microsoft.
|
||||||
|
|
||||||
|
Le nom du projet et son slogan font un usage **parodique / nominatif** du terme
|
||||||
|
« Windows » et n'impliquent aucun lien avec Microsoft.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Autres marques (usage nominatif)
|
||||||
|
|
||||||
|
Les noms suivants désignent des projets/options proposés à l'installation ou
|
||||||
|
utilisés comme composants, et sont des marques de leurs détenteurs, employées
|
||||||
|
de façon **purement descriptive** :
|
||||||
|
|
||||||
|
- **GNOME®** — The GNOME Foundation
|
||||||
|
- **KDE®**, **Plasma** — KDE e.V.
|
||||||
|
- **Xfce** — projet Xfce
|
||||||
|
- **Hyprland** — projet Hyprland
|
||||||
|
- **GTK** — The GNOME Foundation
|
||||||
|
- **Linux®** — marque déposée de Linus Torvalds
|
||||||
|
- **WinBoat** — projet WinBoat
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Principe général
|
||||||
|
|
||||||
|
L'emploi de ces marques dans FWS relève de l'**usage nominatif loyal** (décrire
|
||||||
|
l'origine, la compatibilité ou les composants), **sans** suggérer parrainage ou
|
||||||
|
affiliation. Aucune licence sur ces marques n'est accordée ni reçue. Pour toute
|
||||||
|
utilisation commerciale du nom/logo d'un tiers au-delà de l'usage nominatif,
|
||||||
|
obtenir l'autorisation du détenteur.
|
||||||
|
|
||||||
|
> **Ceci n'est pas un avis juridique.** Faites valider la stratégie de marque
|
||||||
|
> (notamment le nom du projet et le rebranding d'Anaconda) par un conseil avant
|
||||||
|
> diffusion publique large.
|
||||||
Executable
+408
@@ -0,0 +1,408 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# ============================================================
|
||||||
|
# FWS — Build OFFICIEL versionné de l'ISO (archiso)
|
||||||
|
#
|
||||||
|
# IDENTIQUE à build.sh (même bascule conteneur/WSL, --network=host, fusion
|
||||||
|
# baseline, MÊME injection local-repo → donc même paquet anaconda avec le champ
|
||||||
|
# Hostname), avec EN PLUS uniquement le RENOMMAGE :
|
||||||
|
# - demande la version (major.minor.build) + le nom de variante, le fichier
|
||||||
|
# VERSION servant de défaut,
|
||||||
|
# - nomme l'ISO fws-<version>-<nom>.iso (ex. fws-1.5.0-cli.iso),
|
||||||
|
# - range l'ISO dans out/vMAJOR/vMAJOR.MINOR/.
|
||||||
|
#
|
||||||
|
# Fonctionne sur :
|
||||||
|
# - Windows 10 / 11 (Git Bash → bascule auto dans WSL Arch)
|
||||||
|
# - Arch Linux natif (exécution directe)
|
||||||
|
# - WSL Arch lancé directement (exécution directe)
|
||||||
|
#
|
||||||
|
# Nom de la distro WSL : "Arch" par défaut, ou $ARCH_WSL_DISTRO,
|
||||||
|
# ou auto-détecté parmi les noms courants.
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
|
set -e
|
||||||
|
trap 'rc=$?; echo -e "\e[31mÉchec (build-offi.sh) ligne $LINENO, code $rc.\e[0m" >&2; exit $rc' ERR
|
||||||
|
|
||||||
|
DISTRO_NAME="${ARCH_WSL_DISTRO:-Arch}"
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# Bascule Git Bash (Windows 10/11) → WSL si besoin
|
||||||
|
# ============================================================
|
||||||
|
if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "cygwin" || -n "$WINDIR" ]]; then
|
||||||
|
echo -e "\e[36mGit Bash détecté — bascule dans WSL ($DISTRO_NAME)...\e[0m"
|
||||||
|
export MSYS_NO_PATHCONV=1
|
||||||
|
export MSYS2_ARG_CONV_EXCL="*"
|
||||||
|
|
||||||
|
# WSL doit être présent (sinon message clair plutôt que command not found).
|
||||||
|
command -v wsl.exe >/dev/null 2>&1 || {
|
||||||
|
echo -e "\e[31mWSL introuvable. Installe WSL2 puis une distro Arch :\e[0m" >&2
|
||||||
|
echo " 1) PowerShell admin : wsl --install" >&2
|
||||||
|
echo " 2) Installe Arch (ArchWSL, ou 'wsl --install -d archlinux') puis relance." >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Choix de la distro Arch : override $ARCH_WSL_DISTRO, sinon nom exact,
|
||||||
|
# sinon 1re distro « arch » réellement joignable. On énumère via
|
||||||
|
# `wsl -l -q` (sortie UTF-16LE → on retire NUL/CR) au lieu d'une liste
|
||||||
|
# figée, mais on garde la sonde « echo ok » (une distro listée peut
|
||||||
|
# être en cours d'install / cassée).
|
||||||
|
pick_arch_distro() {
|
||||||
|
wsl.exe -d "$DISTRO_NAME" -u root -- echo ok >/dev/null 2>&1 && return 0
|
||||||
|
local d distros=()
|
||||||
|
mapfile -t distros < <(wsl.exe -l -q 2>/dev/null | tr -d '\0\r' | sed 's/[[:space:]]*$//;/^$/d')
|
||||||
|
for d in "${distros[@]}"; do
|
||||||
|
[[ "$d" == "$DISTRO_NAME" ]] || continue
|
||||||
|
wsl.exe -d "$d" -u root -- echo ok >/dev/null 2>&1 && { DISTRO_NAME="$d"; return 0; }
|
||||||
|
done
|
||||||
|
for d in "${distros[@]}"; do
|
||||||
|
[[ "$d" =~ [Aa][Rr][Cc][Hh] ]] || continue
|
||||||
|
wsl.exe -d "$d" -u root -- echo ok >/dev/null 2>&1 && { DISTRO_NAME="$d"; return 0; }
|
||||||
|
done
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
if ! pick_arch_distro; then
|
||||||
|
echo -e "\e[31mAucune distribution WSL Arch joignable.\e[0m" >&2
|
||||||
|
echo "Distros WSL installées :" >&2
|
||||||
|
wsl.exe -l -v 2>/dev/null | tr -d '\0' >&2 || true
|
||||||
|
echo "" >&2
|
||||||
|
echo "Installe Arch dans WSL puis relance :" >&2
|
||||||
|
echo " - ArchWSL (yuk7) — s'enregistre sous 'Arch' : https://github.com/yuk7/ArchWSL/releases/latest" >&2
|
||||||
|
echo " - ou image officielle : wsl --install -d archlinux (nom 'archlinux')" >&2
|
||||||
|
echo "Distro sous un autre nom ? export ARCH_WSL_DISTRO=<nom> (cf. 'wsl -l -v' ci-dessus)." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo -e "\e[36m==> Distro WSL : $DISTRO_NAME\e[0m"
|
||||||
|
|
||||||
|
# Traduit le dossier du script en chemin WSL.
|
||||||
|
SCRIPT_DIR_WIN="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -W)"
|
||||||
|
SCRIPT_PATH_WSL=$(MSYS_NO_PATHCONV=1 wsl.exe -d "$DISTRO_NAME" -u root -- \
|
||||||
|
wslpath "$(echo "$SCRIPT_DIR_WIN" | sed 's|/|\\\\|g')/build-offi.sh" \
|
||||||
|
2>/dev/null | tr -d '\r\n')
|
||||||
|
[ -n "$SCRIPT_PATH_WSL" ] || {
|
||||||
|
echo -e "\e[31mTraduction du chemin vers WSL échouée (wslpath). Vérifie ARCH_WSL_DISTRO ($DISTRO_NAME).\e[0m" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
wsl.exe -d "$DISTRO_NAME" -u root -- test -f "$SCRIPT_PATH_WSL" || {
|
||||||
|
echo -e "\e[31mScript introuvable dans WSL : $SCRIPT_PATH_WSL\e[0m" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Relance ce même script dans WSL, en root, depuis son vrai chemin
|
||||||
|
# (BASH_SOURCE → WORK_DIR correct). Les fins de ligne sont garanties LF
|
||||||
|
# par .gitattributes (*.sh text eol=lf) ; le profil copié est en plus
|
||||||
|
# passé à dos2unix plus loin.
|
||||||
|
echo "==> Script à exécuter dans WSL : $SCRIPT_PATH_WSL"
|
||||||
|
MSYS_NO_PATHCONV=1 wsl.exe -d "$DISTRO_NAME" -u root -- bash "$SCRIPT_PATH_WSL"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# Bascule conteneur : hôte non-Arch (Fedora, Ubuntu, …) →
|
||||||
|
# build dans un conteneur Arch via podman.
|
||||||
|
#
|
||||||
|
# mkarchiso exige pacman + des mounts/chroot/loop privilégiés que
|
||||||
|
# seul un environnement Arch fournit. Sur un hôte non-Arch on relance
|
||||||
|
# CE script à l'identique dans docker.io/library/archlinux:latest, le
|
||||||
|
# dépôt monté au MÊME chemin absolu (→ WORK_DIR et out/ inchangés).
|
||||||
|
# podman ROOTFUL + --privileged obligatoire : rootless ne gère pas les
|
||||||
|
# mounts/chroot de mkarchiso (et --privileged relâche aussi SELinux,
|
||||||
|
# enforcing sur Fedora, sur le bind-mount sans avoir besoin de :Z).
|
||||||
|
# ============================================================
|
||||||
|
host_is_arch() {
|
||||||
|
# Fedora empaquette aussi « pacman » → sa seule présence ne suffit pas ;
|
||||||
|
# on exige en plus un ID/ID_LIKE « arch » dans /etc/os-release.
|
||||||
|
command -v pacman >/dev/null 2>&1 \
|
||||||
|
&& grep -qiE '^ID(_LIKE)?=.*arch' /etc/os-release 2>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ -z "$FWS_IN_CONTAINER" ] && ! host_is_arch; then
|
||||||
|
echo -e "\e[36mHôte non-Arch détecté — build officiel dans un conteneur Arch (podman)...\e[0m"
|
||||||
|
|
||||||
|
command -v podman >/dev/null 2>&1 || {
|
||||||
|
echo -e "\e[31mpodman introuvable.\e[0m" >&2
|
||||||
|
echo " Fedora : sudo dnf install -y podman" >&2
|
||||||
|
echo " Debian/Ubuntu : sudo apt install -y podman" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# La version + le nom sont DEMANDÉS sur l'hôte (avant le conteneur) et passés
|
||||||
|
# via -e, pour que le prompt s'affiche au bon endroit (terminal de l'hôte).
|
||||||
|
# (Définis FWS_ISO_VERSION / FWS_ISO_TAG ; lus plus bas, prompt sauté si déjà
|
||||||
|
# fournis — c.-à-d. dans le conteneur.)
|
||||||
|
ask_iso_meta_host() {
|
||||||
|
[ -n "$FWS_ISO_VERSION" ] && [ -n "$FWS_ISO_TAG" ] && return 0
|
||||||
|
local def=""
|
||||||
|
if [ -f "$(dirname "${BASH_SOURCE[0]}")/VERSION" ]; then
|
||||||
|
def="$(tr -d ' \t\r\n' < "$(dirname "${BASH_SOURCE[0]}")/VERSION")"
|
||||||
|
[[ "$def" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || def=""
|
||||||
|
fi
|
||||||
|
while :; do
|
||||||
|
if [ -n "$def" ]; then
|
||||||
|
read -rp "==> Version (major.minor.build) [Entrée = $def] : " FWS_ISO_VERSION || exit 1
|
||||||
|
[ -n "$FWS_ISO_VERSION" ] || FWS_ISO_VERSION="$def"
|
||||||
|
else
|
||||||
|
read -rp "==> Version (major.minor.build, ex. 1.5.0) : " FWS_ISO_VERSION || exit 1
|
||||||
|
fi
|
||||||
|
[[ "$FWS_ISO_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] && break
|
||||||
|
echo -e "\e[31m Format attendu : major.minor.build (ex. 1.5.0)\e[0m" >&2
|
||||||
|
done
|
||||||
|
while :; do
|
||||||
|
read -rp "==> Nom de la variante (ex. cli, gnome, kde) : " FWS_ISO_TAG || exit 1
|
||||||
|
FWS_ISO_TAG="$(printf '%s' "$FWS_ISO_TAG" | tr '[:upper:]' '[:lower:]' | tr -cd 'a-z0-9-')"
|
||||||
|
[ -n "$FWS_ISO_TAG" ] && break
|
||||||
|
echo -e "\e[31m Nom requis (lettres, chiffres, tirets)\e[0m" >&2
|
||||||
|
done
|
||||||
|
export FWS_ISO_VERSION FWS_ISO_TAG
|
||||||
|
}
|
||||||
|
ask_iso_meta_host
|
||||||
|
|
||||||
|
# Rootful : préfixe sudo si on n'est pas déjà root.
|
||||||
|
SUDO=(); [ "$EUID" -eq 0 ] || SUDO=(sudo)
|
||||||
|
# -it seulement si on est dans un terminal (sinon podman casse en CI).
|
||||||
|
TTY=(); [ -t 0 ] && TTY=(-it)
|
||||||
|
|
||||||
|
REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
SELF="$(basename "${BASH_SOURCE[0]}")"
|
||||||
|
IMAGE="docker.io/library/archlinux:latest"
|
||||||
|
|
||||||
|
# pull explicite : « run » ne re-résout jamais le tag « latest » une fois
|
||||||
|
# l'image en cache → sans ça on build indéfiniment sur une image qui
|
||||||
|
# vieillit (puis partial upgrades pacman). Le -Syu côté conteneur (plus
|
||||||
|
# bas) complète la parade.
|
||||||
|
echo "==> Pull de l'image $IMAGE..."
|
||||||
|
"${SUDO[@]}" podman pull "$IMAGE"
|
||||||
|
|
||||||
|
echo "==> Relance dans le conteneur ($SELF)..."
|
||||||
|
# --network=host : le réseau bridge de podman ne route plus vers l'extérieur
|
||||||
|
# sur ce wifi (firewalld/NAT cassé après changement de réseau → « core.db :
|
||||||
|
# Resolving timed out », même avec --dns). En partageant la pile réseau de
|
||||||
|
# l'hôte (qui, lui, a internet + DNS via 127.0.0.53/systemd-resolved joignable
|
||||||
|
# dans son propre netns), le conteneur récupère une connectivité identique.
|
||||||
|
"${SUDO[@]}" podman run --rm "${TTY[@]}" --network=host --privileged \
|
||||||
|
-e FWS_IN_CONTAINER=1 \
|
||||||
|
-e FWS_ISO_VERSION -e FWS_ISO_TAG \
|
||||||
|
-v "$REPO_DIR":"$REPO_DIR" \
|
||||||
|
-v fws-pacman-cache:/var/cache/pacman/pkg \
|
||||||
|
-w "$REPO_DIR" \
|
||||||
|
"$IMAGE" \
|
||||||
|
bash "$REPO_DIR/$SELF"
|
||||||
|
|
||||||
|
# podman rootful → les fichiers produits (out/) appartiennent à root.
|
||||||
|
# On les rend au propriétaire du dépôt pour confort côté hôte.
|
||||||
|
OWNER="$(stat -c '%u:%g' "$REPO_DIR" 2>/dev/null || true)"
|
||||||
|
if [ -n "$OWNER" ]; then
|
||||||
|
for d in out local-repo; do
|
||||||
|
[ -e "$REPO_DIR/$d" ] && "${SUDO[@]}" chown -R "$OWNER" "$REPO_DIR/$d" 2>/dev/null || true
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# Exécution native (Arch Linux bare-metal, WSL, OU conteneur Arch)
|
||||||
|
# ============================================================
|
||||||
|
command -v pacman >/dev/null \
|
||||||
|
|| { echo -e "\e[31mpacman introuvable — lance ce script depuis Arch / WSL.\e[0m"; exit 1; }
|
||||||
|
|
||||||
|
# mkarchiso exige root. Sur Arch natif on s'élève (sudo de préférence,
|
||||||
|
# sinon su) ; depuis la bascule Git Bash on est déjà root (-u root).
|
||||||
|
# $0 est cité pour gérer les chemins à espaces (ex. "1. FWS").
|
||||||
|
if [ "$EUID" -ne 0 ]; then
|
||||||
|
if command -v sudo >/dev/null 2>&1; then
|
||||||
|
# -E : conserve FWS_ISO_VERSION / FWS_ISO_TAG (demandés avant) à travers sudo.
|
||||||
|
exec sudo -E bash "$0" "$@"
|
||||||
|
else
|
||||||
|
exec su -c "bash \"$0\"" root
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if grep -qi 'microsoft\|wsl' /proc/version 2>/dev/null; then
|
||||||
|
echo -e "\e[36mBuild officiel dans WSL ($DISTRO_NAME) en tant que root...\e[0m"
|
||||||
|
IS_WSL=1
|
||||||
|
else
|
||||||
|
echo -e "\e[36mBuild officiel sur Arch Linux natif en tant que root...\e[0m"
|
||||||
|
IS_WSL=0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Le dossier de travail = dossier qui contient ce script (gère les
|
||||||
|
# espaces du chemin, ex. "1. FWS").
|
||||||
|
WORK_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
echo "==> Dossier de travail : $WORK_DIR"
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# Version (major.minor.build) + nom de la variante.
|
||||||
|
# Déjà demandés sur l'hôte (FWS_ISO_VERSION/FWS_ISO_TAG passés via -e) ; sinon
|
||||||
|
# (exécution native Arch / WSL directe) on les demande ici. Le fichier VERSION
|
||||||
|
# sert de défaut (Entrée = le reprendre). Produit fws-<version>-<nom>.iso.
|
||||||
|
# ============================================================
|
||||||
|
VERSION="$FWS_ISO_VERSION"
|
||||||
|
ISO_TAG="$FWS_ISO_TAG"
|
||||||
|
VERSION_DEFAULT=""
|
||||||
|
if [ -f "$WORK_DIR/VERSION" ]; then
|
||||||
|
VERSION_DEFAULT="$(tr -d ' \t\r\n' < "$WORK_DIR/VERSION")"
|
||||||
|
[[ "$VERSION_DEFAULT" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || VERSION_DEFAULT=""
|
||||||
|
fi
|
||||||
|
while [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; do
|
||||||
|
if [ -n "$VERSION_DEFAULT" ]; then
|
||||||
|
read -rp "==> Version (major.minor.build) [Entrée = $VERSION_DEFAULT] : " VERSION \
|
||||||
|
|| { echo -e "\e[31mEntrée requise — lance le script en interactif.\e[0m" >&2; exit 1; }
|
||||||
|
[ -n "$VERSION" ] || VERSION="$VERSION_DEFAULT"
|
||||||
|
else
|
||||||
|
read -rp "==> Version (major.minor.build, ex. 1.5.0) : " VERSION \
|
||||||
|
|| { echo -e "\e[31mEntrée requise — lance le script en interactif.\e[0m" >&2; exit 1; }
|
||||||
|
fi
|
||||||
|
[[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] \
|
||||||
|
|| echo -e "\e[31m Format attendu : major.minor.build (ex. 1.5.0)\e[0m" >&2
|
||||||
|
done
|
||||||
|
while [ -z "$ISO_TAG" ]; do
|
||||||
|
read -rp "==> Nom de la variante (ex. cli, gnome, kde) : " ISO_TAG \
|
||||||
|
|| { echo -e "\e[31mEntrée requise — lance le script en interactif.\e[0m" >&2; exit 1; }
|
||||||
|
ISO_TAG="$(printf '%s' "$ISO_TAG" | tr '[:upper:]' '[:lower:]' | tr -cd 'a-z0-9-')"
|
||||||
|
[ -n "$ISO_TAG" ] || echo -e "\e[31m Nom requis (lettres, chiffres, tirets)\e[0m" >&2
|
||||||
|
done
|
||||||
|
|
||||||
|
IFS='.' read -r MAJOR MINOR BUILD <<< "$VERSION"
|
||||||
|
BUILD_DATE="$(date +%Y.%m.%d)"
|
||||||
|
# iso_version interne (passé à mkarchiso) ; l'ISO finale est renommée plus bas.
|
||||||
|
ISO_VERSION="${VERSION}-${ISO_TAG}"
|
||||||
|
OUT_DIR="$WORK_DIR/out/v${MAJOR}/v${MAJOR}.${MINOR}"
|
||||||
|
# Date ajoutée À LA FIN du nom, avant .iso → fws-<version>-<nom>-<AAAA.MM.JJ>.iso
|
||||||
|
ISO_FILE="$OUT_DIR/fws-${VERSION}-${ISO_TAG}-${BUILD_DATE}.iso"
|
||||||
|
|
||||||
|
echo "==> Version : ${VERSION} · variante : ${ISO_TAG} · date : ${BUILD_DATE}"
|
||||||
|
echo "==> ISO finale : fws-${VERSION}-${ISO_TAG}-${BUILD_DATE}.iso"
|
||||||
|
echo "==> Dossier : $OUT_DIR"
|
||||||
|
|
||||||
|
# pacman ≥ 7 sandboxe les ops FS via landlock, non supporté par le kernel
|
||||||
|
# WSL ni (selon le noyau) par le conteneur → désactivation. Idempotent,
|
||||||
|
# sans effet sur Arch natif.
|
||||||
|
if { [ "$IS_WSL" -eq 1 ] || [ -n "$FWS_IN_CONTAINER" ]; } \
|
||||||
|
&& ! grep -qE '^[[:space:]]*DisableSandbox' /etc/pacman.conf; then
|
||||||
|
sed -i '/^\[options\]/a DisableSandbox' /etc/pacman.conf
|
||||||
|
echo "==> WSL/conteneur détecté → DisableSandbox ajouté à /etc/pacman.conf"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "==> Mise à jour des miroirs et installation de archiso..."
|
||||||
|
pacman -Sy --noconfirm reflector || true
|
||||||
|
reflector --verbose --latest 10 --sort rate --save /etc/pacman.d/mirrorlist || true
|
||||||
|
if [ -n "$FWS_IN_CONTAINER" ]; then
|
||||||
|
# Image de base qui vieillit → upgrade complet AVANT d'ajouter archiso,
|
||||||
|
# sinon partial upgrade (archiso tire des deps plus récentes que la base).
|
||||||
|
pacman -Syu --noconfirm archiso
|
||||||
|
else
|
||||||
|
pacman -Sy --noconfirm archiso
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "==> Préparation de l'environnement de build..."
|
||||||
|
rm -rf /tmp/fws-build
|
||||||
|
mkdir -p /tmp/fws-build/releng
|
||||||
|
|
||||||
|
# Copie configs/releng/ en base
|
||||||
|
if [ -d "$WORK_DIR/configs/releng" ]; then
|
||||||
|
cp -ar "$WORK_DIR/configs/releng/"* /tmp/fws-build/releng/
|
||||||
|
echo "==> configs/releng/ copié"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Fusionne configs/baseline/ par dessus (priorité aux fichiers baseline)
|
||||||
|
if [ -d "$WORK_DIR/configs/baseline" ]; then
|
||||||
|
cp -ar "$WORK_DIR/configs/baseline/"* /tmp/fws-build/releng/
|
||||||
|
echo "==> configs/baseline/ fusionné (prioritaire)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── Injection de la version dans profiledef.sh (copie temporaire) ──
|
||||||
|
# mkarchiso nomme l'ISO ${iso_name}-${iso_version}-${arch}.iso ; on force
|
||||||
|
# iso_version pour obtenir le nom voulu (l'ISO est renommée fws-… plus bas).
|
||||||
|
if [ -f /tmp/fws-build/releng/profiledef.sh ]; then
|
||||||
|
sed -i "s|^iso_version=.*|iso_version=\"${ISO_VERSION}\"|" \
|
||||||
|
/tmp/fws-build/releng/profiledef.sh
|
||||||
|
echo "==> iso_version forcé à '${ISO_VERSION}' dans profiledef.sh"
|
||||||
|
else
|
||||||
|
echo -e "\e[31mprofiledef.sh introuvable dans le profil de build.\e[0m"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "==> Activation de NetworkManager.service sur le live (symlink réel)..."
|
||||||
|
mkdir -p /tmp/fws-build/releng/airootfs/etc/systemd/system/multi-user.target.wants
|
||||||
|
ln -sf /usr/lib/systemd/system/NetworkManager.service \
|
||||||
|
/tmp/fws-build/releng/airootfs/etc/systemd/system/multi-user.target.wants/NetworkManager.service
|
||||||
|
|
||||||
|
echo "==> Vérification des services systemd..."
|
||||||
|
ls /tmp/fws-build/releng/airootfs/etc/systemd/system/ 2>/dev/null || echo " (aucun service)"
|
||||||
|
ls /tmp/fws-build/releng/airootfs/etc/systemd/system/multi-user.target.wants/ 2>/dev/null || echo " (aucun symlink)"
|
||||||
|
|
||||||
|
# Copie le repo local (winboat-bin + deps Anaconda packagées)
|
||||||
|
if ls "$WORK_DIR/local-repo/"*.pkg.tar.zst &>/dev/null 2>&1; then
|
||||||
|
echo "==> Copie du repo local fws-local..."
|
||||||
|
mkdir -p /tmp/fws-build/local-repo
|
||||||
|
cp -a "$WORK_DIR/local-repo/"* /tmp/fws-build/local-repo/
|
||||||
|
|
||||||
|
echo "==> Injection [fws-local] dans pacman.conf..."
|
||||||
|
sed -i '/^\[fws-local\]/,/^$/d' /tmp/fws-build/releng/pacman.conf
|
||||||
|
PACMAN_TMP=$(mktemp)
|
||||||
|
printf '[fws-local]\nSigLevel = Optional TrustAll\nServer = file:///tmp/fws-build/local-repo\n\n' \
|
||||||
|
> "$PACMAN_TMP"
|
||||||
|
cat /tmp/fws-build/releng/pacman.conf >> "$PACMAN_TMP"
|
||||||
|
mv "$PACMAN_TMP" /tmp/fws-build/releng/pacman.conf
|
||||||
|
|
||||||
|
echo "==> Vérification pacman.conf :"
|
||||||
|
head -5 /tmp/fws-build/releng/pacman.conf
|
||||||
|
else
|
||||||
|
echo "==> Aucun repo local détecté."
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "==> Correction des retours à la ligne Windows (dos2unix)..."
|
||||||
|
pacman -S --needed --noconfirm dos2unix
|
||||||
|
find /tmp/fws-build/releng -type f -exec dos2unix {} + 2>/dev/null
|
||||||
|
|
||||||
|
# ── Pré-vol : résolution de TOUS les paquets du profil ──
|
||||||
|
# « error: target not found » ne doit plus surgir en plein mkarchiso : on
|
||||||
|
# résout la liste complète (packages.x86_64 fusionné) contre le pacman.conf
|
||||||
|
# du profil (fws-local injecté inclus) dans une base temporaire. S'il manque
|
||||||
|
# un paquet, on échoue ICI avec la liste + le geste correctif.
|
||||||
|
echo "==> Pré-vol : résolution des paquets du profil..."
|
||||||
|
PREFLIGHT_DB="$(mktemp -d)"
|
||||||
|
pacman -Sy --config /tmp/fws-build/releng/pacman.conf --dbpath "$PREFLIGHT_DB" >/dev/null
|
||||||
|
mapfile -t PROFILE_PKGS < <(sed -e 's/#.*//' -e 's/[[:space:]]//g' -e '/^$/d' \
|
||||||
|
/tmp/fws-build/releng/packages.x86_64)
|
||||||
|
# -Sp n'installe rien (affiche les URLs) ; LC_ALL=C fige le motif d'erreur.
|
||||||
|
# stderr → capture, stdout → poubelle ; le pipeline sed sort toujours 0.
|
||||||
|
MISSING="$(LC_ALL=C pacman -Sp --config /tmp/fws-build/releng/pacman.conf \
|
||||||
|
--dbpath "$PREFLIGHT_DB" "${PROFILE_PKGS[@]}" 2>&1 >/dev/null \
|
||||||
|
| sed -n 's/^error: target not found:[[:space:]]*//p')"
|
||||||
|
rm -rf "$PREFLIGHT_DB"
|
||||||
|
if [ -n "$MISSING" ]; then
|
||||||
|
echo -e "\e[31mPaquets introuvables dans les dépôts du profil :\e[0m" >&2
|
||||||
|
printf ' \e[31m%s\e[0m\n' $MISSING >&2
|
||||||
|
echo -e "\e[33mDépôt fws-local absent/incomplet ? Lance ./setup-aur.sh (construit" >&2
|
||||||
|
echo -e "anaconda, winboat-bin, fws-dnd, …) puis relance ce script.\e[0m" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "==> Pré-vol OK : ${#PROFILE_PKGS[@]} paquets résolus."
|
||||||
|
|
||||||
|
echo "==> Lancement de mkarchiso..."
|
||||||
|
mkdir -p "$OUT_DIR"
|
||||||
|
# mkarchiso fait un « rm » interne de l'ISO cible avant de la (ré)écrire ; si
|
||||||
|
# une ISO du même nom est VERROUILLÉE par Windows (VM encore ouverte dessus,
|
||||||
|
# ISO montée, antivirus), ce rm échoue et tout le build casse à la toute fin.
|
||||||
|
# Parade : mkarchiso écrit dans un dossier de staging neuf, puis on déplace
|
||||||
|
# l'ISO. Si la cible (cette même version) est verrouillée, on bascule sur un
|
||||||
|
# nom horodaté → on ne touche jamais aux ISO des autres versions.
|
||||||
|
STAGE="$OUT_DIR/.staging-$$"
|
||||||
|
rm -rf "$STAGE"; mkdir -p "$STAGE"
|
||||||
|
mkarchiso -v -w /tmp/fws-build/work -o "$STAGE" /tmp/fws-build/releng
|
||||||
|
|
||||||
|
NEW_ISO="$(ls -1 "$STAGE/"*.iso 2>/dev/null | head -1)"
|
||||||
|
[ -n "$NEW_ISO" ] || { echo -e "\e[31mAucune ISO produite par mkarchiso.\e[0m" >&2; exit 1; }
|
||||||
|
if { chmod -f 666 "$ISO_FILE" 2>/dev/null; rm -f "$ISO_FILE" 2>/dev/null; } && mv -f "$NEW_ISO" "$ISO_FILE" 2>/dev/null; then
|
||||||
|
FINAL="$ISO_FILE"
|
||||||
|
else
|
||||||
|
FINAL="${ISO_FILE%.iso}-$(date +%H%M%S).iso"
|
||||||
|
echo -e "\e[33m[!] '$ISO_FILE' est verrouillée (une VM l'utilise ?). Écriture sous un nom unique.\e[0m" >&2
|
||||||
|
mv -f "$NEW_ISO" "$FINAL"
|
||||||
|
fi
|
||||||
|
rm -rf "$STAGE" 2>/dev/null || true
|
||||||
|
|
||||||
|
echo "==> Nettoyage..."
|
||||||
|
rm -rf /tmp/fws-build/work
|
||||||
|
|
||||||
|
echo "==> Build officiel terminé ! ISO : $FINAL"
|
||||||
|
echo -e "\e[32mScript de build officiel (fws-${VERSION}-${ISO_TAG}-${BUILD_DATE}) terminé avec succès.\e[0m"
|
||||||
@@ -1,54 +1,229 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
# ============================================================
|
||||||
export MSYS_NO_PATHCONV=1
|
# FWS — Build de l'ISO via mkarchiso (archiso)
|
||||||
|
#
|
||||||
|
# Fonctionne sur :
|
||||||
|
# - Windows 10 / 11 (Git Bash → bascule auto dans WSL Arch)
|
||||||
|
# - Arch Linux natif (exécution directe)
|
||||||
|
# - WSL Arch lancé directement (exécution directe)
|
||||||
|
#
|
||||||
|
# Nom de la distro WSL : "Arch" par défaut, ou $ARCH_WSL_DISTRO,
|
||||||
|
# ou auto-détecté parmi les noms courants.
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
trap 'echo -e "\e[31mErreur lors de l execution (build.sh).\e[0m"; exit 1' ERR
|
trap 'rc=$?; echo -e "\e[31mÉchec (build.sh) ligne $LINENO, code $rc.\e[0m" >&2; exit $rc' ERR
|
||||||
|
|
||||||
DISTRO_NAME="Arch"
|
DISTRO_NAME="${ARCH_WSL_DISTRO:-Arch}"
|
||||||
|
|
||||||
if [ -n "$WSL_DISTRO_NAME" ]; then
|
# ============================================================
|
||||||
echo -e "\e[36mBuild exécuté depuis WSL ($WSL_DISTRO_NAME) en tant que root...\e[0m"
|
# Bascule Git Bash (Windows 10/11) → WSL si besoin
|
||||||
IN_WSL=1
|
# ============================================================
|
||||||
else
|
if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "cygwin" || -n "$WINDIR" ]]; then
|
||||||
echo -e "\e[36mLancement du processus de build dans WSL ($DISTRO_NAME) en tant que root...\e[0m"
|
echo -e "\e[36mGit Bash détecté — bascule dans WSL ($DISTRO_NAME)...\e[0m"
|
||||||
|
export MSYS_NO_PATHCONV=1
|
||||||
|
export MSYS2_ARG_CONV_EXCL="*"
|
||||||
|
|
||||||
|
# WSL doit être présent (sinon message clair plutôt que command not found).
|
||||||
|
command -v wsl.exe >/dev/null 2>&1 || {
|
||||||
|
echo -e "\e[31mWSL introuvable. Installe WSL2 puis une distro Arch :\e[0m" >&2
|
||||||
|
echo " 1) PowerShell admin : wsl --install" >&2
|
||||||
|
echo " 2) Installe Arch (ArchWSL, ou 'wsl --install -d archlinux') puis relance." >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Choix de la distro Arch : override $ARCH_WSL_DISTRO, sinon nom exact,
|
||||||
|
# sinon 1re distro « arch » réellement joignable. On énumère via
|
||||||
|
# `wsl -l -q` (sortie UTF-16LE → on retire NUL/CR) au lieu d'une liste
|
||||||
|
# figée, mais on garde la sonde « echo ok » (une distro listée peut
|
||||||
|
# être en cours d'install / cassée).
|
||||||
|
pick_arch_distro() {
|
||||||
|
wsl.exe -d "$DISTRO_NAME" -u root -- echo ok >/dev/null 2>&1 && return 0
|
||||||
|
local d distros=()
|
||||||
|
mapfile -t distros < <(wsl.exe -l -q 2>/dev/null | tr -d '\0\r' | sed 's/[[:space:]]*$//;/^$/d')
|
||||||
|
for d in "${distros[@]}"; do
|
||||||
|
[[ "$d" == "$DISTRO_NAME" ]] || continue
|
||||||
|
wsl.exe -d "$d" -u root -- echo ok >/dev/null 2>&1 && { DISTRO_NAME="$d"; return 0; }
|
||||||
|
done
|
||||||
|
for d in "${distros[@]}"; do
|
||||||
|
[[ "$d" =~ [Aa][Rr][Cc][Hh] ]] || continue
|
||||||
|
wsl.exe -d "$d" -u root -- echo ok >/dev/null 2>&1 && { DISTRO_NAME="$d"; return 0; }
|
||||||
|
done
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
if ! pick_arch_distro; then
|
||||||
|
echo -e "\e[31mAucune distribution WSL Arch joignable.\e[0m" >&2
|
||||||
|
echo "Distros WSL installées :" >&2
|
||||||
|
wsl.exe -l -v 2>/dev/null | tr -d '\0' >&2 || true
|
||||||
|
echo "" >&2
|
||||||
|
echo "Installe Arch dans WSL puis relance :" >&2
|
||||||
|
echo " - ArchWSL (yuk7) — s'enregistre sous 'Arch' : https://github.com/yuk7/ArchWSL/releases/latest" >&2
|
||||||
|
echo " - ou image officielle : wsl --install -d archlinux (nom 'archlinux')" >&2
|
||||||
|
echo "Distro sous un autre nom ? export ARCH_WSL_DISTRO=<nom> (cf. 'wsl -l -v' ci-dessus)." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo -e "\e[36m==> Distro WSL : $DISTRO_NAME\e[0m"
|
||||||
|
|
||||||
|
# Traduit le dossier du script en chemin WSL.
|
||||||
|
SCRIPT_DIR_WIN="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -W)"
|
||||||
|
SCRIPT_PATH_WSL=$(MSYS_NO_PATHCONV=1 wsl.exe -d "$DISTRO_NAME" -u root -- \
|
||||||
|
wslpath "$(echo "$SCRIPT_DIR_WIN" | sed 's|/|\\\\|g')/build.sh" \
|
||||||
|
2>/dev/null | tr -d '\r\n')
|
||||||
|
[ -n "$SCRIPT_PATH_WSL" ] || {
|
||||||
|
echo -e "\e[31mTraduction du chemin vers WSL échouée (wslpath). Vérifie ARCH_WSL_DISTRO ($DISTRO_NAME).\e[0m" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
wsl.exe -d "$DISTRO_NAME" -u root -- test -f "$SCRIPT_PATH_WSL" || {
|
||||||
|
echo -e "\e[31mScript introuvable dans WSL : $SCRIPT_PATH_WSL\e[0m" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Relance ce même script dans WSL, en root, depuis son vrai chemin
|
||||||
|
# (BASH_SOURCE → WORK_DIR correct). Les fins de ligne sont garanties LF
|
||||||
|
# par .gitattributes (*.sh text eol=lf) ; le profil copié est en plus
|
||||||
|
# passé à dos2unix plus loin.
|
||||||
|
echo "==> Script à exécuter dans WSL : $SCRIPT_PATH_WSL"
|
||||||
|
MSYS_NO_PATHCONV=1 wsl.exe -d "$DISTRO_NAME" -u root -- bash "$SCRIPT_PATH_WSL"
|
||||||
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "$IN_WSL" ]; then
|
# ============================================================
|
||||||
# ── Depuis Git Bash ──────────────────────────────────────
|
# Bascule conteneur : hôte non-Arch (Fedora, Ubuntu, …) →
|
||||||
SCRIPT_DIR_WIN="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -W)"
|
# build dans un conteneur Arch via podman.
|
||||||
WORK_DIR_WSL=$(MSYS_NO_PATHCONV=1 wsl.exe -d "$DISTRO_NAME" -u root -- \
|
#
|
||||||
wslpath "$(echo "$SCRIPT_DIR_WIN" | sed 's|/|\\\\|g')" 2>/dev/null | tr -d '\r\n')
|
# mkarchiso exige pacman + des mounts/chroot/loop privilégiés que
|
||||||
|
# seul un environnement Arch fournit. Sur un hôte non-Arch on relance
|
||||||
|
# CE script à l'identique dans docker.io/library/archlinux:latest, le
|
||||||
|
# dépôt monté au MÊME chemin absolu (→ WORK_DIR et out/ inchangés).
|
||||||
|
# podman ROOTFUL + --privileged obligatoire : rootless ne gère pas les
|
||||||
|
# mounts/chroot de mkarchiso (et --privileged relâche aussi SELinux,
|
||||||
|
# enforcing sur Fedora, sur le bind-mount sans avoir besoin de :Z).
|
||||||
|
# ============================================================
|
||||||
|
host_is_arch() {
|
||||||
|
# Fedora empaquette aussi « pacman » → sa seule présence ne suffit pas ;
|
||||||
|
# on exige en plus un ID/ID_LIKE « arch » dans /etc/os-release.
|
||||||
|
command -v pacman >/dev/null 2>&1 \
|
||||||
|
&& grep -qiE '^ID(_LIKE)?=.*arch' /etc/os-release 2>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
echo "==> Dossier de travail WSL : $WORK_DIR_WSL"
|
if [ -z "$FWS_IN_CONTAINER" ] && ! host_is_arch; then
|
||||||
|
echo -e "\e[36mHôte non-Arch détecté — build dans un conteneur Arch (podman)...\e[0m"
|
||||||
|
|
||||||
MSYS_NO_PATHCONV=1 wsl.exe -d "$DISTRO_NAME" -u root -- bash << EOF
|
command -v podman >/dev/null 2>&1 || {
|
||||||
set -e
|
echo -e "\e[31mpodman introuvable.\e[0m" >&2
|
||||||
WORK_DIR="${WORK_DIR_WSL}"
|
echo " Fedora : sudo dnf install -y podman" >&2
|
||||||
echo "==> Dossier de travail : \$WORK_DIR"
|
echo " Debian/Ubuntu : sudo apt install -y podman" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Rootful : préfixe sudo si on n'est pas déjà root.
|
||||||
|
SUDO=(); [ "$EUID" -eq 0 ] || SUDO=(sudo)
|
||||||
|
# -it seulement si on est dans un terminal (sinon podman casse en CI).
|
||||||
|
TTY=(); [ -t 0 ] && TTY=(-it)
|
||||||
|
|
||||||
|
REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
SELF="$(basename "${BASH_SOURCE[0]}")"
|
||||||
|
IMAGE="docker.io/library/archlinux:latest"
|
||||||
|
|
||||||
|
# pull explicite : « run » ne re-résout jamais le tag « latest » une fois
|
||||||
|
# l'image en cache → sans ça on build indéfiniment sur une image qui
|
||||||
|
# vieillit (puis partial upgrades pacman). Le -Syu côté conteneur (plus
|
||||||
|
# bas) complète la parade.
|
||||||
|
echo "==> Pull de l'image $IMAGE..."
|
||||||
|
"${SUDO[@]}" podman pull "$IMAGE"
|
||||||
|
|
||||||
|
echo "==> Relance dans le conteneur ($SELF)..."
|
||||||
|
# --network=host : le réseau bridge de podman ne route plus vers l'extérieur
|
||||||
|
# sur ce wifi (firewalld/NAT cassé après changement de réseau → « core.db :
|
||||||
|
# Resolving timed out », même avec --dns). En partageant la pile réseau de
|
||||||
|
# l'hôte (qui, lui, a internet + DNS via 127.0.0.53/systemd-resolved joignable
|
||||||
|
# dans son propre netns), le conteneur récupère une connectivité identique.
|
||||||
|
"${SUDO[@]}" podman run --rm "${TTY[@]}" --network=host --privileged \
|
||||||
|
-e FWS_IN_CONTAINER=1 \
|
||||||
|
-v "$REPO_DIR":"$REPO_DIR" \
|
||||||
|
-v fws-pacman-cache:/var/cache/pacman/pkg \
|
||||||
|
-w "$REPO_DIR" \
|
||||||
|
"$IMAGE" \
|
||||||
|
bash "$REPO_DIR/$SELF"
|
||||||
|
|
||||||
|
# podman rootful → les fichiers produits (out/) appartiennent à root.
|
||||||
|
# On les rend au propriétaire du dépôt pour confort côté hôte.
|
||||||
|
OWNER="$(stat -c '%u:%g' "$REPO_DIR" 2>/dev/null || true)"
|
||||||
|
if [ -n "$OWNER" ]; then
|
||||||
|
for d in out local-repo; do
|
||||||
|
[ -e "$REPO_DIR/$d" ] && "${SUDO[@]}" chown -R "$OWNER" "$REPO_DIR/$d" 2>/dev/null || true
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# Exécution native (Arch Linux bare-metal, WSL, OU conteneur Arch)
|
||||||
|
# ============================================================
|
||||||
|
command -v pacman >/dev/null \
|
||||||
|
|| { echo -e "\e[31mpacman introuvable — lance ce script depuis Arch / WSL.\e[0m"; exit 1; }
|
||||||
|
|
||||||
|
# mkarchiso exige root. Sur Arch natif on s'élève (sudo de préférence,
|
||||||
|
# sinon su) ; depuis la bascule Git Bash on est déjà root (-u root).
|
||||||
|
# $0 est cité pour gérer les chemins à espaces (ex. "1. FWS").
|
||||||
|
if [ "$EUID" -ne 0 ]; then
|
||||||
|
if command -v sudo >/dev/null 2>&1; then
|
||||||
|
exec sudo bash "$0" "$@"
|
||||||
|
else
|
||||||
|
exec su -c "bash \"$0\"" root
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if grep -qi 'microsoft\|wsl' /proc/version 2>/dev/null; then
|
||||||
|
echo -e "\e[36mBuild exécuté dans WSL ($DISTRO_NAME) en tant que root...\e[0m"
|
||||||
|
IS_WSL=1
|
||||||
|
else
|
||||||
|
echo -e "\e[36mBuild exécuté sur Arch Linux natif en tant que root...\e[0m"
|
||||||
|
IS_WSL=0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Le dossier de travail = dossier qui contient ce script (gère les
|
||||||
|
# espaces du chemin, ex. "1. FWS").
|
||||||
|
WORK_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
echo "==> Dossier de travail : $WORK_DIR"
|
||||||
|
|
||||||
|
# pacman ≥ 7 sandboxe les ops FS via landlock, non supporté par le kernel
|
||||||
|
# WSL ni (selon le noyau) par le conteneur → désactivation. Idempotent,
|
||||||
|
# sans effet sur Arch natif.
|
||||||
|
if { [ "$IS_WSL" -eq 1 ] || [ -n "$FWS_IN_CONTAINER" ]; } \
|
||||||
|
&& ! grep -qE '^[[:space:]]*DisableSandbox' /etc/pacman.conf; then
|
||||||
|
sed -i '/^\[options\]/a DisableSandbox' /etc/pacman.conf
|
||||||
|
echo "==> WSL/conteneur détecté → DisableSandbox ajouté à /etc/pacman.conf"
|
||||||
|
fi
|
||||||
|
|
||||||
echo "==> Mise à jour des miroirs et installation de archiso..."
|
echo "==> Mise à jour des miroirs et installation de archiso..."
|
||||||
pacman -Sy --noconfirm reflector || true
|
pacman -Sy --noconfirm reflector || true
|
||||||
reflector --verbose --latest 10 --sort rate --save /etc/pacman.d/mirrorlist || true
|
reflector --verbose --latest 10 --sort rate --save /etc/pacman.d/mirrorlist || true
|
||||||
pacman -Sy --noconfirm archiso
|
if [ -n "$FWS_IN_CONTAINER" ]; then
|
||||||
|
# Image de base qui vieillit → upgrade complet AVANT d'ajouter archiso,
|
||||||
|
# sinon partial upgrade (archiso tire des deps plus récentes que la base).
|
||||||
|
pacman -Syu --noconfirm archiso
|
||||||
|
else
|
||||||
|
pacman -Sy --noconfirm archiso
|
||||||
|
fi
|
||||||
|
|
||||||
echo "==> Préparation de l'environnement de build..."
|
echo "==> Préparation de l'environnement de build..."
|
||||||
rm -rf /tmp/fws-build
|
rm -rf /tmp/fws-build
|
||||||
mkdir -p /tmp/fws-build/releng
|
mkdir -p /tmp/fws-build/releng
|
||||||
|
|
||||||
# Copie configs/releng/ en base
|
# Copie configs/releng/ en base
|
||||||
if [ -d "\$WORK_DIR/configs/releng" ]; then
|
if [ -d "$WORK_DIR/configs/releng" ]; then
|
||||||
cp -ar "\$WORK_DIR/configs/releng/"* /tmp/fws-build/releng/
|
cp -ar "$WORK_DIR/configs/releng/"* /tmp/fws-build/releng/
|
||||||
echo "==> configs/releng/ copié"
|
echo "==> configs/releng/ copié"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Fusionne configs/baseline/ par dessus (priorité aux fichiers baseline)
|
# Fusionne configs/baseline/ par dessus (priorité aux fichiers baseline)
|
||||||
if [ -d "\$WORK_DIR/configs/baseline" ]; then
|
if [ -d "$WORK_DIR/configs/baseline" ]; then
|
||||||
cp -ar "\$WORK_DIR/configs/baseline/"* /tmp/fws-build/releng/
|
cp -ar "$WORK_DIR/configs/baseline/"* /tmp/fws-build/releng/
|
||||||
echo "==> configs/baseline/ fusionné (prioritaire)"
|
echo "==> configs/baseline/ fusionné (prioritaire)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "==> Activation de NetworkManager.service sur le live (symlink réel WSL)..."
|
echo "==> Activation de NetworkManager.service sur le live (symlink réel)..."
|
||||||
mkdir -p /tmp/fws-build/releng/airootfs/etc/systemd/system/multi-user.target.wants
|
mkdir -p /tmp/fws-build/releng/airootfs/etc/systemd/system/multi-user.target.wants
|
||||||
ln -sf /usr/lib/systemd/system/NetworkManager.service \
|
ln -sf /usr/lib/systemd/system/NetworkManager.service \
|
||||||
/tmp/fws-build/releng/airootfs/etc/systemd/system/multi-user.target.wants/NetworkManager.service
|
/tmp/fws-build/releng/airootfs/etc/systemd/system/multi-user.target.wants/NetworkManager.service
|
||||||
@@ -57,19 +232,19 @@ echo "==> Vérification des services systemd..."
|
|||||||
ls /tmp/fws-build/releng/airootfs/etc/systemd/system/ 2>/dev/null || echo " (aucun service)"
|
ls /tmp/fws-build/releng/airootfs/etc/systemd/system/ 2>/dev/null || echo " (aucun service)"
|
||||||
ls /tmp/fws-build/releng/airootfs/etc/systemd/system/multi-user.target.wants/ 2>/dev/null || echo " (aucun symlink)"
|
ls /tmp/fws-build/releng/airootfs/etc/systemd/system/multi-user.target.wants/ 2>/dev/null || echo " (aucun symlink)"
|
||||||
|
|
||||||
# Copie le repo local (calamares + winboat-bin)
|
# Copie le repo local (winboat-bin + deps Anaconda packagées)
|
||||||
if ls "\$WORK_DIR/local-repo/"*.pkg.tar.zst &>/dev/null 2>&1; then
|
if ls "$WORK_DIR/local-repo/"*.pkg.tar.zst &>/dev/null 2>&1; then
|
||||||
echo "==> Copie du repo local Calamares..."
|
echo "==> Copie du repo local fws-local..."
|
||||||
mkdir -p /tmp/fws-build/local-repo
|
mkdir -p /tmp/fws-build/local-repo
|
||||||
cp -a "\$WORK_DIR/local-repo/"* /tmp/fws-build/local-repo/
|
cp -a "$WORK_DIR/local-repo/"* /tmp/fws-build/local-repo/
|
||||||
|
|
||||||
echo "==> Injection [fws-local] dans pacman.conf..."
|
echo "==> Injection [fws-local] dans pacman.conf..."
|
||||||
sed -i '/^\[fws-local\]/,/^$/d' /tmp/fws-build/releng/pacman.conf
|
sed -i '/^\[fws-local\]/,/^$/d' /tmp/fws-build/releng/pacman.conf
|
||||||
PACMAN_TMP=\$(mktemp)
|
PACMAN_TMP=$(mktemp)
|
||||||
printf '[fws-local]\nSigLevel = Optional TrustAll\nServer = file:///tmp/fws-build/local-repo\n\n' \
|
printf '[fws-local]\nSigLevel = Optional TrustAll\nServer = file:///tmp/fws-build/local-repo\n\n' \
|
||||||
> "\$PACMAN_TMP"
|
> "$PACMAN_TMP"
|
||||||
cat /tmp/fws-build/releng/pacman.conf >> "\$PACMAN_TMP"
|
cat /tmp/fws-build/releng/pacman.conf >> "$PACMAN_TMP"
|
||||||
mv "\$PACMAN_TMP" /tmp/fws-build/releng/pacman.conf
|
mv "$PACMAN_TMP" /tmp/fws-build/releng/pacman.conf
|
||||||
|
|
||||||
echo "==> Vérification pacman.conf :"
|
echo "==> Vérification pacman.conf :"
|
||||||
head -5 /tmp/fws-build/releng/pacman.conf
|
head -5 /tmp/fws-build/releng/pacman.conf
|
||||||
@@ -82,99 +257,31 @@ pacman -S --needed --noconfirm dos2unix
|
|||||||
find /tmp/fws-build/releng -type f -exec dos2unix {} + 2>/dev/null
|
find /tmp/fws-build/releng -type f -exec dos2unix {} + 2>/dev/null
|
||||||
|
|
||||||
echo "==> Lancement de mkarchiso..."
|
echo "==> Lancement de mkarchiso..."
|
||||||
# Simulation Try/Catch en Bash pour l'écriture du fichier ISO
|
mkdir -p "$WORK_DIR/out"
|
||||||
TARGET_OUT="\$WORK_DIR/out"
|
# mkarchiso fait un « rm » interne de l'ISO cible avant de la (ré)écrire ; si
|
||||||
mkdir -p "\$TARGET_OUT" 2>/dev/null || true
|
# une ISO du même nom est VERROUILLÉE par Windows (VM encore ouverte dessus,
|
||||||
|
# ISO montée, antivirus), ce rm échoue et tout le build casse à la toute fin.
|
||||||
|
# Parade : mkarchiso écrit dans un dossier de staging neuf, puis on déplace
|
||||||
|
# l'ISO. Si la cible est verrouillée, on bascule sur un nom horodaté → le
|
||||||
|
# build réussit quand même au lieu de tout perdre.
|
||||||
|
STAGE="$WORK_DIR/out/.staging-$$"
|
||||||
|
rm -rf "$STAGE"; mkdir -p "$STAGE"
|
||||||
|
mkarchiso -v -w /tmp/fws-build/work -o "$STAGE" /tmp/fws-build/releng
|
||||||
|
|
||||||
if [ -w "\$TARGET_OUT" ]; then
|
NEW_ISO="$(ls -1 "$STAGE/"*.iso 2>/dev/null | head -1)"
|
||||||
mkarchiso -v -w /tmp/fws-build/work -o "\$TARGET_OUT" /tmp/fws-build/releng
|
[ -n "$NEW_ISO" ] || { echo -e "\e[31mAucune ISO produite par mkarchiso.\e[0m" >&2; exit 1; }
|
||||||
echo "==> Build terminé ! ISO dans \$TARGET_OUT"
|
DEST="$WORK_DIR/out/$(basename "$NEW_ISO")"
|
||||||
|
if { chmod -f 666 "$DEST" 2>/dev/null; rm -f "$DEST" 2>/dev/null; } && mv -f "$NEW_ISO" "$DEST" 2>/dev/null; then
|
||||||
|
FINAL="$DEST"
|
||||||
else
|
else
|
||||||
echo -e "\e[33m[Attention] Impossible d'écrire dans \$TARGET_OUT. Utilisation d'un dossier temporaire de secours...\e[0m"
|
FINAL="$WORK_DIR/out/$(basename "${NEW_ISO%.iso}")-$(date +%H%M%S).iso"
|
||||||
BACKUP_OUT="/tmp/fws-out-backup"
|
echo -e "\e[33m[!] '$DEST' est verrouillée (une VM l'utilise ?). Écriture sous un nom unique.\e[0m" >&2
|
||||||
mkdir -p "\$BACKUP_OUT"
|
mv -f "$NEW_ISO" "$FINAL"
|
||||||
mkarchiso -v -w /tmp/fws-build/work -o "\$BACKUP_OUT" /tmp/fws-build/releng
|
|
||||||
echo -e "\e[32m==> Build terminé ! ISO sauvegardée en sécurité dans : \$BACKUP_OUT\e[0m"
|
|
||||||
fi
|
fi
|
||||||
|
rm -rf "$STAGE" 2>/dev/null || true
|
||||||
|
|
||||||
echo "==> Nettoyage..."
|
echo "==> Nettoyage..."
|
||||||
rm -rf /tmp/fws-build/work
|
rm -rf /tmp/fws-build/work
|
||||||
EOF
|
|
||||||
|
|
||||||
else
|
|
||||||
# ── Déjà dans WSL ────────────────────────────────────────
|
|
||||||
WORK_DIR="$PWD"
|
|
||||||
echo "==> Dossier de travail : $WORK_DIR"
|
|
||||||
|
|
||||||
echo "==> Mise à jour et installation de archiso..."
|
|
||||||
pacman -Sy --noconfirm reflector || true
|
|
||||||
reflector --verbose --latest 10 --sort rate --save /etc/pacman.d/mirrorlist || true
|
|
||||||
pacman -Sy --noconfirm archiso
|
|
||||||
|
|
||||||
echo "==> Préparation de l'environnement de build..."
|
|
||||||
rm -rf /tmp/fws-build
|
|
||||||
mkdir -p /tmp/fws-build/releng
|
|
||||||
|
|
||||||
if [ -d "$WORK_DIR/configs/releng" ]; then
|
|
||||||
cp -ar "$WORK_DIR/configs/releng/"* /tmp/fws-build/releng/
|
|
||||||
echo "==> configs/releng/ copié"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -d "$WORK_DIR/configs/baseline" ]; then
|
|
||||||
cp -ar "$WORK_DIR/configs/baseline/"* /tmp/fws-build/releng/
|
|
||||||
echo "==> configs/baseline/ fusionné (prioritaire)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "==> Activation de NetworkManager.service sur le live (symlink réel)..."
|
|
||||||
mkdir -p /tmp/fws-build/releng/airootfs/etc/systemd/system/multi-user.target.wants
|
|
||||||
ln -sf /usr/lib/systemd/system/NetworkManager.service \
|
|
||||||
/tmp/fws-build/releng/airootfs/etc/systemd/system/multi-user.target.wants/NetworkManager.service
|
|
||||||
|
|
||||||
echo "==> Vérification des services systemd..."
|
|
||||||
ls /tmp/fws-build/releng/airootfs/etc/systemd/system/ 2>/dev/null || echo " (aucun service)"
|
|
||||||
ls /tmp/fws-build/releng/airootfs/etc/systemd/system/multi-user.target.wants/ 2>/dev/null || echo " (aucun symlink)"
|
|
||||||
|
|
||||||
if ls "$WORK_DIR/local-repo/"*.pkg.tar.zst &>/dev/null 2>&1; then
|
|
||||||
echo "==> Copie du repo local Calamares..."
|
|
||||||
mkdir -p /tmp/fws-build/local-repo
|
|
||||||
cp -a "$WORK_DIR/local-repo/"* /tmp/fws-build/local-repo/
|
|
||||||
|
|
||||||
echo "==> Injection [fws-local] dans pacman.conf..."
|
|
||||||
sed -i '/^\[fws-local\]/,/^$/d' /tmp/fws-build/releng/pacman.conf
|
|
||||||
PACMAN_TMP=$(mktemp)
|
|
||||||
printf '[fws-local]\nSigLevel = Optional TrustAll\nServer = file:///tmp/fws-build/local-repo\n\n' \
|
|
||||||
> "$PACMAN_TMP"
|
|
||||||
cat /tmp/fws-build/releng/pacman.conf >> "$PACMAN_TMP"
|
|
||||||
mv "$PACMAN_TMP" /tmp/fws-build/releng/pacman.conf
|
|
||||||
|
|
||||||
echo "==> Vérification pacman.conf :"
|
|
||||||
head -5 /tmp/fws-build/releng/pacman.conf
|
|
||||||
else
|
|
||||||
echo "==> Aucun repo local détecté."
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "==> Correction des retours à la ligne Windows (dos2unix)..."
|
|
||||||
pacman -S --needed --noconfirm dos2unix
|
|
||||||
find /tmp/fws-build/releng -type f -exec dos2unix {} + 2>/dev/null
|
|
||||||
|
|
||||||
echo "==> Lancement de mkarchiso..."
|
|
||||||
# Simulation Try/Catch en Bash pour l'écriture du fichier ISO
|
|
||||||
TARGET_OUT="$WORK_DIR/out"
|
|
||||||
mkdir -p "$TARGET_OUT" 2>/dev/null || true
|
|
||||||
|
|
||||||
if [ -w "$TARGET_OUT" ]; then
|
|
||||||
mkarchiso -v -w /tmp/fws-build/work -o "$TARGET_OUT" /tmp/fws-build/releng
|
|
||||||
echo "==> Build terminé ! ISO dans $TARGET_OUT"
|
|
||||||
else
|
|
||||||
echo -e "\e[33m[Attention] Impossible d'écrire dans $TARGET_OUT. Utilisation d'un dossier temporaire de secours...\e[0m"
|
|
||||||
BACKUP_OUT="/tmp/fws-out-backup"
|
|
||||||
mkdir -p "$BACKUP_OUT"
|
|
||||||
mkarchiso -v -w /tmp/fws-build/work -o "$BACKUP_OUT" /tmp/fws-build/releng
|
|
||||||
echo -e "\e[32m==> Build terminé ! ISO sauvegardée en sécurité dans : $BACKUP_OUT\e[0m"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "==> Nettoyage..."
|
|
||||||
rm -rf /tmp/fws-build/work
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
echo "==> Build terminé ! ISO : $FINAL"
|
||||||
echo -e "\e[32mScript de build terminé avec succès.\e[0m"
|
echo -e "\e[32mScript de build terminé avec succès.\e[0m"
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
# ============================================================
|
|
||||||
# FWS Linux — branding.desc
|
|
||||||
# ============================================================
|
|
||||||
|
|
||||||
componentName: fws
|
|
||||||
|
|
||||||
strings:
|
|
||||||
productName: "FWS"
|
|
||||||
shortProductName: "FWS"
|
|
||||||
version: "1.0"
|
|
||||||
shortVersion: "1.0"
|
|
||||||
versionedName: "FWS 1.0"
|
|
||||||
shortVersionedName: "FWS 1.0"
|
|
||||||
bootloaderEntryName: "FWS"
|
|
||||||
productUrl: ""
|
|
||||||
supportUrl: ""
|
|
||||||
releaseNotesUrl: ""
|
|
||||||
donateUrl: ""
|
|
||||||
|
|
||||||
images:
|
|
||||||
productLogo: "logo.png"
|
|
||||||
productIcon: "logo.png"
|
|
||||||
productWelcome: "logo.png"
|
|
||||||
|
|
||||||
slideshow: "slideshow.qml"
|
|
||||||
slideshowAPI: 2
|
|
||||||
|
|
||||||
style:
|
|
||||||
# Couleurs de la sidebar
|
|
||||||
sidebarBackground: "#1a1a2e"
|
|
||||||
sidebarText: "#e0e0e0"
|
|
||||||
sidebarTextHighlight: "#00d4ff"
|
|
||||||
sidebarSelect: "#16213e"
|
|
||||||
|
|
||||||
# Couleurs générales
|
|
||||||
backgroundColor: "#0f3460"
|
|
||||||
highlightedTextColor: "#ffffff"
|
|
||||||
genericTextColor: "#e0e0e0"
|
|
||||||
errorTextColor: "#ff6b6b"
|
|
||||||
warningTextColor: "#ffa500"
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 11 KiB |
@@ -1,138 +0,0 @@
|
|||||||
/* ============================================================
|
|
||||||
FWS Linux — slideshow.qml
|
|
||||||
Affiché pendant l'installation
|
|
||||||
============================================================ */
|
|
||||||
|
|
||||||
import QtQuick 2.0
|
|
||||||
import calamares.slideshow 1.0
|
|
||||||
|
|
||||||
Presentation {
|
|
||||||
id: presentation
|
|
||||||
|
|
||||||
function nextSlide() {
|
|
||||||
if (presentation.currentSlide < slides.count - 1)
|
|
||||||
presentation.currentSlide++
|
|
||||||
else
|
|
||||||
presentation.currentSlide = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
Timer {
|
|
||||||
id: timer
|
|
||||||
interval: 4000
|
|
||||||
repeat: true
|
|
||||||
running: true
|
|
||||||
onTriggered: nextSlide()
|
|
||||||
}
|
|
||||||
|
|
||||||
Slide {
|
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
anchors.fill: parent
|
|
||||||
color: "#1a1a2e"
|
|
||||||
|
|
||||||
Column {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
spacing: 20
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "🚀 Bienvenue sur FWS Linux"
|
|
||||||
color: "#00d4ff"
|
|
||||||
font.pixelSize: 32
|
|
||||||
font.bold: true
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
}
|
|
||||||
Text {
|
|
||||||
text: "Un système rapide, léger et puissant."
|
|
||||||
color: "#e0e0e0"
|
|
||||||
font.pixelSize: 18
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Slide {
|
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
anchors.fill: parent
|
|
||||||
color: "#16213e"
|
|
||||||
|
|
||||||
Column {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
spacing: 20
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "⚡ Basé sur Arch Linux"
|
|
||||||
color: "#00d4ff"
|
|
||||||
font.pixelSize: 32
|
|
||||||
font.bold: true
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
}
|
|
||||||
Text {
|
|
||||||
text: "Accès à l'AUR et aux derniers paquets."
|
|
||||||
color: "#e0e0e0"
|
|
||||||
font.pixelSize: 18
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Slide {
|
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
anchors.fill: parent
|
|
||||||
color: "#0f3460"
|
|
||||||
|
|
||||||
Column {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
spacing: 20
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "🛡️ Sécurité & Stabilité"
|
|
||||||
color: "#00d4ff"
|
|
||||||
font.pixelSize: 32
|
|
||||||
font.bold: true
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
}
|
|
||||||
Text {
|
|
||||||
text: "FWS est conçu pour être robuste et fiable."
|
|
||||||
color: "#e0e0e0"
|
|
||||||
font.pixelSize: 18
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Slide {
|
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
anchors.fill: parent
|
|
||||||
color: "#1a1a2e"
|
|
||||||
|
|
||||||
Column {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
spacing: 20
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "✅ Installation en cours..."
|
|
||||||
color: "#00d4ff"
|
|
||||||
font.pixelSize: 32
|
|
||||||
font.bold: true
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
}
|
|
||||||
Text {
|
|
||||||
text: "Merci de patienter, FWS s'installe sur votre machine."
|
|
||||||
color: "#e0e0e0"
|
|
||||||
font.pixelSize: 18
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
---
|
|
||||||
efiBootLoader: "grub"
|
|
||||||
|
|
||||||
kernel: "/vmlinuz-linux"
|
|
||||||
img: "/initramfs-linux.img"
|
|
||||||
fallback: "/initramfs-linux-fallback.img"
|
|
||||||
timeout: "5"
|
|
||||||
|
|
||||||
grubInstall: "grub-install"
|
|
||||||
grubMkconfig: "grub-mkconfig"
|
|
||||||
grubCfg: "/boot/grub/grub.cfg"
|
|
||||||
grubProbe: "grub-probe"
|
|
||||||
efiBootMgr: "efibootmgr"
|
|
||||||
|
|
||||||
efiDirectory: "/boot/efi"
|
|
||||||
efiBootloaderId: "FWS"
|
|
||||||
|
|
||||||
installEFIFallback: true
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
---
|
|
||||||
restartNowEnabled: true
|
|
||||||
restartNowChecked: false
|
|
||||||
restartNowCommand: "systemctl -i reboot"
|
|
||||||
|
|
||||||
notifyOnFinished: true
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
---
|
|
||||||
mountOptions:
|
|
||||||
default: defaults,noatime
|
|
||||||
btrfs: defaults,noatime,compress=zstd,space_cache=v2
|
|
||||||
|
|
||||||
ssdExtraMountOptions:
|
|
||||||
ext4: discard
|
|
||||||
jfs: discard
|
|
||||||
xfs: discard
|
|
||||||
swap: discard
|
|
||||||
btrfs: discard=async
|
|
||||||
|
|
||||||
crypttabOptions: luks,keyscript=/bin/cat
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
---
|
|
||||||
overwrite: true
|
|
||||||
|
|
||||||
kernel_params:
|
|
||||||
- "quiet"
|
|
||||||
|
|
||||||
defaults:
|
|
||||||
GRUB_TIMEOUT: 5
|
|
||||||
GRUB_DEFAULT: "saved"
|
|
||||||
GRUB_DISABLE_SUBMENU: true
|
|
||||||
GRUB_TERMINAL_OUTPUT: "console"
|
|
||||||
GRUB_DISABLE_RECOVERY: true
|
|
||||||
GRUB_DISTRIBUTOR: "FWS"
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
---
|
|
||||||
location: EtcFile
|
|
||||||
writeHostsFile: true
|
|
||||||
setSystemdHostname: EtcFile
|
|
||||||
|
|
||||||
template: "fws-${first}"
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
---
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
---
|
|
||||||
# Hooks par défaut Arch + support clavier/LUKS avant block/filesystems.
|
|
||||||
modules: []
|
|
||||||
binaries: []
|
|
||||||
files: []
|
|
||||||
|
|
||||||
hooks:
|
|
||||||
- base
|
|
||||||
- udev
|
|
||||||
- autodetect
|
|
||||||
- microcode
|
|
||||||
- modconf
|
|
||||||
- kms
|
|
||||||
- keyboard
|
|
||||||
- keymap
|
|
||||||
- consolefont
|
|
||||||
- block
|
|
||||||
- filesystems
|
|
||||||
- fsck
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
---
|
|
||||||
xOrgConfFileName: "00-keyboard.conf"
|
|
||||||
convertedKeymapPath: "/usr/share/X11/xkb/symbols/pc"
|
|
||||||
keyboardLayout: "fr"
|
|
||||||
keyboardVariant: ""
|
|
||||||
keyboardModel: "pc105"
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
---
|
|
||||||
region: "Europe"
|
|
||||||
zone: "Paris"
|
|
||||||
localeGenPath: "/etc/locale.gen"
|
|
||||||
geoipStyle: "json"
|
|
||||||
geoipUrl: "https://geoip.kde.org/v1/calamares"
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
---
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
systemd: true
|
|
||||||
dbus: true
|
|
||||||
dbus-symlink: true
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
---
|
|
||||||
extraMounts:
|
|
||||||
- device: proc
|
|
||||||
fs: proc
|
|
||||||
mountPoint: /proc
|
|
||||||
- device: sys
|
|
||||||
fs: sysfs
|
|
||||||
mountPoint: /sys
|
|
||||||
- device: /dev
|
|
||||||
mountPoint: /dev
|
|
||||||
options: [bind]
|
|
||||||
- device: /dev/pts
|
|
||||||
fs: devpts
|
|
||||||
mountPoint: /dev/pts
|
|
||||||
- device: tmpfs
|
|
||||||
fs: tmpfs
|
|
||||||
mountPoint: /run
|
|
||||||
- device: /run/udev
|
|
||||||
mountPoint: /run/udev
|
|
||||||
options: [bind]
|
|
||||||
|
|
||||||
extraMountsEfi:
|
|
||||||
- device: efivarfs
|
|
||||||
fs: efivarfs
|
|
||||||
mountPoint: /sys/firmware/efi/efivars
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
---
|
|
||||||
# Copie /etc/NetworkManager du live vers le système cible (NM gérera le réseau).
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
---
|
|
||||||
# Étape post-unpackfs : on retire les paquets qui ne servent que dans
|
|
||||||
# l'ISO live (installeur + outils archiso). Les paquets utiles sont déjà
|
|
||||||
# présents sur le système cible parce qu'unpackfs a copié tout le live.
|
|
||||||
|
|
||||||
backend: pacman
|
|
||||||
update_db: false
|
|
||||||
update_system: false
|
|
||||||
|
|
||||||
operations:
|
|
||||||
- remove:
|
|
||||||
- calamares
|
|
||||||
- kpmcore
|
|
||||||
- archinstall
|
|
||||||
- livecd-sounds
|
|
||||||
- mkinitcpio-archiso
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
---
|
|
||||||
efiSystemPartition: "/boot/efi"
|
|
||||||
efiSystemPartitionSize: 300M
|
|
||||||
efiSystemPartitionName: EFI
|
|
||||||
|
|
||||||
userSwapChoices:
|
|
||||||
- none
|
|
||||||
- small
|
|
||||||
- suspend
|
|
||||||
- file
|
|
||||||
|
|
||||||
drawNestedPartitions: true
|
|
||||||
alwaysShowPartitionLabels: true
|
|
||||||
|
|
||||||
initialPartitioningChoice: replace
|
|
||||||
initialSwapChoice: small
|
|
||||||
|
|
||||||
defaultFileSystemType: "ext4"
|
|
||||||
availableFileSystemTypes: ["ext4", "btrfs", "xfs", "f2fs"]
|
|
||||||
|
|
||||||
enableLuksAutomatedPartitioning: true
|
|
||||||
allowManualPartitioning: true
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
---
|
|
||||||
services:
|
|
||||||
- name: NetworkManager
|
|
||||||
mandatory: true
|
|
||||||
|
|
||||||
- name: systemd-resolved
|
|
||||||
mandatory: true
|
|
||||||
|
|
||||||
- name: systemd-timesyncd
|
|
||||||
mandatory: true
|
|
||||||
|
|
||||||
- name: sshd
|
|
||||||
mandatory: false
|
|
||||||
|
|
||||||
targets: []
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
---
|
|
||||||
# Copie le squashfs du live vers le disque cible.
|
|
||||||
# Le chemin /run/archiso/bootmnt/<install_dir>/<arch>/airootfs.sfs
|
|
||||||
# doit correspondre à `install_dir` dans configs/releng/profiledef.sh ("fws").
|
|
||||||
|
|
||||||
unpack:
|
|
||||||
- source: "/run/archiso/bootmnt/fws/x86_64/airootfs.sfs"
|
|
||||||
sourcefs: "squashfs"
|
|
||||||
destination: ""
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
---
|
|
||||||
defaultGroups:
|
|
||||||
- wheel
|
|
||||||
- audio
|
|
||||||
- video
|
|
||||||
- network
|
|
||||||
- storage
|
|
||||||
- power
|
|
||||||
- lp
|
|
||||||
- scanner
|
|
||||||
|
|
||||||
autologinGroup: autologin
|
|
||||||
sudoersGroup: wheel
|
|
||||||
setRootPassword: true
|
|
||||||
doAutologin: false
|
|
||||||
userShell: /bin/bash
|
|
||||||
|
|
||||||
passwordRequirements:
|
|
||||||
minLength: 6
|
|
||||||
maxLength: -1
|
|
||||||
nonempty: true
|
|
||||||
|
|
||||||
allowWeakPasswords: false
|
|
||||||
allowWeakPasswordsDefault: false
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
---
|
|
||||||
showSupportUrl: true
|
|
||||||
showKnownIssuesUrl: true
|
|
||||||
showReleaseNotesUrl: false
|
|
||||||
showDonateUrl: false
|
|
||||||
|
|
||||||
requirements:
|
|
||||||
requiredStorage: 8.0
|
|
||||||
requiredRam: 1.5
|
|
||||||
internetCheckUrl: "https://archlinux.org"
|
|
||||||
check:
|
|
||||||
- storage
|
|
||||||
- ram
|
|
||||||
- power
|
|
||||||
- root
|
|
||||||
- screen
|
|
||||||
required:
|
|
||||||
- storage
|
|
||||||
- ram
|
|
||||||
- root
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
---
|
|
||||||
# ============================================================
|
|
||||||
# FWS — Calamares settings
|
|
||||||
# ============================================================
|
|
||||||
|
|
||||||
modules-search: [ local, /usr/lib/calamares/modules ]
|
|
||||||
|
|
||||||
sequence:
|
|
||||||
- show:
|
|
||||||
- welcome
|
|
||||||
- locale
|
|
||||||
- keyboard
|
|
||||||
- partition
|
|
||||||
- users
|
|
||||||
- summary
|
|
||||||
- exec:
|
|
||||||
- partition
|
|
||||||
- mount
|
|
||||||
- unpackfs
|
|
||||||
- machineid
|
|
||||||
- fstab
|
|
||||||
- locale
|
|
||||||
- keyboard
|
|
||||||
- localecfg
|
|
||||||
- users
|
|
||||||
- hostname
|
|
||||||
- hwclock
|
|
||||||
- networkcfg
|
|
||||||
- initcpiocfg
|
|
||||||
- initcpio
|
|
||||||
- grubcfg
|
|
||||||
- bootloader
|
|
||||||
- packages
|
|
||||||
- services-systemd
|
|
||||||
- umount
|
|
||||||
- show:
|
|
||||||
- finished
|
|
||||||
|
|
||||||
branding: fws
|
|
||||||
|
|
||||||
prompt-install: true
|
|
||||||
dont-chroot: false
|
|
||||||
oem-setup: false
|
|
||||||
disable-cancel: false
|
|
||||||
disable-cancel-during-exec: false
|
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
# FWS — force le plugin LVM de libblockdev en mode CLI (libbd_lvm.so) au lieu
|
||||||
|
# du mode DBus (libbd_lvm-dbus.so).
|
||||||
|
#
|
||||||
|
# POURQUOI : libblockdev 3.x sur Arch charge par défaut la variante LVM qui
|
||||||
|
# pilote le démon « lvmdbusd » (service DBus com.redhat.lvmdbus1). Or Arch ne
|
||||||
|
# package PAS lvmdbusd (lvm2 ne livre ni le binaire ni le .service DBus). Quand
|
||||||
|
# Anaconda/blivet peuple l'arbre des périphériques, blivet appelle
|
||||||
|
# blockdev.lvm.lvs() → la variante DBus tente d'activer com.redhat.lvmdbus1 →
|
||||||
|
# GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown: name is not activatable
|
||||||
|
# ce qui FAIT PLANTER Anaconda au démarrage.
|
||||||
|
#
|
||||||
|
# La variante CLI (libbd_lvm.so) parle directement aux binaires LVM (lvs, vgs…)
|
||||||
|
# sans démon → fonctionne sans lvmdbusd. Ce fichier conf.d (numéro élevé → lu
|
||||||
|
# après 00-default.cfg) force ce choix de façon fiable.
|
||||||
|
[lvm]
|
||||||
|
sonames=libbd_lvm.so.3
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
# FWS — locales à générer dans l'ISO (par locale-gen, via le hook pacman
|
||||||
|
# etc/pacman.d/hooks/zzz-fws-locale-gen.hook au moment du pacstrap).
|
||||||
|
#
|
||||||
|
# en_US.UTF-8 est REQUIS par Anaconda : ses modules DBus font
|
||||||
|
# locale.setlocale(LC_ALL, "en_US.UTF-8") (DEFAULT_LANG)
|
||||||
|
# au démarrage → sans cette locale générée : « locale.Error: unsupported
|
||||||
|
# locale setting » et le module Boss sort en status 1 (installateur planté).
|
||||||
|
# C.UTF-8 (la locale par défaut du live, cf. locale.conf) est intégrée à la
|
||||||
|
# glibc et n'a pas besoin d'être générée.
|
||||||
|
en_US.UTF-8 UTF-8
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
# FWS — expose la base squashfs du live à /run/rootfsbase.
|
||||||
|
#
|
||||||
|
# POURQUOI : avec --liveinst, Anaconda utilise le payload « LiveOS » qui RECOPIE
|
||||||
|
# le système live en cours sur le disque. Sa tâche DetectLiveOSImageTask cherche
|
||||||
|
# l'image de base à /dev/mapper/live-base, /dev/mapper/live-osimg-min ou
|
||||||
|
# /run/rootfsbase (conventions dracut-live de Fedora). archiso n'en crée AUCUNE
|
||||||
|
# → « SourceSetupError: No Live OS image found! » et l'installateur plante.
|
||||||
|
#
|
||||||
|
# archiso a pourtant la squashfs (montée en lecture seule sur /run/archiso/
|
||||||
|
# airootfs). On la remonte ici en loop sur /run/rootfsbase pour qu'Anaconda la
|
||||||
|
# détecte : findmnt -o SOURCE /run/rootfsbase → /dev/loopN, qu'Anaconda monte
|
||||||
|
# puis recopie sur la cible (= installe FWS). Le %post du kickstart fait ensuite
|
||||||
|
# mkinitcpio + grub-install (bootloader --disabled côté Anaconda).
|
||||||
|
[Unit]
|
||||||
|
Description=FWS — base squashfs sur /run/rootfsbase (payload LiveOS Anaconda)
|
||||||
|
DefaultDependencies=no
|
||||||
|
After=local-fs.target
|
||||||
|
ConditionPathExists=/run/archiso/bootmnt/fws/x86_64/airootfs.sfs
|
||||||
|
ConditionPathIsMountPoint=!/run/rootfsbase
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
RemainAfterExit=yes
|
||||||
|
ExecStart=/usr/bin/mkdir -p /run/rootfsbase
|
||||||
|
ExecStart=/usr/bin/mount -o loop,ro /run/archiso/bootmnt/fws/x86_64/airootfs.sfs /run/rootfsbase
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
@@ -1,6 +1,242 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# Lancé par startx (cf. /root/.zprofile)
|
# Lancé par startx (cf. /root/.zprofile), uniquement dans le live FWS.
|
||||||
|
if [ ! -d /run/archiso ]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
xsetroot -solid "#1a1a2e"
|
xsetroot -solid "#1a1a2e"
|
||||||
|
|
||||||
|
# Openbox en arrière-plan : gestionnaire de fenêtres pour l'installateur.
|
||||||
openbox &
|
openbox &
|
||||||
sleep 1
|
_OB_PID=$!
|
||||||
exec calamares
|
|
||||||
|
# Chantier C : lance l'installateur Anaconda en mode live s'il est présent.
|
||||||
|
# « liveinst » re-exécute anaconda (ici on est déjà root → pas de pkexec/polkit).
|
||||||
|
#
|
||||||
|
# DEBUG (premier run réel) : on CAPTURE stdout+stderr — un plantage d'import
|
||||||
|
# précoce de Python n'apparaît QUE là, pas dans /tmp/anaconda.log — et, si
|
||||||
|
# liveinst quitte en erreur, on regroupe tous les logs Anaconda et on les AFFICHE
|
||||||
|
# (zenity) au lieu de laisser startx rendre la main → .zprofile relancerait X en
|
||||||
|
# boucle (symptôme « fond bleu qui clignote/reboote »). On NE rend jamais la main
|
||||||
|
# à startx : on reste sur Openbox pour lire les logs / rebooter proprement.
|
||||||
|
if command -v liveinst >/dev/null 2>&1; then
|
||||||
|
# Payload LiveOS : avec --liveinst (passé par liveinst), Anaconda IGNORE le
|
||||||
|
# payload du kickstart (anaconda.py teste opts.liveinst AVANT le type du
|
||||||
|
# payload DBus — un « liveimg » dans le ks serait du code mort) et détecte
|
||||||
|
# l'image live sur des chemins Fedora/dracut : /dev/mapper/live-base,
|
||||||
|
# /dev/mapper/live-osimg-min ou /run/rootfsbase — tous ABSENTS d'archiso →
|
||||||
|
# « SourceSetupError: No Live OS image found! » = crash au démarrage
|
||||||
|
# (reproduit hors VM dans un chroot de l'airootfs). On expose donc le
|
||||||
|
# squashfs archiso (monté ro sur /run/archiso/airootfs) là où Anaconda le
|
||||||
|
# cherche : findmnt y résout le loop device → montage → rsync vers la cible.
|
||||||
|
if [ -d /run/archiso/airootfs ] && [ ! -e /run/rootfsbase ]; then
|
||||||
|
mkdir -p /run/rootfsbase
|
||||||
|
mount --bind /run/archiso/airootfs /run/rootfsbase || rmdir /run/rootfsbase
|
||||||
|
fi
|
||||||
|
|
||||||
|
# GARDE-FOU RAM : le live n'a que le zram comme marge — en dessous de
|
||||||
|
# ~2 Go, Anaconda (GUI Python + squashfs) peut geler la machine en plein
|
||||||
|
# « Préparation de l'installateur ». On prévient AVANT plutôt que de
|
||||||
|
# laisser l'utilisateur croire à un bug.
|
||||||
|
_MEMKB=$(awk '/^MemTotal:/{print $2}' /proc/meminfo 2>/dev/null)
|
||||||
|
if [ -n "$_MEMKB" ] && [ "$_MEMKB" -lt 2000000 ] && command -v zenity >/dev/null 2>&1; then
|
||||||
|
zenity --warning --width=460 --title="FWS — mémoire insuffisante ?" \
|
||||||
|
--text="<b>Cette machine n'a que $(( _MEMKB / 1024 )) Mo de RAM.</b>\n\nL'installateur graphique peut geler en dessous de 2 Go.\nEn VM : augmente la mémoire (4 Go recommandés) puis redémarre.\n\nOK pour tenter quand même." 2>/dev/null
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ÉCRAN D'ATTENTE immédiat : le démarrage d'anaconda peut prendre 2 à
|
||||||
|
# 4 minutes (observé en VM VMware : un worker udev se bloque au boot et
|
||||||
|
# n'est tué par udevd qu'après 45 s — udev.event_timeout). Sans feedback,
|
||||||
|
# l'utilisateur croit à une panne alors que TOUT va bien. Le splash montre
|
||||||
|
# EN DIRECT ce que fait anaconda : un nourrisseur écrit sur stdin de
|
||||||
|
# zenity --progress (« # texte » = mise à jour du libellé) le log anaconda
|
||||||
|
# le plus récemment modifié + son dernier message + un chrono. Si les logs
|
||||||
|
# ne bougent plus (vrai blocage), le libellé le DIT (au lieu d'une barre
|
||||||
|
# qui pulse pour rien) et, au-delà de 4 min d'inactivité, on collecte
|
||||||
|
# journal+dmesg dans /tmp/fws-stall.txt et on l'affiche : l'écran devient
|
||||||
|
# lui-même le rapport de bug. Le nourrisseur meurt par SIGPIPE quand le
|
||||||
|
# splash est tué à la sortie de liveinst.
|
||||||
|
_SPLASH_PID=""
|
||||||
|
if command -v zenity >/dev/null 2>&1; then
|
||||||
|
(
|
||||||
|
_el=0; _quiet=0; _prevstamp=""
|
||||||
|
while :; do
|
||||||
|
sleep 3
|
||||||
|
# GUI d'anaconda à l'écran (marqueur ui.gui) → le splash n'a
|
||||||
|
# plus de raison d'être et le watchdog DOIT se désarmer : des
|
||||||
|
# logs silencieux pendant que l'utilisateur remplit les écrans
|
||||||
|
# sont NORMAUX (bug vécu : le rapport « préparation bloquée »
|
||||||
|
# s'affichait PAR-DESSUS l'installateur au bout de 4 min).
|
||||||
|
if grep -q 'ui\.gui' /tmp/anaconda.log 2>/dev/null; then
|
||||||
|
pkill -f 'zenity --progress' 2>/dev/null
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
# Compteurs en itérations (pas d'heure murale : l'horloge du
|
||||||
|
# guest SAUTE en VM — resynchro RTC — et gonflerait les âges,
|
||||||
|
# vu en vrai : « 242 s d'inactivité » 90 s après le boot).
|
||||||
|
_el=$(( _el + 3 ))
|
||||||
|
_last=$(ls -t /tmp/storage.log /tmp/anaconda.log /tmp/program.log /tmp/dbus.log 2>/dev/null | head -n1)
|
||||||
|
if [ -z "$_last" ]; then
|
||||||
|
printf '# Démarrage d'"'"'Anaconda… (%d min %02d s)\n' $(( _el / 60 )) $(( _el % 60 )) || exit 0
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
_stamp=$(stat -c %Y "$_last" 2>/dev/null)
|
||||||
|
if [ "$_stamp" = "$_prevstamp" ]; then
|
||||||
|
_quiet=$(( _quiet + 3 ))
|
||||||
|
else
|
||||||
|
_quiet=0; _prevstamp="$_stamp"
|
||||||
|
fi
|
||||||
|
# Rebranding d'affichage : anaconda (installateur Fedora) parle
|
||||||
|
# de Fedora/Arch dans ses logs — on ne montre pas ça à l'écran.
|
||||||
|
_msg=$(tail -n1 "$_last" 2>/dev/null | tr -d '\r' \
|
||||||
|
| sed -E 's/Fedora( Linux)?/FWS/g; s/Arch Linux/FWS/g; s/\<Arch\>/FWS/g' \
|
||||||
|
| cut -c1-90)
|
||||||
|
if [ "$_quiet" -ge 240 ] && [ ! -f /tmp/fws-stall.txt ]; then
|
||||||
|
{
|
||||||
|
echo "=== FWS : préparation bloquée (aucune activité log depuis ${_quiet}s) ==="
|
||||||
|
echo "--- dernier log actif : $_last"; tail -n 25 "$_last" 2>/dev/null
|
||||||
|
echo "--- udev (workers bloqués ?)"; udevadm settle --timeout=0 2>&1
|
||||||
|
echo "--- journal (fin)"; journalctl -b --no-pager 2>/dev/null | tail -n 60
|
||||||
|
echo "--- dmesg (fin)"; dmesg 2>/dev/null | tail -n 40
|
||||||
|
} > /tmp/fws-stall.txt 2>&1
|
||||||
|
zenity --text-info --title="FWS — préparation bloquée : diagnostic" \
|
||||||
|
--filename=/tmp/fws-stall.txt --width=1000 --height=650 2>/dev/null &
|
||||||
|
fi
|
||||||
|
if [ "$_quiet" -ge 60 ]; then
|
||||||
|
printf '# ⚠ Aucune activité depuis %d s (%s) — dernier message : %s\n' "$_quiet" "$(basename "$_last")" "$_msg" || exit 0
|
||||||
|
else
|
||||||
|
printf '# Préparation (%d min %02d s) — %s : %s\n' $(( _el / 60 )) $(( _el % 60 )) "$(basename "$_last")" "$_msg" || exit 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
) | zenity --progress --pulsate --no-cancel \
|
||||||
|
--title="FWS" \
|
||||||
|
--text="<b>Préparation de l'installateur FWS…</b>\n\nAnalyse du matériel et des disques en cours.\nEncore une à deux minutes, c'est normal." \
|
||||||
|
--width=560 2>/dev/null &
|
||||||
|
_SPLASH_PID=$!
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Hub Résumé SANS le libellé « We won't touch your disks… » : notre glade
|
||||||
|
# modifié NE PEUT PAS être livré directement à son chemin final —
|
||||||
|
# mkarchiso pose l'overlay airootfs AVANT pacstrap, et pacman refuse
|
||||||
|
# alors d'installer anaconda par-dessus (« exists in filesystem »). On le
|
||||||
|
# livre donc sous /usr/local/share/fws et on ÉCRASE ici, au boot du live
|
||||||
|
# (l'overlay du live est inscriptible), le fichier du paquet.
|
||||||
|
if [ -f /usr/local/share/fws/anaconda-summary-hub.glade ]; then
|
||||||
|
cp -f /usr/local/share/fws/anaconda-summary-hub.glade \
|
||||||
|
/usr/share/anaconda/ui/hubs/summary.glade 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# BRANDING : sans /.buildstamp, anaconda s'appelle « anaconda bluesky »
|
||||||
|
# (défauts de pyanaconda/core/product.py) et ses logs parlent de Fedora.
|
||||||
|
# Les variables d'environnement ANACONDA_* ont priorité → l'en-tête
|
||||||
|
# devient « FWS 1.0 INSTALLATION » et le log « anaconda … for FWS started ».
|
||||||
|
# (Les mentions Fedora PROFONDES dans les logs — GeoIP, profils — restent :
|
||||||
|
# ce sont des chaînes internes de l'installateur, sans effet sur l'install.)
|
||||||
|
export ANACONDA_PRODUCTNAME="$(. /etc/os-release 2>/dev/null; echo "${NAME:-FWS}")"
|
||||||
|
export ANACONDA_PRODUCTVERSION="$(. /etc/os-release 2>/dev/null; echo "${VERSION_ID:-0.6}")"
|
||||||
|
export ANACONDA_ISFINAL=true
|
||||||
|
|
||||||
|
LIVEINST_LOG=/tmp/fws-liveinst.log
|
||||||
|
# Bus D-Bus de SESSION : au démarrage (--liveinst), inhibit_screensaver()
|
||||||
|
# de pyanaconda se connecte au bus de session. S'il n'y en a AUCUN (notre
|
||||||
|
# startx root minimal n'en garantit pas), Gio lève une GLib.GError que
|
||||||
|
# pyanaconda n'attrape PAS (il n'attrape que DBusError) → crash immédiat
|
||||||
|
# (2e crash reproduit hors VM). dbus-run-session fournit un bus de session
|
||||||
|
# pour toute la durée de l'installateur ; avec un bus présent, l'absence du
|
||||||
|
# service ScreenSaver est attrapée (simple warning dans anaconda.log).
|
||||||
|
if command -v dbus-run-session >/dev/null 2>&1 && [ -z "${DBUS_SESSION_BUS_ADDRESS:-}" ]; then
|
||||||
|
dbus-run-session -- liveinst >"$LIVEINST_LOG" 2>&1
|
||||||
|
else
|
||||||
|
liveinst >"$LIVEINST_LOG" 2>&1
|
||||||
|
fi
|
||||||
|
rc=$?
|
||||||
|
|
||||||
|
# liveinst terminé (install finie ou échec) : le splash n'a plus de raison
|
||||||
|
# d'être — kill de zenity ; le nourrisseur meurt de SIGPIPE à son
|
||||||
|
# prochain printf. Idem pour un éventuel dialogue de diagnostic de stall.
|
||||||
|
if [ -n "$_SPLASH_PID" ]; then
|
||||||
|
pkill -P "$_SPLASH_PID" 2>/dev/null
|
||||||
|
kill "$_SPLASH_PID" 2>/dev/null
|
||||||
|
fi
|
||||||
|
pkill -f "fws-stall.txt" 2>/dev/null
|
||||||
|
|
||||||
|
# ATTENTION : liveinst NE propage PAS le code de sortie d'anaconda — il
|
||||||
|
# enchaîne son propre nettoyage et sort souvent 0 même quand anaconda a
|
||||||
|
# planté. On ne se fie donc PAS à $rc : en phase debug on regroupe TOUS les
|
||||||
|
# logs et on les affiche systématiquement (zenity). Le traceback Python d'un
|
||||||
|
# crash d'import précoce n'est QUE dans $LIVEINST_LOG (stderr capturé).
|
||||||
|
# Log du %post chrooté (grub-install / mkinitcpio) = CE qui rend le disque
|
||||||
|
# bootable. Le kickstart en copie une version dans le LIVE
|
||||||
|
# (/tmp/fws-post-chroot.log, via un %post --nochroot final, cible encore
|
||||||
|
# montée → fiable). SECOURS si absent : on réactive le LVM (pvscan/vgscan
|
||||||
|
# rescannent les PV qu'Anaconda a désactivés) et on remonte le disque pour
|
||||||
|
# le lire.
|
||||||
|
if [ ! -s /tmp/fws-post-chroot.log ]; then
|
||||||
|
pvscan --cache >/dev/null 2>&1 || true
|
||||||
|
vgscan --mknodes >/dev/null 2>&1 || true
|
||||||
|
vgchange -ay >/dev/null 2>&1 || true
|
||||||
|
udevadm settle --timeout=10 >/dev/null 2>&1 || true
|
||||||
|
mkdir -p /run/fws-installed
|
||||||
|
for _dev in /dev/mapper/*-root /dev/mapper/* /dev/sd*[0-9] /dev/vd*[0-9] /dev/nvme*n*p*; do
|
||||||
|
[ -b "$_dev" ] || continue
|
||||||
|
mount -o ro "$_dev" /run/fws-installed 2>/dev/null || continue
|
||||||
|
if [ -f /run/fws-installed/var/log/fws-post.log ]; then
|
||||||
|
cp -f /run/fws-installed/var/log/fws-post.log /tmp/fws-post-chroot.log 2>/dev/null
|
||||||
|
umount /run/fws-installed 2>/dev/null || true
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
umount /run/fws-installed 2>/dev/null || true
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
DBG=/tmp/fws-debug.txt
|
||||||
|
{
|
||||||
|
echo "===== liveinst sorti (code $rc) — logs Anaconda ====="
|
||||||
|
echo
|
||||||
|
echo "########## sortie liveinst (stdout+stderr) ##########"
|
||||||
|
cat "$LIVEINST_LOG" 2>/dev/null
|
||||||
|
echo
|
||||||
|
echo "########## %post chrooté = grub-install / mkinitcpio ##########"
|
||||||
|
echo "########## >>> C'EST CE BLOC QUI DIT SI LE DISQUE VA BOOTER <<< ##########"
|
||||||
|
cat /tmp/fws-post-chroot.log 2>/dev/null || echo "(log introuvable)"
|
||||||
|
echo
|
||||||
|
echo "########## %post --nochroot (/tmp/fws-post-nochroot.log) ##########"
|
||||||
|
cat /tmp/fws-post-nochroot.log 2>/dev/null || echo "(absent)"
|
||||||
|
echo
|
||||||
|
echo "########## Récapitulatif (page GUI fws_recap, avant install) ##########"
|
||||||
|
cat /tmp/fws-hw-summary.txt 2>/dev/null || echo "(absent — page récap pas atteinte)"
|
||||||
|
for f in /tmp/anaconda.log /tmp/syslog /tmp/program.log \
|
||||||
|
/tmp/storage.log /tmp/dbus.log /tmp/packaging.log /tmp/X.log; do
|
||||||
|
echo
|
||||||
|
echo "########## $f ##########"
|
||||||
|
tail -n 200 "$f" 2>/dev/null || echo "(absent)"
|
||||||
|
done
|
||||||
|
} >"$DBG" 2>&1
|
||||||
|
|
||||||
|
# Succès d'install = les DEUX étapes qui rendent le disque bootable ont
|
||||||
|
# réussi dans le %post : mkinitcpio (« Initcpio image generation successful »)
|
||||||
|
# ET grub-install (« Installation finished. No error reported. »). Si oui →
|
||||||
|
# on montre un écran de RÉUSSITE et on éteint (l'utilisateur retire l'ISO puis
|
||||||
|
# rallume sur FWS). Sinon → on affiche tous les logs de debug (comportement
|
||||||
|
# debug). Les lignes cosmétiques (load_policy, warnings GTK…) n'influent PAS
|
||||||
|
# sur cette détection : on ne regarde que le log du %post.
|
||||||
|
if grep -q 'Initcpio image generation successful' /tmp/fws-post-chroot.log 2>/dev/null \
|
||||||
|
&& grep -q 'Installation finished. No error reported.' /tmp/fws-post-chroot.log 2>/dev/null; then
|
||||||
|
if command -v zenity >/dev/null 2>&1; then
|
||||||
|
zenity --info --width=480 --title="FWS — installation réussie ✅" \
|
||||||
|
--text="<b>FWS est installé sur le disque.</b>\n\n1. Clique OK pour <b>éteindre</b> la machine.\n2. <b>Retire l'ISO</b> (lecteur CD/DVD).\n3. Rallume → FWS démarre." \
|
||||||
|
2>/dev/null
|
||||||
|
fi
|
||||||
|
systemctl poweroff
|
||||||
|
else
|
||||||
|
# Échec (ou install non terminée) : on montre les logs pour diagnostiquer.
|
||||||
|
if command -v zenity >/dev/null 2>&1; then
|
||||||
|
zenity --text-info --title="FWS — logs Anaconda (sortie $rc)" \
|
||||||
|
--filename="$DBG" --width=1100 --height=720 2>/dev/null &
|
||||||
|
fi
|
||||||
|
wait "$_OB_PID"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "[FWS] Anaconda absent de l'ISO — à builder (setup-aur.sh) + ajouter à packages.x86_64." >&2
|
||||||
|
exec openbox
|
||||||
|
fi
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
# fix for screen readers
|
||||||
|
if grep -Fqa 'accessibility=' /proc/cmdline &> /dev/null; then
|
||||||
|
setopt SINGLE_LINE_ZLE
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Provisionnement automatique archiso (param noyau script=) : LIVE uniquement.
|
||||||
|
# Sur le système installé /run/archiso n'existe pas, donc ce bloc ne s'exécute
|
||||||
|
# jamais hors du live — c'est la barrière qui empêche l'auto-script sur la cible.
|
||||||
|
if [[ -d /run/archiso ]]; then
|
||||||
|
~/.automated_script.sh
|
||||||
|
fi
|
||||||
@@ -1,5 +1,18 @@
|
|||||||
# Démarrage automatique de Xorg + Calamares sur tty1 (autologin root).
|
# Démarrage automatique dans le live FWS uniquement.
|
||||||
# La session X exécute /root/.xinitrc qui lance Openbox + Calamares.
|
# Sur le système installé, /run/archiso n'existe pas, donc rien ne se lance.
|
||||||
if [[ "$(tty)" == "/dev/tty1" && -z "$DISPLAY" ]]; then
|
|
||||||
|
# Mode RÉPARATION (entrée de boot « Réparer FWS », paramètre fws.recovery=1) :
|
||||||
|
# on démarre X + l'application GTK (fws-recovery-session lance openbox puis
|
||||||
|
# fws-recovery-gui, qui pilote le moteur fws-recovery). Si X échoue à
|
||||||
|
# démarrer, startx rend la main → repli sur l'assistant console fws-recovery.
|
||||||
|
# (Sur le SYSTÈME INSTALLÉ, l'équivalent est fws-recovery-boot.service via
|
||||||
|
# l'entrée GRUB « Réparer FWS » — pas ce fichier.)
|
||||||
|
if [[ -d /run/archiso && "$(tty)" == "/dev/tty1" ]] \
|
||||||
|
&& grep -qw 'fws.recovery=1' /proc/cmdline 2>/dev/null; then
|
||||||
|
startx /usr/local/bin/fws-recovery-session -- vt1
|
||||||
|
exec fws-recovery
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -d /run/archiso && "$(tty)" == "/dev/tty1" && -z "$DISPLAY" ]]; then
|
||||||
exec startx -- vt1
|
exec startx -- vt1
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# ============================================================================
|
||||||
|
# FWS — script de customisation de l'airootfs.
|
||||||
|
# Exécuté par mkarchiso DANS le chroot airootfs, APRÈS le pacstrap
|
||||||
|
# (cf. fws/mkarchiso _make_customize_airootfs), puis supprimé : il n'apparaît
|
||||||
|
# donc PAS dans l'ISO finale. C'est le seul endroit fiable pour lancer des
|
||||||
|
# commandes dans l'image (les hooks pacman ne tournent pas sous pacstrap).
|
||||||
|
# ============================================================================
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Génère les locales déclarées dans /etc/locale.gen. en_US.UTF-8 est REQUIS par
|
||||||
|
# Anaconda (ses modules DBus font setlocale(LC_ALL, "en_US.UTF-8") au démarrage,
|
||||||
|
# sinon « locale.Error: unsupported locale setting » → le module Boss plante).
|
||||||
|
# ~3 Mo générés, vs 222 Mo pour le paquet glibc-locales complet.
|
||||||
|
locale-gen
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
grub-editenv
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
grub-install
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
grub-mkconfig
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
grub-mkpasswd-pbkdf2
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
grub-set-default
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# FWS — stub no-op de load_policy.
|
||||||
|
#
|
||||||
|
# À sa fermeture, le module Runtime d'Anaconda appelle /usr/sbin/load_policy
|
||||||
|
# pour recharger la politique SELinux. Arch N'EST PAS SELinux → le vrai binaire
|
||||||
|
# n'existe pas → « AnacondaError: ... '/usr/sbin/load_policy' » dans un atexit
|
||||||
|
# callback (« Exception ignored »). C'est cosmétique (exit 0 quand même), mais
|
||||||
|
# ça affiche un traceback rouge. Ce stub renvoie 0 → plus aucune erreur.
|
||||||
|
# (/usr/sbin est un lien vers /usr/bin sur Arch usr-merge → ce fichier répond
|
||||||
|
# aussi pour /usr/sbin/load_policy.)
|
||||||
|
exit 0
|
||||||
Executable
+8
@@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# FWS — stub no-op de setstatus.
|
||||||
|
#
|
||||||
|
# Le script Fedora « liveinst » appelle « setstatus » (ligne ~154) pour publier
|
||||||
|
# un statut SELinux/systemd. Cet outil n'existe pas sur Arch →
|
||||||
|
# « /usr/bin/liveinst: line 154: setstatus: command not found » (cosmétique,
|
||||||
|
# liveinst continue). Ce stub renvoie 0 → l'avertissement disparaît.
|
||||||
|
exit 0
|
||||||
+106
@@ -0,0 +1,106 @@
|
|||||||
|
# FWS — Spoke « Desktop Environment » : nouvel onglet de choix du bureau.
|
||||||
|
#
|
||||||
|
# POURQUOI ICI (airootfs, pas dans le paquet anaconda) : Anaconda découvre les
|
||||||
|
# spokes au RUNTIME via collect()/collect_spokes (os.listdir du dossier des
|
||||||
|
# spokes puis import de chaque .py). Déposer ce fichier dans le dossier des
|
||||||
|
# spokes via l'overlay airootfs suffit donc à le faire apparaître — SANS rebuild
|
||||||
|
# du paquet anaconda (juste ./build.sh). Le glade associé est dans
|
||||||
|
# /usr/share/anaconda/ui/spokes/fws_desktop.glade (aussi via l'airootfs).
|
||||||
|
#
|
||||||
|
# ⚠ Le chemin /usr/lib/python3.14/... est couplé à la version de Python d'Arch
|
||||||
|
# (3.14 au moment du build d'anaconda). À mettre à jour si Python change de
|
||||||
|
# version majeure (en même temps que le rebuild d'anaconda de toute façon).
|
||||||
|
#
|
||||||
|
# FONCTION : afficher 5 choix (CLI/GNOME/KDE/Hyprland/XFCE) et écrire la clé
|
||||||
|
# choisie dans /tmp/fws-desktop. Le %post du kickstart lit ce fichier, fait
|
||||||
|
# « pacman -S » du bureau + d'un navigateur (Firefox), et active le display
|
||||||
|
# manager. « cli » (défaut) = aucun bureau, rien à installer.
|
||||||
|
|
||||||
|
from pyanaconda.core.i18n import CN_, _
|
||||||
|
from pyanaconda.ui.categories.software import SoftwareCategory
|
||||||
|
from pyanaconda.ui.gui.spokes import NormalSpoke
|
||||||
|
|
||||||
|
__all__ = ["FWSDesktopSpoke"]
|
||||||
|
|
||||||
|
# clé interne (écrite dans /tmp/fws-desktop) → libellé affiché dans le statut.
|
||||||
|
_CHOICES = [
|
||||||
|
("cli", _("Command line only (no desktop)")),
|
||||||
|
("gnome", "GNOME"),
|
||||||
|
("kde", "KDE Plasma"),
|
||||||
|
("hyprland", "Hyprland — Wayland (non compatible VR)"),
|
||||||
|
("i3", "i3 — X11 (compatible VR : SteamVR)"),
|
||||||
|
("xfce", "XFCE"),
|
||||||
|
]
|
||||||
|
_DESKTOP_FILE = "/tmp/fws-desktop"
|
||||||
|
|
||||||
|
|
||||||
|
class FWSDesktopSpoke(NormalSpoke):
|
||||||
|
"""Choix de l'environnement de bureau FWS (écrit /tmp/fws-desktop)."""
|
||||||
|
|
||||||
|
builderObjects = ["fwsDesktopWindow"]
|
||||||
|
mainWidgetName = "fwsDesktopWindow"
|
||||||
|
uiFile = "spokes/fws_desktop.glade"
|
||||||
|
category = SoftwareCategory
|
||||||
|
icon = "preferences-desktop-display-symbolic"
|
||||||
|
title = CN_("GUI|Spoke", "_Desktop Environment")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_screen_id():
|
||||||
|
"""Identifiant unique de cet écran."""
|
||||||
|
return "fws-desktop-selection"
|
||||||
|
|
||||||
|
def __init__(self, *args):
|
||||||
|
NormalSpoke.__init__(self, *args)
|
||||||
|
self._choice = "cli"
|
||||||
|
self._radios = {}
|
||||||
|
|
||||||
|
def initialize(self):
|
||||||
|
NormalSpoke.initialize(self)
|
||||||
|
for key, _label in _CHOICES:
|
||||||
|
self._radios[key] = self.builder.get_object("radio_" + key)
|
||||||
|
# Reprend un éventuel choix déjà écrit (revisite du spoke).
|
||||||
|
try:
|
||||||
|
with open(_DESKTOP_FILE) as fh:
|
||||||
|
val = fh.read().strip()
|
||||||
|
if val in self._radios:
|
||||||
|
self._choice = val
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def refresh(self):
|
||||||
|
# Coche le bouton correspondant au choix courant.
|
||||||
|
rb = self._radios.get(self._choice) or self._radios.get("cli")
|
||||||
|
if rb is not None:
|
||||||
|
rb.set_active(True)
|
||||||
|
|
||||||
|
def apply(self):
|
||||||
|
# Relit le bouton actif et persiste le choix pour le %post du kickstart.
|
||||||
|
for key, rb in self._radios.items():
|
||||||
|
if rb is not None and rb.get_active():
|
||||||
|
self._choice = key
|
||||||
|
break
|
||||||
|
try:
|
||||||
|
with open(_DESKTOP_FILE, "w") as fh:
|
||||||
|
fh.write(self._choice)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@property
|
||||||
|
def status(self):
|
||||||
|
for key, label in _CHOICES:
|
||||||
|
if key == self._choice:
|
||||||
|
return label
|
||||||
|
return _("Command line only (no desktop)")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def completed(self):
|
||||||
|
# « cli » est un défaut valide → le spoke n'est jamais bloquant.
|
||||||
|
return True
|
||||||
|
|
||||||
|
@property
|
||||||
|
def mandatory(self):
|
||||||
|
return False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def ready(self):
|
||||||
|
return True
|
||||||
+348
@@ -0,0 +1,348 @@
|
|||||||
|
# FWS — Page « Récapitulatif » : écran À PART ENTIÈRE avant l'installation.
|
||||||
|
#
|
||||||
|
# POURQUOI ICI (airootfs, pas dans le paquet anaconda) : même mécanisme que la
|
||||||
|
# spoke « Desktop Environment » (fws_desktop.py) — Anaconda découvre les spokes
|
||||||
|
# au RUNTIME (collect) dans ce dossier → l'overlay airootfs suffit, AUCUN
|
||||||
|
# rebuild du paquet anaconda. Le glade associé est dans
|
||||||
|
# /usr/share/anaconda/ui/spokes/fws_recap.glade (aussi via l'airootfs).
|
||||||
|
#
|
||||||
|
# PLACEMENT DANS LE FLUX : standalone spoke « postForHub = SummaryHub » avec
|
||||||
|
# priority = -10. L'ordre des écrans est pre(SummaryHub) → SummaryHub →
|
||||||
|
# post(SummaryHub) trié par priority croissante (UserInterface.
|
||||||
|
# _orderActionClasses). ProgressSpoke — l'écran qui DÉMARRE l'installation
|
||||||
|
# dans son refresh() — est aussi post(SummaryHub), priority 0 par défaut →
|
||||||
|
# cette page s'intercale ENTRE les deux : l'utilisateur clique « Commencer
|
||||||
|
# l'installation » sur le hub, voit CE récapitulatif (le disque n'a encore
|
||||||
|
# subi AUCUNE écriture), et l'installation ne démarre qu'à son clic
|
||||||
|
# « Lancer l'installation ». Le bouton « Précédent » ramène au hub pour
|
||||||
|
# modifier les choix (cf. _on_back_clicked : la file d'actions du GUI est
|
||||||
|
# consommée à chaque écran, on y réinsère le hub).
|
||||||
|
#
|
||||||
|
# CONTENU : configuration choisie par l'utilisateur (via les modules D-Bus
|
||||||
|
# d'Anaconda : langue, clavier, fuseau, comptes, partitionnement + les
|
||||||
|
# fichiers /tmp des spokes FWS : bureau, hostname) ET matériel détecté
|
||||||
|
# (virtualisation, GPU, disques, réseau) — mêmes sources que ce que le
|
||||||
|
# %post du kickstart et fws-setup-hardware appliqueront.
|
||||||
|
#
|
||||||
|
# ⚠ « completed » doit rester False : _instantiateAction SAUTE les standalone
|
||||||
|
# spokes complétées (mécanisme prévu pour les installs kickstart).
|
||||||
|
# ⚠ Chemin couplé à la version Python d'Arch (3.14) — comme fws_desktop.py —
|
||||||
|
# et le bouton « Précédent » s'appuie sur les internes du GUI d'anaconda
|
||||||
|
# 45.8 (_actions/_currentAction) : à re-vérifier à chaque bump d'anaconda.
|
||||||
|
|
||||||
|
import inspect
|
||||||
|
|
||||||
|
import gi
|
||||||
|
|
||||||
|
gi.require_version("Gtk", "3.0")
|
||||||
|
from gi.repository import Gtk
|
||||||
|
|
||||||
|
from pyanaconda.anaconda_loggers import get_module_logger
|
||||||
|
from pyanaconda.core import util
|
||||||
|
from pyanaconda.modules.common.constants.objects import DISK_SELECTION
|
||||||
|
from pyanaconda.modules.common.constants.services import (
|
||||||
|
LOCALIZATION,
|
||||||
|
STORAGE,
|
||||||
|
TIMEZONE,
|
||||||
|
USERS,
|
||||||
|
)
|
||||||
|
from pyanaconda.modules.common.structures.user import UserData
|
||||||
|
from pyanaconda.ui.gui import GraphicalUserInterface
|
||||||
|
from pyanaconda.ui.gui.hubs.summary import SummaryHub
|
||||||
|
from pyanaconda.ui.gui.spokes import StandaloneSpoke
|
||||||
|
|
||||||
|
log = get_module_logger(__name__)
|
||||||
|
|
||||||
|
__all__ = ["FWSRecapSpoke"]
|
||||||
|
|
||||||
|
# Doit rester aligné sur le %post du kickstart (étape « Bureau choisi ») et
|
||||||
|
# sur les libellés de la spoke fws_desktop.
|
||||||
|
_DESKTOP_LABELS = {
|
||||||
|
"cli": "ligne de commande uniquement (aucun bureau)",
|
||||||
|
"gnome": "GNOME (+ Firefox, GDM)",
|
||||||
|
"kde": "KDE Plasma (+ Firefox, SDDM)",
|
||||||
|
"hyprland": "Hyprland — Wayland, non compatible VR (+ Firefox, SDDM)",
|
||||||
|
"i3": "i3 — X11, compatible VR/SteamVR (+ Firefox, SDDM)",
|
||||||
|
"xfce": "XFCE (+ Firefox, SDDM)",
|
||||||
|
}
|
||||||
|
|
||||||
|
_PARTITIONING_LABELS = {
|
||||||
|
"AUTOMATIC": "automatique (recommandé)",
|
||||||
|
"INTERACTIVE": "personnalisé (assistant)",
|
||||||
|
"CUSTOM": "personnalisé",
|
||||||
|
"BLIVET": "avancé (blivet-gui)",
|
||||||
|
"MANUAL": "points de montage manuels",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _safe(getter, default):
|
||||||
|
"""Valeur d'un getter D-Bus/système, ou défaut : le récap ne doit JAMAIS
|
||||||
|
faire tomber l'installateur, quel que soit le module indisponible (d'où
|
||||||
|
le except large : dasbus lève des types variés selon la panne)."""
|
||||||
|
try:
|
||||||
|
return getter()
|
||||||
|
except Exception: # pylint: disable=broad-except
|
||||||
|
return default
|
||||||
|
|
||||||
|
|
||||||
|
def _capture(*argv):
|
||||||
|
"""stdout d'une commande, chaîne vide si absente ou en échec."""
|
||||||
|
try:
|
||||||
|
return util.execWithCapture(argv[0], list(argv[1:])) or ""
|
||||||
|
except (OSError, RuntimeError):
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
|
def _read_flag(path):
|
||||||
|
try:
|
||||||
|
with open(path) as fh:
|
||||||
|
return fh.read().strip()
|
||||||
|
except OSError:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
|
def _config_lines():
|
||||||
|
"""Section « configuration choisie » : interroge les modules D-Bus
|
||||||
|
d'Anaconda (remplis par les spokes) + les fichiers /tmp des spokes FWS."""
|
||||||
|
lines = []
|
||||||
|
|
||||||
|
lang = _safe(lambda: LOCALIZATION.get_proxy().Language, "")
|
||||||
|
if lang:
|
||||||
|
lines.append(f" • Langue : {lang}")
|
||||||
|
|
||||||
|
layouts = _safe(lambda: list(LOCALIZATION.get_proxy().XLayouts), [])
|
||||||
|
if layouts:
|
||||||
|
lines.append(f" • Clavier (X11) : {', '.join(layouts)}")
|
||||||
|
|
||||||
|
tz = _safe(lambda: TIMEZONE.get_proxy().Timezone, "")
|
||||||
|
if tz:
|
||||||
|
ntp = _safe(lambda: TIMEZONE.get_proxy().NTPEnabled, None)
|
||||||
|
suffix = {True: " — synchronisation NTP activée",
|
||||||
|
False: " — synchronisation NTP désactivée"}.get(ntp, "")
|
||||||
|
lines.append(f" • Fuseau horaire : {tz}{suffix}")
|
||||||
|
|
||||||
|
users = _safe(
|
||||||
|
lambda: UserData.from_structure_list(USERS.get_proxy().Users), [])
|
||||||
|
if users:
|
||||||
|
names = ", ".join(u.name for u in users if u.name)
|
||||||
|
lines.append(f" • Utilisateur(s) : {names} (sudo via wheel)")
|
||||||
|
else:
|
||||||
|
lines.append(" • Utilisateur(s) : AUCUN — pensez-y avant de lancer !")
|
||||||
|
|
||||||
|
root_locked = _safe(lambda: USERS.get_proxy().IsRootAccountLocked, None)
|
||||||
|
root_pw = _safe(lambda: USERS.get_proxy().IsRootPasswordSet, None)
|
||||||
|
if root_locked:
|
||||||
|
root_txt = "verrouillé (recommandé)"
|
||||||
|
elif root_pw:
|
||||||
|
root_txt = "actif, mot de passe défini"
|
||||||
|
elif root_pw is not None:
|
||||||
|
# Même règle que l'étape « Sécurité » du %post : un root resté sans
|
||||||
|
# mot de passe sera verrouillé en fin d'installation.
|
||||||
|
root_txt = "sans mot de passe → sera VERROUILLÉ en fin d'install"
|
||||||
|
else:
|
||||||
|
root_txt = ""
|
||||||
|
if root_txt:
|
||||||
|
lines.append(f" • Compte root : {root_txt}")
|
||||||
|
|
||||||
|
# Hostname : écrit par le spoke Utilisateur (patch user.py du paquet
|
||||||
|
# anaconda). Même nettoyage / même défaut que le %post --nochroot.
|
||||||
|
hn = "".join(c for c in _read_flag("/tmp/fws-hostname")
|
||||||
|
if c.isalnum() or c in "._-") or "fws"
|
||||||
|
lines.append(f" • Nom de machine : {hn}")
|
||||||
|
|
||||||
|
# Bureau : écrit par fws_desktop.apply() (sortie de la spoke). Absent =
|
||||||
|
# spoke jamais visitée = « cli », exactement le défaut du %post.
|
||||||
|
desk = _read_flag("/tmp/fws-desktop") or "cli"
|
||||||
|
lines.append(f" • Bureau : {_DESKTOP_LABELS.get(desk, desk)}")
|
||||||
|
|
||||||
|
method = _safe(
|
||||||
|
lambda: STORAGE.get_proxy(
|
||||||
|
STORAGE.get_proxy().AppliedPartitioning).PartitioningMethod, "")
|
||||||
|
if method:
|
||||||
|
lines.append(" • Partitionnement : "
|
||||||
|
f"{_PARTITIONING_LABELS.get(method, method)}")
|
||||||
|
|
||||||
|
return lines, desk, method
|
||||||
|
|
||||||
|
|
||||||
|
def _build_summary():
|
||||||
|
config_lines, desk, method = _config_lines()
|
||||||
|
config_text = "\n".join(config_lines) \
|
||||||
|
or " (configuration non disponible)"
|
||||||
|
|
||||||
|
# Disques ciblés par l'installation (spoke « Destination »).
|
||||||
|
selected = set(_safe(
|
||||||
|
lambda: list(STORAGE.get_proxy(DISK_SELECTION).SelectedDisks), []))
|
||||||
|
disks = []
|
||||||
|
for line in _capture("lsblk", "-dno", "NAME,SIZE,MODEL,TYPE").splitlines():
|
||||||
|
fields = line.split()
|
||||||
|
if fields and fields[-1] == "disk":
|
||||||
|
mark = " ← CIBLE de l'installation" if fields[0] in selected else ""
|
||||||
|
disks.append(" • " + " ".join(fields[:-1]) + mark)
|
||||||
|
disk_text = "\n".join(disks) or " (aucun disque détecté)"
|
||||||
|
|
||||||
|
if method == "AUTOMATIC":
|
||||||
|
disk_warn = (
|
||||||
|
" ⚠ Rien n'a encore été écrit. Le partitionnement automatique\n"
|
||||||
|
" EFFACERA ENTIÈREMENT le(s) disque(s) cible(s) au lancement.")
|
||||||
|
else:
|
||||||
|
disk_warn = (
|
||||||
|
" ⚠ Rien n'a encore été écrit. Au lancement, ce sont vos choix\n"
|
||||||
|
" de partitionnement faits dans l'installateur qui s'appliqueront.")
|
||||||
|
|
||||||
|
virt = (_capture("systemd-detect-virt").strip().splitlines() or ["none"])[0]
|
||||||
|
if virt in ("", "none"):
|
||||||
|
virt = "aucune (machine physique)"
|
||||||
|
|
||||||
|
gpus = []
|
||||||
|
for line in _capture("lspci").splitlines():
|
||||||
|
low = line.lower()
|
||||||
|
if ("vga" in low or "3d" in low or "display" in low) and ":" in line:
|
||||||
|
gpus.append(" • " + line.split(":", 2)[-1].strip())
|
||||||
|
gpu_text = "\n".join(gpus) or " (aucune carte graphique détectée)"
|
||||||
|
|
||||||
|
try:
|
||||||
|
net_ok = util.execWithRedirect("ip", ["route", "get", "1.1.1.1"]) == 0
|
||||||
|
except (OSError, RuntimeError):
|
||||||
|
net_ok = False
|
||||||
|
if net_ok:
|
||||||
|
net = "disponible ✔"
|
||||||
|
else:
|
||||||
|
net = ("INDISPONIBLE ✖ — bureau, drivers et stack FWS ne\n"
|
||||||
|
" s'installeront PAS (rattrapable au 1er boot)")
|
||||||
|
|
||||||
|
extras = ("Steam, Wine, VR (Monado/OpenXR), winboat-bin"
|
||||||
|
if desk != "cli" else "rien de plus (choix CLI)")
|
||||||
|
|
||||||
|
return f"""\
|
||||||
|
══════════════════════════════════════════════════════════
|
||||||
|
FWS — RÉCAPITULATIF AVANT INSTALLATION
|
||||||
|
══════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
CONFIGURATION CHOISIE
|
||||||
|
{config_text}
|
||||||
|
|
||||||
|
DISQUES
|
||||||
|
{disk_warn}
|
||||||
|
{disk_text}
|
||||||
|
|
||||||
|
MATÉRIEL DÉTECTÉ
|
||||||
|
• Virtualisation : {virt}
|
||||||
|
• Réseau : {net}
|
||||||
|
Cartes graphiques (drivers installés automatiquement en fin d'install) :
|
||||||
|
{gpu_text}
|
||||||
|
|
||||||
|
DÉROULEMENT DE L'INSTALLATION
|
||||||
|
1. Partitionnement, puis copie du système live FWS (payload LiveOS)
|
||||||
|
2. Noyau + initramfs régénérés (mkinitcpio), GRUB installé
|
||||||
|
3. Bureau choisi + navigateur installés (réseau requis)
|
||||||
|
4. Matériel : drivers GPU, outils VM, son, Bluetooth, Podman
|
||||||
|
+ si bureau choisi : {extras}
|
||||||
|
|
||||||
|
« Précédent » pour revenir modifier vos choix —
|
||||||
|
« Lancer l'installation » pour démarrer réellement l'installation.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class FWSRecapSpoke(StandaloneSpoke):
|
||||||
|
"""Récapitulatif des choix, affiché entre le hub et l'installation."""
|
||||||
|
|
||||||
|
builderObjects = ["fwsRecapWindow"]
|
||||||
|
mainWidgetName = "fwsRecapWindow"
|
||||||
|
uiFile = "spokes/fws_recap.glade"
|
||||||
|
|
||||||
|
postForHub = SummaryHub
|
||||||
|
priority = -10
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_screen_id():
|
||||||
|
"""Identifiant unique de cet écran."""
|
||||||
|
return "fws-recap"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def completed(self):
|
||||||
|
# False, sinon _instantiateAction saute l'écran (cf. en-tête).
|
||||||
|
return False
|
||||||
|
|
||||||
|
def apply(self):
|
||||||
|
# Rien à persister : cette page ne fait que montrer l'état.
|
||||||
|
pass
|
||||||
|
|
||||||
|
def initialize(self):
|
||||||
|
StandaloneSpoke.initialize(self)
|
||||||
|
# Le bouton « continuer » de CETTE page est le vrai déclencheur :
|
||||||
|
# l'écran suivant (ProgressSpoke) démarre la file d'installation.
|
||||||
|
self.window.get_continue_button().set_label("_Lancer l'installation")
|
||||||
|
|
||||||
|
# Capture pour « Précédent » : initialize() est appelé DEPUIS
|
||||||
|
# GraphicalUserInterface._on_continue_clicked (clic « Commencer
|
||||||
|
# l'installation » du hub), AVANT la bascule de _currentAction → à
|
||||||
|
# cet instant ui._currentAction est ENCORE l'instance du hub Résumé,
|
||||||
|
# et le « self » de l'appelant est l'UI. Aucune API publique ne les
|
||||||
|
# expose ; on remonte la pile d'appels (déterministe — pas de scan
|
||||||
|
# mémoire, pas de variable globale).
|
||||||
|
self._gui = None
|
||||||
|
self._hub = None
|
||||||
|
frame = inspect.currentframe()
|
||||||
|
try:
|
||||||
|
frame = frame.f_back
|
||||||
|
while frame is not None:
|
||||||
|
candidate = frame.f_locals.get("self")
|
||||||
|
if isinstance(candidate, GraphicalUserInterface):
|
||||||
|
self._gui = candidate
|
||||||
|
current = getattr(candidate, "_currentAction", None)
|
||||||
|
if isinstance(current, SummaryHub):
|
||||||
|
self._hub = current
|
||||||
|
break
|
||||||
|
frame = frame.f_back
|
||||||
|
finally:
|
||||||
|
del frame
|
||||||
|
|
||||||
|
# Bouton « Précédent », placé avec les boutons de navigation
|
||||||
|
# (à côté de « Quitter » — leur parent est la GtkButtonBox du bas).
|
||||||
|
quit_button = self.window.get_quit_button()
|
||||||
|
button_box = quit_button.get_parent()
|
||||||
|
self._back_button = Gtk.Button.new_with_mnemonic("_Précédent")
|
||||||
|
self._back_button.connect("clicked", self._on_back_clicked)
|
||||||
|
button_box.add(self._back_button)
|
||||||
|
button_box.reorder_child(self._back_button, 0)
|
||||||
|
if self._gui is None or self._hub is None:
|
||||||
|
# Références introuvables (flux inattendu) : bouton grisé plutôt
|
||||||
|
# qu'une navigation cassée — l'install reste possible.
|
||||||
|
log.warning("FWS recap: hub/UI introuvables, « Précédent » désactivé.")
|
||||||
|
self._back_button.set_sensitive(False)
|
||||||
|
self._back_button.show()
|
||||||
|
|
||||||
|
def _on_back_clicked(self, _button):
|
||||||
|
ui = self._gui
|
||||||
|
hub = self._hub
|
||||||
|
if ui is None or hub is None:
|
||||||
|
return
|
||||||
|
log.info("FWS recap: retour au hub Résumé pour modification.")
|
||||||
|
# La file d'actions du GUI est CONSOMMÉE (pop(0)) à chaque écran :
|
||||||
|
# ici _actions = [FWSRecapSpoke, ProgressSpoke] et le hub en est déjà
|
||||||
|
# sorti. On le réinsère en tête pour que le prochain « Commencer
|
||||||
|
# l'installation » ré-enchaîne hub → NOUVELLE page récap (résumé
|
||||||
|
# recalculé avec les choix modifiés) → installation.
|
||||||
|
if not ui._actions or ui._actions[0] is not SummaryHub:
|
||||||
|
ui._actions.insert(0, SummaryHub)
|
||||||
|
# _on_continue_clicked a désactivé le « continuer » du hub en le
|
||||||
|
# quittant : on le réarme, sinon « Commencer l'installation » est mort.
|
||||||
|
hub.window.set_may_continue(True)
|
||||||
|
# Même séquence que la transition officielle (_on_continue_clicked).
|
||||||
|
self.exited.emit(self)
|
||||||
|
hub.refresh()
|
||||||
|
ui.mainWindow.setCurrentAction(hub)
|
||||||
|
hub.entered.emit(hub)
|
||||||
|
ui._currentAction = hub
|
||||||
|
|
||||||
|
def refresh(self):
|
||||||
|
StandaloneSpoke.refresh(self)
|
||||||
|
text = _build_summary()
|
||||||
|
self.builder.get_object("recapView").get_buffer().set_text(text)
|
||||||
|
# Copie pour le harnais de debug du .xinitrc (fws-debug.txt).
|
||||||
|
try:
|
||||||
|
with open("/tmp/fws-hw-summary.txt", "w") as fh:
|
||||||
|
fh.write(text)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
@@ -0,0 +1,136 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!-- Generated with glade 3.18.3 -->
|
||||||
|
<interface>
|
||||||
|
<!-- FWS : copie de summary.glade d'anaconda 45.8 SANS le libellé
|
||||||
|
« We won't touch your disks… » du bas du hub. Livré ICI (chemin neutre)
|
||||||
|
car mkarchiso pose l'airootfs AVANT pacstrap : au chemin du paquet,
|
||||||
|
pacman refuserait d'installer anaconda (« exists in filesystem »).
|
||||||
|
C'est le .xinitrc du live qui le copie sur
|
||||||
|
/usr/share/anaconda/ui/hubs/summary.glade au boot. -->
|
||||||
|
<requires lib="gtk+" version="3.0"/>
|
||||||
|
<requires lib="AnacondaWidgets" version="3.0"/>
|
||||||
|
<object class="AnacondaHubWindow" id="summaryWindow">
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="window_name" translatable="yes">INSTALLATION SUMMARY</property>
|
||||||
|
<property name="quit_button">quitButton</property>
|
||||||
|
<property name="continue_button">continueButton</property>
|
||||||
|
<child internal-child="main_box">
|
||||||
|
<object class="GtkBox" id="AnacondaHubWindow-main_box1">
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<child internal-child="nav_box">
|
||||||
|
<object class="GtkEventBox" id="AnacondaHubWindow-nav_box1">
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<child internal-child="nav_area">
|
||||||
|
<object class="GtkGrid" id="AnacondaHubWindow-nav_area1">
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<child>
|
||||||
|
<placeholder/>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<placeholder/>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">False</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child internal-child="alignment">
|
||||||
|
<object class="GtkAlignment" id="AnacondaHubWindow-alignment1">
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="yalign">0</property>
|
||||||
|
<property name="left_padding">12</property>
|
||||||
|
<property name="right_padding">6</property>
|
||||||
|
<child internal-child="action_area">
|
||||||
|
<object class="GtkBox" id="summaryWindow-actionArea">
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<property name="spacing">6</property>
|
||||||
|
<child internal-child="scrolled_window">
|
||||||
|
<object class="GtkScrolledWindow" id="summaryWindow-scroll">
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="is_focus">True</property>
|
||||||
|
<property name="hscrollbar_policy">never</property>
|
||||||
|
<child>
|
||||||
|
<placeholder/>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">True</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">True</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButtonBox" id="buttonbox1">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="margin_left">6</property>
|
||||||
|
<property name="margin_right">6</property>
|
||||||
|
<property name="spacing">12</property>
|
||||||
|
<property name="layout_style">end</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="quitButton">
|
||||||
|
<property name="label" translatable="yes" context="GUI|Summary">_Quit</property>
|
||||||
|
<property name="use_action_appearance">False</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">True</property>
|
||||||
|
<property name="hexpand">True</property>
|
||||||
|
<property name="use_underline">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="continueButton">
|
||||||
|
<property name="label" translatable="yes" context="GUI|Summary">_Begin Installation</property>
|
||||||
|
<property name="use_action_appearance">False</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="sensitive">False</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">True</property>
|
||||||
|
<property name="use_underline">True</property>
|
||||||
|
<style>
|
||||||
|
<class name="suggested-action"/>
|
||||||
|
</style>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="pack_type">end</property>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">2</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child internal-child="accessible">
|
||||||
|
<object class="AtkObject" id="summaryWindow-atkobject">
|
||||||
|
<property name="AtkObject::accessible-name" translatable="yes">INSTALLATION SUMMARY</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</interface>
|
||||||
@@ -0,0 +1,168 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!-- FWS — onglet « Desktop Environment » (choix du bureau à installer). -->
|
||||||
|
<interface>
|
||||||
|
<requires lib="gtk+" version="3.6"/>
|
||||||
|
<requires lib="AnacondaWidgets" version="1.0"/>
|
||||||
|
<object class="AnacondaSpokeWindow" id="fwsDesktopWindow">
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="hexpand">True</property>
|
||||||
|
<property name="vexpand">True</property>
|
||||||
|
<property name="window-name" translatable="yes">DESKTOP ENVIRONMENT</property>
|
||||||
|
<signal name="button-clicked" handler="on_back_clicked" swapped="no"/>
|
||||||
|
<child internal-child="main_box">
|
||||||
|
<object class="GtkBox" id="AnacondaSpokeWindow-main_box1">
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<property name="spacing">6</property>
|
||||||
|
<child internal-child="nav_box">
|
||||||
|
<object class="GtkEventBox" id="AnacondaSpokeWindow-nav_box1">
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<child internal-child="nav_area">
|
||||||
|
<object class="GtkGrid" id="AnacondaSpokeWindow-nav_area1">
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="margin-left">6</property>
|
||||||
|
<property name="margin-right">6</property>
|
||||||
|
<property name="margin-top">6</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">False</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child internal-child="alignment">
|
||||||
|
<object class="GtkAlignment" id="AnacondaSpokeWindow-alignment1">
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="margin-top">12</property>
|
||||||
|
<property name="yalign">0</property>
|
||||||
|
<property name="xscale">0</property>
|
||||||
|
<property name="yscale">0</property>
|
||||||
|
<property name="bottom-padding">48</property>
|
||||||
|
<property name="left-padding">24</property>
|
||||||
|
<property name="right-padding">24</property>
|
||||||
|
<child internal-child="action_area">
|
||||||
|
<object class="GtkBox" id="AnacondaSpokeWindow-action_area1">
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<property name="spacing">8</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="fws_desktop_desc">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="xalign">0</property>
|
||||||
|
<property name="margin-bottom">12</property>
|
||||||
|
<property name="wrap">True</property>
|
||||||
|
<property name="max-width-chars">60</property>
|
||||||
|
<property name="label" translatable="yes">Choose the desktop environment to install. A web browser (Firefox) is installed automatically with any desktop.</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkRadioButton" id="radio_cli">
|
||||||
|
<property name="label" translatable="yes">Command line only (no desktop)</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">True</property>
|
||||||
|
<property name="receives-default">False</property>
|
||||||
|
<property name="active">True</property>
|
||||||
|
<property name="draw-indicator">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkRadioButton" id="radio_gnome">
|
||||||
|
<property name="label" translatable="yes">GNOME</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">True</property>
|
||||||
|
<property name="receives-default">False</property>
|
||||||
|
<property name="draw-indicator">True</property>
|
||||||
|
<property name="group">radio_cli</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">2</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkRadioButton" id="radio_kde">
|
||||||
|
<property name="label" translatable="yes">KDE Plasma</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">True</property>
|
||||||
|
<property name="receives-default">False</property>
|
||||||
|
<property name="draw-indicator">True</property>
|
||||||
|
<property name="group">radio_cli</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">3</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkRadioButton" id="radio_hyprland">
|
||||||
|
<property name="label" translatable="yes">Hyprland — Wayland (NOT VR compatible)</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">True</property>
|
||||||
|
<property name="receives-default">False</property>
|
||||||
|
<property name="draw-indicator">True</property>
|
||||||
|
<property name="group">radio_cli</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">4</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkRadioButton" id="radio_i3">
|
||||||
|
<property name="label" translatable="yes">i3 — X11 (VR compatible: SteamVR, HTC Vive, Valve Index…)</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">True</property>
|
||||||
|
<property name="receives-default">False</property>
|
||||||
|
<property name="draw-indicator">True</property>
|
||||||
|
<property name="group">radio_cli</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">5</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkRadioButton" id="radio_xfce">
|
||||||
|
<property name="label" translatable="yes">XFCE</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">True</property>
|
||||||
|
<property name="receives-default">False</property>
|
||||||
|
<property name="draw-indicator">True</property>
|
||||||
|
<property name="group">radio_cli</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">6</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child internal-child="accessible">
|
||||||
|
<object class="AtkObject" id="fwsDesktopWindow-atkobject">
|
||||||
|
<property name="AtkObject::accessible-name" translatable="yes">DESKTOP ENVIRONMENT</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</interface>
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!-- FWS — page « Récapitulatif avant installation » (cf. fws_recap.py).
|
||||||
|
Squelette calqué sur installation_progress.glade : AnacondaStandaloneWindow
|
||||||
|
avec ses enfants internes (nav_box/nav_area, alignment/action_area). -->
|
||||||
|
<interface>
|
||||||
|
<requires lib="gtk+" version="3.0"/>
|
||||||
|
<requires lib="AnacondaWidgets" version="3.0"/>
|
||||||
|
<object class="AnacondaStandaloneWindow" id="fwsRecapWindow">
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="window_name" translatable="yes">RÉCAPITULATIF AVANT INSTALLATION</property>
|
||||||
|
<child internal-child="main_box">
|
||||||
|
<object class="GtkBox" id="AnacondaStandaloneWindow-main_box1">
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<child internal-child="nav_box">
|
||||||
|
<object class="GtkEventBox" id="AnacondaStandaloneWindow-nav_box1">
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<child internal-child="nav_area">
|
||||||
|
<object class="GtkGrid" id="AnacondaStandaloneWindow-nav_area1">
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<child>
|
||||||
|
<placeholder/>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<placeholder/>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">False</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child internal-child="alignment">
|
||||||
|
<object class="GtkAlignment" id="AnacondaStandaloneWindow-alignment1">
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="yalign">0</property>
|
||||||
|
<property name="left_padding">12</property>
|
||||||
|
<property name="right_padding">6</property>
|
||||||
|
<child internal-child="action_area">
|
||||||
|
<object class="GtkBox" id="fwsRecapWindow-actionArea">
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<property name="spacing">6</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkScrolledWindow" id="recapScroll">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="shadow_type">in</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkTextView" id="recapView">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="editable">False</property>
|
||||||
|
<property name="cursor_visible">False</property>
|
||||||
|
<property name="monospace">True</property>
|
||||||
|
<property name="left_margin">12</property>
|
||||||
|
<property name="right_margin">12</property>
|
||||||
|
<property name="top_margin">12</property>
|
||||||
|
<property name="bottom_margin">12</property>
|
||||||
|
<property name="wrap_mode">word-char</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">True</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">True</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</interface>
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
title Arch Linux (%ARCH%, UEFI)
|
title FWS install medium (%ARCH%, UEFI)
|
||||||
linux /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux
|
sort-key 01
|
||||||
initrd /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux.img
|
linux /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux
|
||||||
options archisobasedir=%INSTALL_DIR% archisosearchuuid=%ARCHISO_UUID%
|
initrd /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux.img
|
||||||
|
options archisobasedir=%INSTALL_DIR% archisosearchuuid=%ARCHISO_UUID% udev.event_timeout=45
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# ============================================================
|
# ============================================================
|
||||||
# FWS — paquets de l'ISO live
|
# FWS — paquets de l'ISO live
|
||||||
# Objectif : système live bootable + installeur Calamares
|
# Objectif : système live bootable + installateur Anaconda
|
||||||
# fonctionnel + jeu minimal d'outils de rescue.
|
# (migration depuis Calamares) + jeu minimal d'outils de rescue.
|
||||||
# ============================================================
|
# ============================================================
|
||||||
|
|
||||||
# --- Base système ---
|
# --- Base système ---
|
||||||
@@ -26,6 +26,7 @@ memtest86+
|
|||||||
memtest86+-efi
|
memtest86+-efi
|
||||||
|
|
||||||
# --- Filesystems ---
|
# --- Filesystems ---
|
||||||
|
squashfs-tools
|
||||||
btrfs-progs
|
btrfs-progs
|
||||||
e2fsprogs
|
e2fsprogs
|
||||||
exfatprogs
|
exfatprogs
|
||||||
@@ -60,6 +61,8 @@ wget
|
|||||||
zsh
|
zsh
|
||||||
grml-zsh-config
|
grml-zsh-config
|
||||||
bash
|
bash
|
||||||
|
zenity
|
||||||
|
zram-generator
|
||||||
nano
|
nano
|
||||||
vim
|
vim
|
||||||
less
|
less
|
||||||
@@ -77,6 +80,7 @@ pacman-contrib
|
|||||||
dmidecode
|
dmidecode
|
||||||
usbutils
|
usbutils
|
||||||
pciutils
|
pciutils
|
||||||
|
firewalld
|
||||||
fastfetch
|
fastfetch
|
||||||
htop
|
htop
|
||||||
|
|
||||||
@@ -84,21 +88,15 @@ htop
|
|||||||
alsa-utils
|
alsa-utils
|
||||||
sof-firmware
|
sof-firmware
|
||||||
|
|
||||||
# --- Xorg + Openbox (pour Calamares) ---
|
# --- Xorg + Openbox (session graphique de l'installateur) ---
|
||||||
xorg-server
|
xorg-server
|
||||||
xorg-xinit
|
xorg-xinit
|
||||||
xorg-xrandr
|
xorg-xrandr
|
||||||
xorg-xsetroot
|
xorg-xsetroot
|
||||||
openbox
|
openbox
|
||||||
ttf-dejavu
|
ttf-dejavu
|
||||||
|
# Terminal X : debug de l'installateur + entrée « Terminals » du menu Openbox.
|
||||||
# --- Calamares (fournis par fws-local) ---
|
xterm
|
||||||
calamares
|
|
||||||
kpmcore
|
|
||||||
qt5-base
|
|
||||||
qt5-svg
|
|
||||||
qt5-webengine
|
|
||||||
qt6-base
|
|
||||||
|
|
||||||
# --- Agents VM (pratique pour tester l'ISO) ---
|
# --- Agents VM (pratique pour tester l'ISO) ---
|
||||||
qemu-guest-agent
|
qemu-guest-agent
|
||||||
@@ -107,3 +105,19 @@ open-vm-tools
|
|||||||
|
|
||||||
# --- FWS (fws-local) ---
|
# --- FWS (fws-local) ---
|
||||||
winboat-bin
|
winboat-bin
|
||||||
|
# Gestionnaire D&D 5e (dés, personnages, grimoire, sessions, combat).
|
||||||
|
fws-dnd
|
||||||
|
|
||||||
|
# --- Installateur Anaconda (fws-local) ---
|
||||||
|
# 'anaconda' tire automatiquement anaconda-widgets + toutes ses dépendances
|
||||||
|
# (python-blivet, pykickstart, libreport, gtk3, NetworkManager…).
|
||||||
|
anaconda
|
||||||
|
# Module 'cgi' (retiré de Python 3.13, PEP 594) requis par python-requests-ftp
|
||||||
|
# que pyanaconda/core/util.py importe en dur. python-legacy-cgi le réintroduit.
|
||||||
|
python-legacy-cgi
|
||||||
|
# Module 'crypt'/'crypt_r' (retiré de Python 3.13, PEP 594) requis par
|
||||||
|
# pyanaconda/core/users.py (hash des mots de passe). Paquet maison (fws-local).
|
||||||
|
python-crypt_r
|
||||||
|
# Namespace GI 'OSTree-1.0' : pyanaconda/rescue.py importe le payload rpm_ostree
|
||||||
|
# (inconditionnellement, même si FWS utilise liveimg) → fourni par 'ostree'.
|
||||||
|
ostree
|
||||||
|
|||||||
@@ -1,8 +1,3 @@
|
|||||||
[fws-local]
|
|
||||||
SigLevel = Optional TrustAll
|
|
||||||
Server = file:///mnt/c/Users/Murasaki/Documents/FWS/fws/local-repo
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# /etc/pacman.conf
|
# /etc/pacman.conf
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -14,6 +14,31 @@ pacman_conf="pacman.conf"
|
|||||||
airootfs_image_type="squashfs"
|
airootfs_image_type="squashfs"
|
||||||
airootfs_image_tool_options=('-comp' 'xz' '-Xbcj' 'x86' '-b' '1M' '-Xdict-size' '1M')
|
airootfs_image_tool_options=('-comp' 'xz' '-Xbcj' 'x86' '-b' '1M' '-Xdict-size' '1M')
|
||||||
bootstrap_tarball_compression=(xz -9e)
|
bootstrap_tarball_compression=(xz -9e)
|
||||||
|
# NB : ce profiledef.sh ÉCRASE celui de configs/releng/ lors de la fusion du
|
||||||
|
# build (baseline prioritaire). Il doit donc être un SUR-ENSEMBLE des
|
||||||
|
# permissions de releng, sinon les helpers live perdent leur bit exécutable
|
||||||
|
# (ils sont versionnés en 0644) et /root/.gnupg perd son 0700 (gpg refuse).
|
||||||
file_permissions=(
|
file_permissions=(
|
||||||
["/etc/shadow"]="0:0:400"
|
["/etc/shadow"]="0:0:400"
|
||||||
|
["/root"]="0:0:750"
|
||||||
|
["/root/.automated_script.sh"]="0:0:755"
|
||||||
|
["/root/.gnupg"]="0:0:700"
|
||||||
|
["/usr/local/bin/choose-mirror"]="0:0:755"
|
||||||
|
["/usr/local/bin/Installation_guide"]="0:0:755"
|
||||||
|
["/usr/local/bin/livecd-sound"]="0:0:755"
|
||||||
|
["/usr/bin/load_policy"]="0:0:755"
|
||||||
|
["/usr/bin/setstatus"]="0:0:755"
|
||||||
|
["/usr/local/bin/fws-setup-hardware"]="0:0:755"
|
||||||
|
["/usr/local/bin/fws-keys"]="0:0:755"
|
||||||
|
["/usr/local/bin/fws-vr-setup"]="0:0:755"
|
||||||
|
["/usr/local/bin/fws-hello"]="0:0:755"
|
||||||
|
["/usr/local/bin/fws-update"]="0:0:755"
|
||||||
|
["/usr/local/bin/fws-updates-check"]="0:0:755"
|
||||||
|
["/usr/local/bin/fws-proton-ge"]="0:0:755"
|
||||||
|
["/usr/local/bin/fws-recovery"]="0:0:755"
|
||||||
|
["/usr/local/bin/fws-recovery-session"]="0:0:755"
|
||||||
|
["/usr/local/bin/fws-recovery-gui"]="0:0:755"
|
||||||
|
["/usr/local/bin/fws-powermenu"]="0:0:755"
|
||||||
|
["/usr/local/bin/fws-about"]="0:0:755"
|
||||||
|
["/etc/grub.d/42_fws-recovery"]="0:0:755"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
LABEL arch
|
|
||||||
MENU LABEL Arch Linux (%ARCH%, BIOS)
|
|
||||||
LINUX /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux
|
|
||||||
INITRD /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux.img
|
|
||||||
APPEND archisobasedir=%INSTALL_DIR% archisosearchuuid=%ARCHISO_UUID%
|
|
||||||
@@ -1,9 +1,11 @@
|
|||||||
SERIAL 0 115200
|
DEFAULT select
|
||||||
UI menu.c32
|
|
||||||
MENU TITLE Arch Linux
|
|
||||||
MENU CLEAR
|
|
||||||
|
|
||||||
DEFAULT arch
|
LABEL select
|
||||||
TIMEOUT 30
|
COM32 whichsys.c32
|
||||||
|
APPEND -pxe- pxe -sys- sys -iso- sys
|
||||||
|
|
||||||
INCLUDE syslinux-linux.cfg
|
LABEL pxe
|
||||||
|
CONFIG archiso_pxe.cfg
|
||||||
|
|
||||||
|
LABEL sys
|
||||||
|
CONFIG archiso_sys.cfg
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
# ============================================================
|
|
||||||
# FWS Linux — branding.desc
|
|
||||||
# ============================================================
|
|
||||||
|
|
||||||
componentName: fws
|
|
||||||
|
|
||||||
strings:
|
|
||||||
productName: "FWS Linux"
|
|
||||||
shortProductName: "FWS"
|
|
||||||
version: "1.0"
|
|
||||||
shortVersion: "1.0"
|
|
||||||
versionedName: "FWS Linux 1.0"
|
|
||||||
shortVersionedName: "FWS 1.0"
|
|
||||||
bootloaderEntryName: "FWS Linux"
|
|
||||||
productUrl: "https://fws-linux.org"
|
|
||||||
supportUrl: "https://fws-linux.org/support"
|
|
||||||
releaseNotesUrl: "https://fws-linux.org/release-notes"
|
|
||||||
donateUrl: "https://fws-linux.org/donate"
|
|
||||||
|
|
||||||
images:
|
|
||||||
productLogo: "logo.png"
|
|
||||||
productIcon: "logo.png"
|
|
||||||
productWelcome: "logo.png"
|
|
||||||
|
|
||||||
slideshow: "slideshow.qml"
|
|
||||||
slideshowAPI: 2
|
|
||||||
|
|
||||||
style:
|
|
||||||
# Couleurs de la sidebar
|
|
||||||
sidebarBackground: "#1a1a2e"
|
|
||||||
sidebarText: "#e0e0e0"
|
|
||||||
sidebarTextHighlight: "#00d4ff"
|
|
||||||
sidebarSelect: "#16213e"
|
|
||||||
|
|
||||||
# Couleurs générales
|
|
||||||
backgroundColor: "#0f3460"
|
|
||||||
highlightedTextColor: "#ffffff"
|
|
||||||
genericTextColor: "#e0e0e0"
|
|
||||||
errorTextColor: "#ff6b6b"
|
|
||||||
warningTextColor: "#ffa500"
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 11 KiB |
@@ -1,138 +0,0 @@
|
|||||||
/* ============================================================
|
|
||||||
FWS Linux — slideshow.qml
|
|
||||||
Affiché pendant l'installation
|
|
||||||
============================================================ */
|
|
||||||
|
|
||||||
import QtQuick 2.0
|
|
||||||
import calamares.slideshow 1.0
|
|
||||||
|
|
||||||
Presentation {
|
|
||||||
id: presentation
|
|
||||||
|
|
||||||
function nextSlide() {
|
|
||||||
if (presentation.currentSlide < slides.count - 1)
|
|
||||||
presentation.currentSlide++
|
|
||||||
else
|
|
||||||
presentation.currentSlide = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
Timer {
|
|
||||||
id: timer
|
|
||||||
interval: 4000
|
|
||||||
repeat: true
|
|
||||||
running: true
|
|
||||||
onTriggered: nextSlide()
|
|
||||||
}
|
|
||||||
|
|
||||||
Slide {
|
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
anchors.fill: parent
|
|
||||||
color: "#1a1a2e"
|
|
||||||
|
|
||||||
Column {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
spacing: 20
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "🚀 Bienvenue sur FWS Linux"
|
|
||||||
color: "#00d4ff"
|
|
||||||
font.pixelSize: 32
|
|
||||||
font.bold: true
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
}
|
|
||||||
Text {
|
|
||||||
text: "Un système rapide, léger et puissant."
|
|
||||||
color: "#e0e0e0"
|
|
||||||
font.pixelSize: 18
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Slide {
|
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
anchors.fill: parent
|
|
||||||
color: "#16213e"
|
|
||||||
|
|
||||||
Column {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
spacing: 20
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "⚡ Basé sur Arch Linux"
|
|
||||||
color: "#00d4ff"
|
|
||||||
font.pixelSize: 32
|
|
||||||
font.bold: true
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
}
|
|
||||||
Text {
|
|
||||||
text: "Accès à l'AUR et aux derniers paquets."
|
|
||||||
color: "#e0e0e0"
|
|
||||||
font.pixelSize: 18
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Slide {
|
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
anchors.fill: parent
|
|
||||||
color: "#0f3460"
|
|
||||||
|
|
||||||
Column {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
spacing: 20
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "🛡️ Sécurité & Stabilité"
|
|
||||||
color: "#00d4ff"
|
|
||||||
font.pixelSize: 32
|
|
||||||
font.bold: true
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
}
|
|
||||||
Text {
|
|
||||||
text: "FWS est conçu pour être robuste et fiable."
|
|
||||||
color: "#e0e0e0"
|
|
||||||
font.pixelSize: 18
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Slide {
|
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
anchors.fill: parent
|
|
||||||
color: "#1a1a2e"
|
|
||||||
|
|
||||||
Column {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
spacing: 20
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: "✅ Installation en cours..."
|
|
||||||
color: "#00d4ff"
|
|
||||||
font.pixelSize: 32
|
|
||||||
font.bold: true
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
}
|
|
||||||
Text {
|
|
||||||
text: "Merci de patienter, FWS s'installe sur votre machine."
|
|
||||||
color: "#e0e0e0"
|
|
||||||
font.pixelSize: 18
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
# ============================================================
|
|
||||||
# FWS Linux — modules/bootloader.conf
|
|
||||||
# ============================================================
|
|
||||||
|
|
||||||
# Bootloader à utiliser
|
|
||||||
# Options: grub, systemd-boot, refind
|
|
||||||
efiBootLoader: "grub"
|
|
||||||
|
|
||||||
# Paramètres GRUB
|
|
||||||
grubInstall: "grub-install"
|
|
||||||
grubMkconfig: "grub-mkconfig"
|
|
||||||
grubCfg: "/boot/grub/grub.cfg"
|
|
||||||
|
|
||||||
# Chemin EFI
|
|
||||||
efiDirectory: "/boot/efi"
|
|
||||||
|
|
||||||
# ID pour l'entrée EFI
|
|
||||||
efiBootEntryName: "FWS Linux"
|
|
||||||
|
|
||||||
# Menu GRUB
|
|
||||||
grubTimeout: 5
|
|
||||||
grubQuiet: false
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
# ============================================================
|
|
||||||
# FWS Linux — modules/finished.conf
|
|
||||||
# ============================================================
|
|
||||||
|
|
||||||
# Redémarrer automatiquement après l'installation
|
|
||||||
restartNowEnabled: true
|
|
||||||
restartNowChecked: false
|
|
||||||
restartNowCommand: "systemctl reboot"
|
|
||||||
|
|
||||||
# Message de fin affiché à l'utilisateur
|
|
||||||
notifyOnFinished: true
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
# ============================================================
|
|
||||||
# FWS Linux — modules/grubcfg.conf
|
|
||||||
# Paramètres passés à grub-mkconfig
|
|
||||||
# ============================================================
|
|
||||||
|
|
||||||
# Nom de l'entrée dans le menu GRUB
|
|
||||||
defaultEntry: "FWS Linux"
|
|
||||||
|
|
||||||
defaults:
|
|
||||||
GRUB_ENABLE_CRYPTODISK: true
|
|
||||||
|
|
||||||
# Paramètres kernel supplémentaires
|
|
||||||
kernel_params: ""
|
|
||||||
|
|
||||||
# Désactiver l'écran splash (mettre false pour debug)
|
|
||||||
splash: true
|
|
||||||
|
|
||||||
# Thème GRUB (laisse vide pour le thème par défaut)
|
|
||||||
theme: ""
|
|
||||||
|
|
||||||
# Timeout du menu GRUB (en secondes)
|
|
||||||
timeout: 5
|
|
||||||
|
|
||||||
# Activer les entrées des autres OS détectés (os-prober)
|
|
||||||
enable_osprober: true
|
|
||||||
|
|
||||||
# Écrire /etc/default/grub
|
|
||||||
writeEtcDefaultGrub: true
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
# ============================================================
|
|
||||||
# FWS Linux — modules/initcpiocfg.conf
|
|
||||||
# Configure /etc/mkinitcpio.conf sur le système cible
|
|
||||||
# ============================================================
|
|
||||||
|
|
||||||
# Modules à inclure dans le initramfs
|
|
||||||
modules: []
|
|
||||||
|
|
||||||
# Binaires supplémentaires
|
|
||||||
binaries: []
|
|
||||||
|
|
||||||
# Fichiers supplémentaires
|
|
||||||
files: []
|
|
||||||
|
|
||||||
# Hooks — ordre important !
|
|
||||||
hooks:
|
|
||||||
- base
|
|
||||||
- udev
|
|
||||||
- autodetect
|
|
||||||
- modconf
|
|
||||||
- block
|
|
||||||
- filesystems
|
|
||||||
- keyboard
|
|
||||||
- fsck
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
# ============================================================
|
|
||||||
# FWS Linux — modules/keyboard.conf
|
|
||||||
# ============================================================
|
|
||||||
|
|
||||||
# Disposition clavier par défaut
|
|
||||||
xorgConfigFileName: "/etc/X11/xorg.conf.d/00-keyboard.conf"
|
|
||||||
|
|
||||||
# Clavier par défaut
|
|
||||||
keyboardLayout: "fr"
|
|
||||||
keyboardVariant: ""
|
|
||||||
keyboardModel: "pc105"
|
|
||||||
|
|
||||||
# Permettre à l'utilisateur de choisir son clavier
|
|
||||||
guiTimezone: true
|
|
||||||
|
|
||||||
# Conversions vc (console virtuelle) → X11
|
|
||||||
convertedKeymapPath: "/lib/kbd/keymaps/xkb"
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
# ============================================================
|
|
||||||
# FWS Linux — modules/locale.conf
|
|
||||||
# ============================================================
|
|
||||||
|
|
||||||
# Région/timezone par défaut
|
|
||||||
region: "Europe"
|
|
||||||
zone: "Paris"
|
|
||||||
|
|
||||||
# Langue par défaut
|
|
||||||
locale: "fr_FR.UTF-8"
|
|
||||||
|
|
||||||
# Format des nombres, dates, monnaie
|
|
||||||
# Laisse vide pour utiliser la même valeur que locale
|
|
||||||
localeGenPath: "/etc/locale.gen"
|
|
||||||
|
|
||||||
# Timezone GeoIP (détection auto basée sur l'IP)
|
|
||||||
geoipStyle: "json"
|
|
||||||
geoipUrl: "https://geoip.kde.org/v1/calamares"
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
# ============================================================
|
|
||||||
# FWS Linux — modules/packages.conf
|
|
||||||
# Paquets installés via pacman pendant l'installation
|
|
||||||
# ============================================================
|
|
||||||
|
|
||||||
# Gestionnaire de paquets
|
|
||||||
backend: pacman
|
|
||||||
|
|
||||||
# Ne pas mettre à jour la base de données pacman (déjà dans le live)
|
|
||||||
update_db: false
|
|
||||||
|
|
||||||
operations:
|
|
||||||
- install:
|
|
||||||
# Base système
|
|
||||||
- base
|
|
||||||
- base-devel
|
|
||||||
- linux
|
|
||||||
- linux-headers
|
|
||||||
- linux-firmware
|
|
||||||
|
|
||||||
# Bootloader
|
|
||||||
- grub
|
|
||||||
- efibootmgr
|
|
||||||
- os-prober
|
|
||||||
- mkinitcpio-openswap
|
|
||||||
|
|
||||||
# Réseau
|
|
||||||
- networkmanager
|
|
||||||
- network-manager-applet
|
|
||||||
- wpa_supplicant
|
|
||||||
- dhcpcd
|
|
||||||
|
|
||||||
# Outils essentiels
|
|
||||||
- sudo
|
|
||||||
- nano
|
|
||||||
- vim
|
|
||||||
- git
|
|
||||||
- curl
|
|
||||||
- wget
|
|
||||||
- htop
|
|
||||||
- bash-completion
|
|
||||||
|
|
||||||
# Locale & timezone
|
|
||||||
- tzdata
|
|
||||||
|
|
||||||
# Optionnel — retire ce qui ne correspond pas à FWS
|
|
||||||
- pipewire
|
|
||||||
- pipewire-pulse
|
|
||||||
- wireplumber
|
|
||||||
|
|
||||||
# Paquets à retirer du système live (pas nécessaires après install)
|
|
||||||
- remove:
|
|
||||||
- calamares
|
|
||||||
- calamares-config
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
# ============================================================
|
|
||||||
# FWS Linux — modules/partition.conf
|
|
||||||
# ============================================================
|
|
||||||
|
|
||||||
# Backend de partitionnement
|
|
||||||
backend: kpmcore
|
|
||||||
|
|
||||||
# Autoriser le partitionnement manuel
|
|
||||||
allowManualPartitioning: true
|
|
||||||
|
|
||||||
# Schéma de partition par défaut (pour install automatique)
|
|
||||||
# Options: mbr, gpt
|
|
||||||
defaultPartitionTableType: gpt
|
|
||||||
|
|
||||||
# Swap
|
|
||||||
# Options: none, small, suspend, file
|
|
||||||
defaultSwapType: small
|
|
||||||
|
|
||||||
# Taille minimale des partitions en MiB
|
|
||||||
defaultFileSystemType: "ext4"
|
|
||||||
|
|
||||||
# Partitions EFI (pour UEFI)
|
|
||||||
efiSystemPartition: "/boot/efi"
|
|
||||||
efiSystemPartitionSize: 300
|
|
||||||
|
|
||||||
# Point de montage racine
|
|
||||||
requiredStorage: 20.0
|
|
||||||
|
|
||||||
# Systèmes de fichiers proposés à l'utilisateur
|
|
||||||
availableFileSystemTypes: ["ext4", "btrfs", "xfs", "f2fs"]
|
|
||||||
|
|
||||||
# Chiffrement
|
|
||||||
# Activer le chiffrement LUKS
|
|
||||||
allowZfs: true
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
# ============================================================
|
|
||||||
# FWS Linux — modules/services-systemd.conf
|
|
||||||
# Services systemd activés sur le système installé
|
|
||||||
# ============================================================
|
|
||||||
|
|
||||||
services:
|
|
||||||
# Réseau
|
|
||||||
- name: NetworkManager
|
|
||||||
mandatory: true
|
|
||||||
|
|
||||||
# DHCP
|
|
||||||
- name: dhcpcd
|
|
||||||
mandatory: false
|
|
||||||
|
|
||||||
# Heure synchronisée
|
|
||||||
- name: systemd-timesyncd
|
|
||||||
mandatory: true
|
|
||||||
|
|
||||||
# Ajoute ici tes services FWS supplémentaires
|
|
||||||
# - name: mon-service-fws
|
|
||||||
# mandatory: false
|
|
||||||
|
|
||||||
targets: []
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
# ============================================================
|
|
||||||
# FWS Linux — modules/unpackfs.conf
|
|
||||||
# Copie le système live vers le disque cible
|
|
||||||
# ============================================================
|
|
||||||
|
|
||||||
unpack:
|
|
||||||
# Source : le squashfs de l'ISO FWS
|
|
||||||
# Adapte "FWS" selon la valeur de iso_name dans profiledef.sh
|
|
||||||
- source: /run/archiso/bootmnt/FWS/x86_64/airootfs.sfs
|
|
||||||
sourcefs: squashfs
|
|
||||||
destination: ""
|
|
||||||
|
|
||||||
# Alternative si tu utilises erofs au lieu de squashfs :
|
|
||||||
# - source: /run/archiso/bootmnt/FWS/x86_64/airootfs.erofs
|
|
||||||
# sourcefs: erofs
|
|
||||||
# destination: ""
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
# ============================================================
|
|
||||||
# FWS Linux — modules/users.conf
|
|
||||||
# ============================================================
|
|
||||||
|
|
||||||
# Nom d'hôte par défaut
|
|
||||||
defaultGroups:
|
|
||||||
- users
|
|
||||||
- lp
|
|
||||||
- video
|
|
||||||
- network
|
|
||||||
- storage
|
|
||||||
- wheel
|
|
||||||
- audio
|
|
||||||
- optical
|
|
||||||
- scanner
|
|
||||||
- power
|
|
||||||
|
|
||||||
# Autoriser le login automatique
|
|
||||||
autologinGroup: autologin
|
|
||||||
|
|
||||||
# Sudoers — donne les droits sudo au groupe wheel
|
|
||||||
sudoersGroup: wheel
|
|
||||||
|
|
||||||
# Shell par défaut pour les nouveaux utilisateurs
|
|
||||||
userShell: /bin/bash
|
|
||||||
|
|
||||||
# Hostname par défaut
|
|
||||||
hostname:
|
|
||||||
location: EtcFile
|
|
||||||
template: "fws-${first}"
|
|
||||||
|
|
||||||
# Règles pour les mots de passe
|
|
||||||
passwordRequirements:
|
|
||||||
minLength: 6
|
|
||||||
maxLength: -1
|
|
||||||
nonempty: true
|
|
||||||
|
|
||||||
# Permet de définir le même mot de passe pour root et user
|
|
||||||
allowWeakPasswords: false
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
# ============================================================
|
|
||||||
# FWS Linux — modules/welcome.conf
|
|
||||||
# ============================================================
|
|
||||||
|
|
||||||
# Afficher les conditions requises avant l'installation
|
|
||||||
showSupportUrl: true
|
|
||||||
showKnownIssuesUrl: true
|
|
||||||
showReleaseNotesUrl: false
|
|
||||||
showDonateUrl: false
|
|
||||||
|
|
||||||
# Vérifications système requises
|
|
||||||
requirements:
|
|
||||||
# Espace disque minimum en MiB
|
|
||||||
requiredStorage: 20.0
|
|
||||||
|
|
||||||
# RAM minimum en MiB
|
|
||||||
requiredRam: 2.0
|
|
||||||
|
|
||||||
# Vérifier la connexion internet (optionnel)
|
|
||||||
checkInternet: false
|
|
||||||
|
|
||||||
# Vérifier si on tourne en live (pas déjà installé)
|
|
||||||
checkForRoot: true
|
|
||||||
|
|
||||||
# Vérifier l'alimentation (AC power)
|
|
||||||
checkPower: true
|
|
||||||
|
|
||||||
# Ne bloque pas l'install si pas connecté
|
|
||||||
internetCheckUrl: "https://cloudflare.com"
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
# ============================================================
|
|
||||||
# FWS Linux — Calamares settings.conf
|
|
||||||
# ============================================================
|
|
||||||
|
|
||||||
modules-search: [ local, /usr/lib/calamares/modules ]
|
|
||||||
|
|
||||||
sequence:
|
|
||||||
- show:
|
|
||||||
- welcome
|
|
||||||
- locale
|
|
||||||
- keyboard
|
|
||||||
- partition
|
|
||||||
- users
|
|
||||||
- summary
|
|
||||||
|
|
||||||
- exec:
|
|
||||||
- partition
|
|
||||||
- mount
|
|
||||||
- luksbootkeyfile
|
|
||||||
- luksopenswaphookcfg
|
|
||||||
- unpackfs
|
|
||||||
- machineid
|
|
||||||
- fstab
|
|
||||||
- locale
|
|
||||||
- keyboard
|
|
||||||
- localecfg
|
|
||||||
- users
|
|
||||||
- networkcfg
|
|
||||||
- hwclock
|
|
||||||
- services-systemd
|
|
||||||
- packages
|
|
||||||
- initcpiocfg
|
|
||||||
- initcpio
|
|
||||||
- grubcfg
|
|
||||||
- bootloader
|
|
||||||
- umount
|
|
||||||
|
|
||||||
- show:
|
|
||||||
- finished
|
|
||||||
|
|
||||||
branding: fws
|
|
||||||
|
|
||||||
# Demande confirmation avant d'installer
|
|
||||||
prompt-install: true
|
|
||||||
|
|
||||||
# Ne pas chroot (laisser à false pour une install normale)
|
|
||||||
dont-chroot: false
|
|
||||||
|
|
||||||
# Désactive les vérifications réseau au démarrage
|
|
||||||
disable-cancel: false
|
|
||||||
disable-cancel-during-exec: true
|
|
||||||
+40
@@ -0,0 +1,40 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# ============================================================================
|
||||||
|
# FWS — entrée « Réparer FWS » dans le menu GRUB du SYSTÈME INSTALLÉ
|
||||||
|
# (l'équivalent de l'environnement de récupération de Windows).
|
||||||
|
#
|
||||||
|
# Ce script est exécuté par grub-mkconfig (à l'installation via le %post du
|
||||||
|
# kickstart, puis à chaque fws-recovery « Réinstaller GRUB »). Il démarre le
|
||||||
|
# MÊME système sur fws-recovery.target (+ marqueur fws.recovery=1) :
|
||||||
|
# fws-recovery-boot.service prend alors tty1 et lance l'application de
|
||||||
|
# réparation (GUI via startx, repli console).
|
||||||
|
#
|
||||||
|
# Sur le live, ce fichier est inerte (grub-mkconfig n'y tourne jamais).
|
||||||
|
# ============================================================================
|
||||||
|
set -e
|
||||||
|
. /usr/share/grub/grub-mkconfig_lib
|
||||||
|
|
||||||
|
kernel=/boot/vmlinuz-linux
|
||||||
|
# L'initramfs FALLBACK (sans autodetect) : c'est l'entrée de secours, elle
|
||||||
|
# doit démarrer même si le matériel a changé depuis le dernier mkinitcpio.
|
||||||
|
initrd=/boot/initramfs-linux-fallback.img
|
||||||
|
[ -f "$initrd" ] || initrd=/boot/initramfs-linux.img
|
||||||
|
[ -f "$kernel" ] && [ -f "$initrd" ] || exit 0
|
||||||
|
|
||||||
|
# Même logique racine que 10_linux : UUID sauf refus explicite.
|
||||||
|
if [ -n "${GRUB_DEVICE_UUID:-}" ] && [ "x${GRUB_DISABLE_LINUX_UUID:-}" != xtrue ]; then
|
||||||
|
rootarg="root=UUID=$GRUB_DEVICE_UUID"
|
||||||
|
else
|
||||||
|
rootarg="root=$GRUB_DEVICE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
rel_kernel="$(make_system_path_relative_to_its_root "$kernel")"
|
||||||
|
rel_initrd="$(make_system_path_relative_to_its_root "$initrd")"
|
||||||
|
|
||||||
|
cat <<EOF
|
||||||
|
menuentry 'Réparer FWS (récupération du système)' --class recovery {
|
||||||
|
$(prepare_grub_to_access_device "${GRUB_DEVICE_BOOT}" | grub_add_tab)
|
||||||
|
linux $rel_kernel $rootarg rw ${GRUB_CMDLINE_LINUX:-} systemd.unit=fws-recovery.target fws.recovery=1
|
||||||
|
initrd $rel_initrd
|
||||||
|
}
|
||||||
|
EOF
|
||||||
@@ -1 +1 @@
|
|||||||
archiso
|
fws
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
\S (\l)
|
||||||
|
|
||||||
@@ -1,11 +1,8 @@
|
|||||||
To install [38;2;23;147;209mFWS[0m follow the installation guide:
|
Welcome to [38;2;23;147;209mFWS[0m live media.
|
||||||
https://wiki.archlinux.org/title/Installation_guide
|
|
||||||
|
To install FWS, see the project page:
|
||||||
|
https://github.com/You-re-like-Windows-a-bitch/fws
|
||||||
|
|
||||||
For Wi-Fi, authenticate to the wireless network using the [35miwctl[0m utility.
|
For Wi-Fi, authenticate to the wireless network using the [35miwctl[0m utility.
|
||||||
For mobile broadband (WWAN) modems, connect with the [35mmmcli[0m utility.
|
For mobile broadband (WWAN) modems, connect with the [35mmmcli[0m utility.
|
||||||
Ethernet, WLAN and WWAN interfaces using DHCP should work automatically.
|
Ethernet, WLAN and WWAN interfaces using DHCP should work automatically.
|
||||||
|
|
||||||
After connecting to the internet, the installation guide can be accessed
|
|
||||||
via the convenience script [35mInstallation_guide[0m.
|
|
||||||
|
|
||||||
[41m [41m [41m [40m [44m [40m [41m [46m [45m [41m [46m [43m [41m [44m [45m [40m [44m [40m [41m [44m [41m [41m [46m [42m [41m [44m [43m [41m [45m [40m [40m [44m [40m [41m [44m [42m [41m [46m [44m [41m [46m [47m [0m
|
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
# remove from airootfs!
|
||||||
|
# Branding FWS : le paquet « filesystem » d'Arch installe /usr/lib/os-release
|
||||||
|
# avec NAME="Arch Linux". On le remplace par la version FWS APRÈS l'installation
|
||||||
|
# des paquets (PostTransaction), donc sans conflit pacman « exists in filesystem »
|
||||||
|
# (poser le fichier dans l'overlay déclencherait ce conflit, cf. ordre overlay→
|
||||||
|
# pacstrap dans mkarchiso). /etc/os-release reste un lien vers ce fichier.
|
||||||
|
# Ce hook ne sert qu'au build : zzzz99-remove-custom-hooks le retire du système.
|
||||||
|
|
||||||
|
[Trigger]
|
||||||
|
Operation = Install
|
||||||
|
Operation = Upgrade
|
||||||
|
Type = Package
|
||||||
|
Target = filesystem
|
||||||
|
|
||||||
|
[Action]
|
||||||
|
Description = Applying FWS branding to /usr/lib/os-release...
|
||||||
|
When = PostTransaction
|
||||||
|
Depends = filesystem
|
||||||
|
Depends = coreutils
|
||||||
|
Exec = /usr/bin/install -Dm0644 /usr/local/share/fws/os-release /usr/lib/os-release
|
||||||
@@ -1,5 +1,18 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
status=$?
|
# NB : ce fichier est SOURCÉ par le shell de login (zsh sur le live), pas exécuté
|
||||||
if [ "${status}" -eq 0 ]; then
|
# → le shebang est ignoré. En zsh « status » est une variable spéciale EN LECTURE
|
||||||
fastfetch
|
# SEULE (alias de $?) : s'y affecter casse (« read-only variable: status »).
|
||||||
|
# On utilise donc un autre nom.
|
||||||
|
_fastfetch_rc=$?
|
||||||
|
if [ "${_fastfetch_rc}" -eq 0 ]; then
|
||||||
|
# Logo FWS maison (4 carrés + Tux) au lieu du logo Arch détecté par défaut.
|
||||||
|
fastfetch \
|
||||||
|
--logo-type file \
|
||||||
|
--logo /usr/local/share/fws/logo.txt \
|
||||||
|
--logo-color-1 '38;2;30;160;100' \
|
||||||
|
--logo-color-2 '38;2;45;125;210' \
|
||||||
|
--logo-color-3 '38;2;240;180;40' \
|
||||||
|
--logo-color-4 '38;2;25;85;145' \
|
||||||
|
--logo-color-5 '38;2;28;28;34' \
|
||||||
|
--logo-color-6 '38;2;245;165;35'
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
[Unit]
|
|
||||||
Description=Calamares Installer
|
|
||||||
After=display-manager.service
|
|
||||||
Requires=display-manager.service
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
ExecStart=/usr/bin/calamares
|
|
||||||
Restart=on-failure
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=graphical.target
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
/usr/lib/systemd/system/systemd-timesyncd.service
|
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
/usr/lib/systemd/system/systemd-timesyncd.service
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=FWS - Reparation du systeme (session de secours sur tty1)
|
||||||
|
# Demarre UNIQUEMENT via fws-recovery.target (entree GRUB « Reparer FWS » du
|
||||||
|
# systeme installe : systemd.unit=fws-recovery.target). PAS de [Install] :
|
||||||
|
# enrole dans aucun boot normal, donc son Conflicts=getty@tty1 ne peut jamais
|
||||||
|
# casser le login tty1 d'un boot ordinaire.
|
||||||
|
# Sur le live, c'est /root/.zprofile (autologin tty1) qui gere la reparation.
|
||||||
|
ConditionKernelCommandLine=fws.recovery=1
|
||||||
|
ConditionPathExists=!/run/archiso
|
||||||
|
Conflicts=getty@tty1.service display-manager.service
|
||||||
|
After=systemd-user-sessions.service getty@tty1.service display-manager.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=idle
|
||||||
|
# GUI via startx (openbox + fws-recovery-gui) ; si X ne demarre pas (pilote
|
||||||
|
# video casse — un cas de reparation typique), repli sur l'assistant CONSOLE.
|
||||||
|
ExecStart=/bin/sh -c '/usr/bin/startx /usr/local/bin/fws-recovery-session -- vt1 || exec /usr/local/bin/fws-recovery'
|
||||||
|
StandardInput=tty
|
||||||
|
StandardOutput=tty
|
||||||
|
StandardError=tty
|
||||||
|
TTYPath=/dev/tty1
|
||||||
|
TTYReset=yes
|
||||||
|
TTYVHangup=yes
|
||||||
|
Restart=no
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=FWS - Cible de reparation du systeme
|
||||||
|
# Demandee par l'entree GRUB « Reparer FWS » du systeme installe
|
||||||
|
# (kernel : systemd.unit=fws-recovery.target fws.recovery=1).
|
||||||
|
# Un multi-user complet (reseau pour pacman -Syu) + la session de reparation ;
|
||||||
|
# le Conflicts du service libere tty1 (son start est REQUIS ici, il gagne
|
||||||
|
# contre le Wants de getty@tty1).
|
||||||
|
Requires=multi-user.target fws-recovery-boot.service
|
||||||
|
After=multi-user.target fws-recovery-boot.service
|
||||||
|
AllowIsolate=yes
|
||||||
-1
@@ -1 +0,0 @@
|
|||||||
/usr/lib/systemd/system/systemd-time-wait-sync.service
|
|
||||||
Symlink
+1
@@ -0,0 +1 @@
|
|||||||
|
/usr/lib/systemd/system/systemd-time-wait-sync.service
|
||||||
-1
@@ -1 +0,0 @@
|
|||||||
/usr/lib/systemd/system/systemd-timesyncd.service
|
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
/usr/lib/systemd/system/systemd-timesyncd.service
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
# FWS — swap compressé en RAM (zram), activé automatiquement par
|
||||||
|
# zram-generator (paquet dans packages.x86_64, aucun service à activer).
|
||||||
|
#
|
||||||
|
# Le LIVE n'a AUCUN swap : sur une machine/VM à 2 Go, Anaconda + le rootfs
|
||||||
|
# squashfs saturent la mémoire → livelock, écran figé pendant « Préparation
|
||||||
|
# de l'installateur ». Le zram (compression ~3:1 sur les tas Python) donne
|
||||||
|
# la marge nécessaire. Copié tel quel sur le SYSTÈME INSTALLÉ par le payload
|
||||||
|
# LiveOS → FWS garde ce filet de sécurité après installation (esprit
|
||||||
|
# « remplaçant de Windows » sur des machines modestes).
|
||||||
|
[zram0]
|
||||||
|
zram-size = min(ram, 4096)
|
||||||
|
compression-algorithm = zstd
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Type=Application
|
||||||
|
Name=Bienvenue sur FWS
|
||||||
|
Comment=Fenêtre de bienvenue au premier démarrage
|
||||||
|
Exec=fws-hello --autostart
|
||||||
|
Icon=help-about
|
||||||
|
Terminal=false
|
||||||
|
Categories=System;
|
||||||
|
X-GNOME-Autostart-enabled=true
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# ============================================================
|
|
||||||
# FWS Linux — fws-installer
|
|
||||||
# Script de lancement de Calamares
|
|
||||||
# ============================================================
|
|
||||||
|
|
||||||
# Vérifie que Calamares est installé
|
|
||||||
if ! command -v calamares &>/dev/null; then
|
|
||||||
echo "ERREUR : calamares n'est pas installé."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Vérifie qu'on tourne bien en live
|
|
||||||
if [ ! -d /run/archiso ]; then
|
|
||||||
echo "ATTENTION : Ce script doit être lancé depuis le live FWS."
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Lance Calamares avec les droits root
|
|
||||||
# -D6 active les logs de debug (retirer en production)
|
|
||||||
if [ "$EUID" -ne 0 ]; then
|
|
||||||
if command -v sudo >/dev/null 2>&1; then
|
|
||||||
exec sudo -E calamares "$@"
|
|
||||||
elif command -v pkexec >/dev/null 2>&1; then
|
|
||||||
exec pkexec calamares "$@"
|
|
||||||
else
|
|
||||||
echo "ERREUR : Impossible de lancer Calamares en tant que root (sudo/pkexec non trouvés)."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
exec calamares "$@"
|
|
||||||
fi
|
|
||||||
Regular → Executable
Regular → Executable
+185
@@ -0,0 +1,185 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# FWS — fenêtre « À propos » : deux onglets, « Le projet FWS » (ce qu'est FWS,
|
||||||
|
# version, liens) et « Système » (matériel + logiciel détectés). Remplace le
|
||||||
|
# « About Xfce » de libxfce4ui par une page de marque FWS. GTK3 (python-gobject
|
||||||
|
# installé avec le bureau).
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
import gi
|
||||||
|
|
||||||
|
gi.require_version("Gtk", "3.0")
|
||||||
|
gi.require_version("Gdk", "3.0") # sinon gi charge Gdk 4.0 (conflit avec Gtk3)
|
||||||
|
from gi.repository import Gdk, GLib, Gtk # noqa: E402
|
||||||
|
|
||||||
|
GLib.set_prgname("fws-about")
|
||||||
|
|
||||||
|
|
||||||
|
def _osrelease():
|
||||||
|
data = {}
|
||||||
|
for path in ("/etc/os-release", "/usr/lib/os-release"):
|
||||||
|
try:
|
||||||
|
with open(path) as fh:
|
||||||
|
for line in fh:
|
||||||
|
m = re.match(r'^([A-Z_]+)=(.*)$', line.strip())
|
||||||
|
if m:
|
||||||
|
data[m.group(1)] = m.group(2).strip('"')
|
||||||
|
break
|
||||||
|
except OSError:
|
||||||
|
continue
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def _cmd(*argv):
|
||||||
|
try:
|
||||||
|
return subprocess.check_output(argv, text=True,
|
||||||
|
stderr=subprocess.DEVNULL).strip()
|
||||||
|
except (OSError, subprocess.CalledProcessError):
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
|
def _cpu():
|
||||||
|
try:
|
||||||
|
with open("/proc/cpuinfo") as fh:
|
||||||
|
for line in fh:
|
||||||
|
if line.startswith("model name"):
|
||||||
|
return line.split(":", 1)[1].strip()
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
return "inconnu"
|
||||||
|
|
||||||
|
|
||||||
|
def _mem():
|
||||||
|
try:
|
||||||
|
with open("/proc/meminfo") as fh:
|
||||||
|
for line in fh:
|
||||||
|
if line.startswith("MemTotal"):
|
||||||
|
kib = int(line.split()[1])
|
||||||
|
return f"{kib / 1048576:.1f} Gio"
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
return "inconnu"
|
||||||
|
|
||||||
|
|
||||||
|
def _gpus():
|
||||||
|
out = []
|
||||||
|
for line in _cmd("lspci").splitlines():
|
||||||
|
low = line.lower()
|
||||||
|
if "vga" in low or "3d" in low or "display" in low:
|
||||||
|
out.append(line.split(":", 2)[-1].strip())
|
||||||
|
return out or ["inconnu"]
|
||||||
|
|
||||||
|
|
||||||
|
def _desktop():
|
||||||
|
if os.environ.get("HYPRLAND_INSTANCE_SIGNATURE"):
|
||||||
|
return "Hyprland"
|
||||||
|
env = os.environ.get("XDG_CURRENT_DESKTOP") \
|
||||||
|
or os.environ.get("DESKTOP_SESSION") or ""
|
||||||
|
return env or "inconnu"
|
||||||
|
|
||||||
|
|
||||||
|
def _session_type():
|
||||||
|
t = os.environ.get("XDG_SESSION_TYPE", "")
|
||||||
|
return {"wayland": "Wayland", "x11": "X11"}.get(t, t or "inconnu")
|
||||||
|
|
||||||
|
|
||||||
|
def _disks():
|
||||||
|
out = []
|
||||||
|
for line in _cmd("lsblk", "-dno", "NAME,SIZE,MODEL,TYPE").splitlines():
|
||||||
|
f = line.split()
|
||||||
|
if f and f[-1] == "disk":
|
||||||
|
out.append(" ".join(f[:-1]))
|
||||||
|
return out or ["inconnu"]
|
||||||
|
|
||||||
|
|
||||||
|
def _grid(rows):
|
||||||
|
grid = Gtk.Grid(column_spacing=18, row_spacing=8, margin=18)
|
||||||
|
for i, (key, val) in enumerate(rows):
|
||||||
|
k = Gtk.Label(xalign=1)
|
||||||
|
k.set_markup(f"<b>{GLib.markup_escape_text(key)}</b>")
|
||||||
|
k.get_style_context().add_class("dim-label")
|
||||||
|
v = Gtk.Label(label=val, xalign=0, selectable=True)
|
||||||
|
v.set_line_wrap(True)
|
||||||
|
grid.attach(k, 0, i, 1, 1)
|
||||||
|
grid.attach(v, 1, i, 1, 1)
|
||||||
|
return grid
|
||||||
|
|
||||||
|
|
||||||
|
def _project_tab(osr):
|
||||||
|
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10, margin=20)
|
||||||
|
title = Gtk.Label()
|
||||||
|
name = osr.get("PRETTY_NAME") or osr.get("NAME") or "FWS Linux"
|
||||||
|
title.set_markup(f"<span size='xx-large' weight='bold'>{name}</span>")
|
||||||
|
box.pack_start(title, False, False, 0)
|
||||||
|
|
||||||
|
tag = Gtk.Label(label="Une distribution Linux pensée pour remplacer "
|
||||||
|
"Windows : bureau prêt à l'emploi, jeux, VR et "
|
||||||
|
"compatibilité applicative.")
|
||||||
|
tag.set_line_wrap(True)
|
||||||
|
tag.set_max_width_chars(52)
|
||||||
|
box.pack_start(tag, False, False, 0)
|
||||||
|
|
||||||
|
feats = Gtk.Label()
|
||||||
|
feats.set_markup(
|
||||||
|
"<b>Inclus :</b> installateur graphique · plusieurs bureaux "
|
||||||
|
"(GNOME, KDE, Hyprland, i3, XFCE) · Steam & Proton-GE · "
|
||||||
|
"réalité virtuelle (SteamVR) · winboat (applications Windows) · "
|
||||||
|
"pare-feu · réparation système intégrée.")
|
||||||
|
feats.set_line_wrap(True)
|
||||||
|
feats.set_max_width_chars(52)
|
||||||
|
feats.set_xalign(0)
|
||||||
|
box.pack_start(feats, False, False, 6)
|
||||||
|
|
||||||
|
home = osr.get("HOME_URL") or "https://github.com/You-re-like-Windows-a-bitch/fws"
|
||||||
|
link = Gtk.LinkButton.new_with_label(home, "Site du projet")
|
||||||
|
box.pack_start(link, False, False, 0)
|
||||||
|
return box
|
||||||
|
|
||||||
|
|
||||||
|
def _system_tab(osr):
|
||||||
|
rows = [
|
||||||
|
("Système", osr.get("PRETTY_NAME", "FWS Linux")),
|
||||||
|
("Build", osr.get("BUILD_ID", "rolling")),
|
||||||
|
("Noyau", _cmd("uname", "-r") or "inconnu"),
|
||||||
|
("Bureau", _desktop()),
|
||||||
|
("Affichage", _session_type()),
|
||||||
|
("Nom de machine", _cmd("hostname") or os.uname().nodename),
|
||||||
|
("Processeur", _cpu()),
|
||||||
|
("Mémoire", _mem()),
|
||||||
|
("Carte(s) graphique(s)", "\n".join(_gpus())),
|
||||||
|
("Disque(s)", "\n".join(_disks())),
|
||||||
|
]
|
||||||
|
scroll = Gtk.ScrolledWindow()
|
||||||
|
scroll.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
|
||||||
|
scroll.add(_grid(rows))
|
||||||
|
return scroll
|
||||||
|
|
||||||
|
|
||||||
|
class AboutWindow(Gtk.Window):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__(title="À propos de FWS")
|
||||||
|
self.set_default_size(520, 460)
|
||||||
|
self.set_position(Gtk.WindowPosition.CENTER)
|
||||||
|
self.set_type_hint(Gdk.WindowTypeHint.DIALOG)
|
||||||
|
|
||||||
|
osr = _osrelease()
|
||||||
|
notebook = Gtk.Notebook()
|
||||||
|
notebook.append_page(_project_tab(osr), Gtk.Label(label="Le projet FWS"))
|
||||||
|
notebook.append_page(_system_tab(osr), Gtk.Label(label="Système"))
|
||||||
|
self.add(notebook)
|
||||||
|
self.connect("destroy", Gtk.main_quit)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if not Gtk.init_check()[0]:
|
||||||
|
return 1
|
||||||
|
win = AboutWindow()
|
||||||
|
win.show_all()
|
||||||
|
Gtk.main()
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main())
|
||||||
+158
@@ -0,0 +1,158 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# FWS — fenêtre de bienvenue au premier démarrage (pendant post-install de la
|
||||||
|
# page récap de l'installateur). Boutons : mise à jour, codecs, VR, raccourcis,
|
||||||
|
# Proton-GE. GTK3 : présent sur TOUS les bureaux FWS (Firefox le tire) ;
|
||||||
|
# python-gobject est installé avec le bureau par le kickstart.
|
||||||
|
#
|
||||||
|
# Lancement : /etc/xdg/autostart (KDE/GNOME/XFCE) et exec des configs
|
||||||
|
# Hyprland/i3, toujours avec --autostart : on se retire sans bruit si
|
||||||
|
# l'utilisateur a coché « ne plus afficher » (~/.config/fws/hello-done).
|
||||||
|
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import gi
|
||||||
|
|
||||||
|
gi.require_version("Gtk", "3.0")
|
||||||
|
gi.require_version("Gdk", "3.0") # sinon gi charge Gdk 4.0 (conflit avec Gtk3)
|
||||||
|
from gi.repository import Gdk, GLib, Gtk # noqa: E402
|
||||||
|
|
||||||
|
# WM_CLASS déterministe : les règles i3/Hyprland « fenêtre flottante »
|
||||||
|
# ciblent cette classe.
|
||||||
|
GLib.set_prgname("fws-hello")
|
||||||
|
|
||||||
|
_FLAG = os.path.expanduser("~/.config/fws/hello-done")
|
||||||
|
|
||||||
|
_CODECS = ("gst-plugins-base gst-plugins-good gst-plugins-bad "
|
||||||
|
"gst-plugins-ugly gst-libav ffmpeg mpv")
|
||||||
|
|
||||||
|
# (libellé, description, commande, en_terminal)
|
||||||
|
_ACTIONS = [
|
||||||
|
("Mettre à jour le système",
|
||||||
|
"pacman -Syu + nettoyage du cache",
|
||||||
|
"fws-update", True),
|
||||||
|
("Installer les codecs multimédia",
|
||||||
|
"lecture vidéo/audio (GStreamer, ffmpeg, mpv)",
|
||||||
|
f"sudo pacman -S --needed {_CODECS}", True),
|
||||||
|
("Proton-GE pour Steam",
|
||||||
|
"meilleure compatibilité des jeux Windows",
|
||||||
|
"fws-proton-ge", True),
|
||||||
|
("Configurer la VR",
|
||||||
|
"drivers casque : HTC Vive, Index, Quest…",
|
||||||
|
"fws-vr-setup", True),
|
||||||
|
]
|
||||||
|
|
||||||
|
_TERMINALS = ["kitty", "konsole", "gnome-terminal", "xfce4-terminal", "xterm"]
|
||||||
|
|
||||||
|
|
||||||
|
def _terminal():
|
||||||
|
for term in _TERMINALS:
|
||||||
|
if shutil.which(term):
|
||||||
|
return term
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _run(command, in_terminal):
|
||||||
|
if in_terminal:
|
||||||
|
term = _terminal()
|
||||||
|
if term is None:
|
||||||
|
return
|
||||||
|
if term == "gnome-terminal":
|
||||||
|
argv = [term, "--", "sh", "-c", command]
|
||||||
|
else:
|
||||||
|
argv = [term, "-e", "sh", "-c", command]
|
||||||
|
else:
|
||||||
|
argv = ["sh", "-c", command]
|
||||||
|
subprocess.Popen(argv) # noqa: S603 — commandes internes FWS
|
||||||
|
|
||||||
|
|
||||||
|
class HelloWindow(Gtk.Window):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__(title="Bienvenue sur FWS")
|
||||||
|
self.set_default_size(460, -1)
|
||||||
|
self.set_position(Gtk.WindowPosition.CENTER)
|
||||||
|
self.set_border_width(18)
|
||||||
|
# DIALOGUE : les tuileurs (i3/Hyprland) laissent les dialogues en
|
||||||
|
# flottant → la fenêtre garde sa taille naturelle au lieu d'être
|
||||||
|
# étirée sur tout l'espace de travail (layout illisible sinon).
|
||||||
|
self.set_type_hint(Gdk.WindowTypeHint.DIALOG)
|
||||||
|
self.set_resizable(False)
|
||||||
|
|
||||||
|
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=12)
|
||||||
|
self.add(box)
|
||||||
|
|
||||||
|
title = Gtk.Label()
|
||||||
|
title.set_markup("<span size='x-large' weight='bold'>Bienvenue sur FWS !</span>")
|
||||||
|
box.pack_start(title, False, False, 0)
|
||||||
|
|
||||||
|
subtitle = Gtk.Label(
|
||||||
|
label="Ton système est prêt. Quelques réglages utiles pour bien démarrer :")
|
||||||
|
subtitle.set_line_wrap(True)
|
||||||
|
subtitle.set_xalign(0)
|
||||||
|
box.pack_start(subtitle, False, False, 0)
|
||||||
|
|
||||||
|
actions = list(_ACTIONS)
|
||||||
|
# Raccourcis clavier : uniquement sur les sessions qui ont fws-keys
|
||||||
|
# (Hyprland/i3) — les autres bureaux ont leurs propres réglages.
|
||||||
|
session = os.environ.get("XDG_CURRENT_DESKTOP", "").lower()
|
||||||
|
if os.environ.get("HYPRLAND_INSTANCE_SIGNATURE") or "i3" in session:
|
||||||
|
actions.append(("Voir les raccourcis clavier",
|
||||||
|
"aussi disponible à tout moment : Super+K",
|
||||||
|
"fws-keys", False))
|
||||||
|
|
||||||
|
for label, desc, command, in_term in actions:
|
||||||
|
button = Gtk.Button()
|
||||||
|
inner = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=2)
|
||||||
|
lab = Gtk.Label()
|
||||||
|
lab.set_markup(f"<b>{label}</b>")
|
||||||
|
lab.set_xalign(0)
|
||||||
|
sub = Gtk.Label(label=desc)
|
||||||
|
sub.set_xalign(0)
|
||||||
|
sub.get_style_context().add_class("dim-label")
|
||||||
|
inner.pack_start(lab, False, False, 0)
|
||||||
|
inner.pack_start(sub, False, False, 0)
|
||||||
|
button.add(inner)
|
||||||
|
button.connect("clicked",
|
||||||
|
lambda _b, c=command, t=in_term: _run(c, t))
|
||||||
|
box.pack_start(button, False, False, 0)
|
||||||
|
|
||||||
|
self._again = Gtk.CheckButton(label="Afficher cette fenêtre au prochain démarrage")
|
||||||
|
self._again.set_active(False)
|
||||||
|
box.pack_start(self._again, False, False, 6)
|
||||||
|
|
||||||
|
close = Gtk.Button(label="Fermer")
|
||||||
|
close.connect("clicked", lambda _b: self.close())
|
||||||
|
box.pack_start(close, False, False, 0)
|
||||||
|
|
||||||
|
self.connect("destroy", self._on_destroy)
|
||||||
|
|
||||||
|
def _on_destroy(self, _win):
|
||||||
|
if not self._again.get_active():
|
||||||
|
os.makedirs(os.path.dirname(_FLAG), exist_ok=True)
|
||||||
|
with open(_FLAG, "w") as fh:
|
||||||
|
fh.write("ok\n")
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
os.unlink(_FLAG)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
Gtk.main_quit()
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if "--autostart" in sys.argv and os.path.exists(_FLAG):
|
||||||
|
return 0
|
||||||
|
# Pas d'affichage joignable (lancement hors session graphique) : on se
|
||||||
|
# retire sans traceback plutôt que de crasher.
|
||||||
|
if not Gtk.init_check()[0]:
|
||||||
|
return 1
|
||||||
|
win = HelloWindow()
|
||||||
|
win.show_all()
|
||||||
|
Gtk.main()
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main())
|
||||||
+129
@@ -0,0 +1,129 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# FWS — affiche les raccourcis clavier RÉELS de la session (bouton ⌨ de la
|
||||||
|
# barre ou Super+K). Universel :
|
||||||
|
# • Hyprland : « hyprctl binds -j » = les binds effectivement chargés
|
||||||
|
# (descriptions des bindd) — affichage wofi (Wayland).
|
||||||
|
# • i3 : parse ~/.config/i3/config (bindsym, variables résolues)
|
||||||
|
# — affichage rofi (X11).
|
||||||
|
# Aucune dépendance hors python3 + wofi/rofi (déjà installés avec le bureau).
|
||||||
|
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
_WOFI_STYLE = "/usr/local/share/fws/wofi-keys.css"
|
||||||
|
|
||||||
|
# Bits de modmask Hyprland (masques X11) dans l'ordre d'affichage voulu.
|
||||||
|
_MODS = [(64, "SUPER"), (4, "CTRL"), (8, "ALT"), (1, "SHIFT")]
|
||||||
|
|
||||||
|
_KEY_LABELS = {
|
||||||
|
"mouse:272": "clic gauche",
|
||||||
|
"mouse:273": "clic droit",
|
||||||
|
"mouse:274": "clic molette",
|
||||||
|
"mouse_down": "molette bas",
|
||||||
|
"mouse_up": "molette haut",
|
||||||
|
"button4": "molette haut",
|
||||||
|
"button5": "molette bas",
|
||||||
|
"return": "Entrée",
|
||||||
|
"space": "Espace",
|
||||||
|
"escape": "Échap",
|
||||||
|
"tab": "Tab",
|
||||||
|
"left": "←",
|
||||||
|
"right": "→",
|
||||||
|
"up": "↑",
|
||||||
|
"down": "↓",
|
||||||
|
"print": "Impr écran",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _label(key):
|
||||||
|
return _KEY_LABELS.get(key.lower(), key)
|
||||||
|
|
||||||
|
|
||||||
|
# --- Hyprland : binds réels via hyprctl ------------------------------------
|
||||||
|
def hyprland_lines():
|
||||||
|
raw = subprocess.check_output(["hyprctl", "binds", "-j"], text=True)
|
||||||
|
lines, seen = [], set()
|
||||||
|
for bind in json.loads(raw):
|
||||||
|
parts = [name for bit, name in _MODS if bind.get("modmask", 0) & bit]
|
||||||
|
key = bind.get("key") or (f"code {bind['keycode']}" if bind.get("keycode") else "")
|
||||||
|
parts.append(_label(key))
|
||||||
|
combo = " + ".join(p for p in parts if p)
|
||||||
|
if not combo or combo in seen:
|
||||||
|
continue
|
||||||
|
seen.add(combo)
|
||||||
|
desc = (bind.get("description") or "").strip() \
|
||||||
|
or f"{bind.get('dispatcher', '?')} {(bind.get('arg') or '').strip()}".strip()
|
||||||
|
lines.append(f"{combo:<24} {desc}")
|
||||||
|
return lines
|
||||||
|
|
||||||
|
|
||||||
|
# --- i3 : parse de la config (variables résolues) ----------------------------
|
||||||
|
def i3_lines():
|
||||||
|
path = os.path.expanduser("~/.config/i3/config")
|
||||||
|
variables = {}
|
||||||
|
lines, seen = [], set()
|
||||||
|
with open(path, encoding="utf-8", errors="replace") as fh:
|
||||||
|
content = fh.readlines()
|
||||||
|
for line in content:
|
||||||
|
m = re.match(r"\s*set\s+(\$\S+)\s+(.+)$", line)
|
||||||
|
if m:
|
||||||
|
variables[m.group(1)] = m.group(2).strip()
|
||||||
|
def resolve(text):
|
||||||
|
# $var les plus longs d'abord ($filemanager avant $file…).
|
||||||
|
for var in sorted(variables, key=len, reverse=True):
|
||||||
|
text = text.replace(var, variables[var])
|
||||||
|
return text
|
||||||
|
for line in content:
|
||||||
|
m = re.match(r"\s*bindsym\s+(?:--\S+\s+)*(\S+)\s+(.+)$", line)
|
||||||
|
if not m:
|
||||||
|
continue
|
||||||
|
combo_raw, action = m.groups()
|
||||||
|
combo_raw = resolve(combo_raw).replace("Mod4", "Super").replace("Mod1", "Alt")
|
||||||
|
combo = " + ".join(_label(k) for k in combo_raw.split("+"))
|
||||||
|
if combo in seen:
|
||||||
|
continue
|
||||||
|
seen.add(combo)
|
||||||
|
action = resolve(action)
|
||||||
|
action = re.sub(r"^exec\s+(--no-startup-id\s+)?", "", action).strip().strip('"')
|
||||||
|
lines.append(f"{combo:<24} {action}")
|
||||||
|
return lines
|
||||||
|
|
||||||
|
|
||||||
|
def show(lines):
|
||||||
|
if not lines:
|
||||||
|
lines = ["(aucun raccourci trouvé)"]
|
||||||
|
text = "\n".join(lines)
|
||||||
|
if os.environ.get("HYPRLAND_INSTANCE_SIGNATURE"):
|
||||||
|
cmd = ["wofi", "--dmenu", "--prompt", "Raccourcis clavier — taper pour filtrer",
|
||||||
|
"--width", "820", "--height", "600", "--insensitive",
|
||||||
|
"--cache-file", "/dev/null"]
|
||||||
|
if os.path.exists(_WOFI_STYLE):
|
||||||
|
cmd += ["--style", _WOFI_STYLE]
|
||||||
|
else:
|
||||||
|
# X11/i3 : rofi en dmenu, style assorti (mono pour l'alignement).
|
||||||
|
cmd = ["rofi", "-dmenu", "-i", "-p", "Raccourcis clavier",
|
||||||
|
"-no-custom",
|
||||||
|
"-theme-str", 'window { width: 880px; } listview { lines: 18; }',
|
||||||
|
"-theme-str", '* { font: "Noto Sans Mono 11"; }']
|
||||||
|
subprocess.run(cmd, input=text, text=True, check=False)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
try:
|
||||||
|
if os.environ.get("HYPRLAND_INSTANCE_SIGNATURE"):
|
||||||
|
lines = hyprland_lines()
|
||||||
|
else:
|
||||||
|
lines = i3_lines()
|
||||||
|
except Exception as exc: # noqa: BLE001 — best effort, jamais de crash muet
|
||||||
|
subprocess.run(["notify-send", "Raccourcis FWS", f"Erreur : {exc}"],
|
||||||
|
check=False)
|
||||||
|
return 1
|
||||||
|
show(lines)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main())
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user