Compare commits
171 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 53ceeabcfb | |||
| 335b59ceca | |||
|
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
|
+1
-5
@@ -1,8 +1,4 @@
|
||||
out/
|
||||
local-repo/
|
||||
configs/baseline/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/
|
||||
configs/releng/airootfs/etc/systemd/system/multi-user.target.wants/
|
||||
+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
|
||||
===============
|
||||
|
||||
The build system (``mkarchiso``, profiles, man pages) derives from archiso and
|
||||
retains the authorship of its original contributors:
|
||||
|
||||
* 2hexed <2hexed@protonmail.com>
|
||||
* Aaron Griffin <aaron@archlinux.org>
|
||||
* Adam Purkrt <adam@purkrt.net>
|
||||
|
||||
+31
-2
@@ -2,15 +2,35 @@
|
||||
Changelog
|
||||
#########
|
||||
|
||||
[XX] - YYYY-MM-DD
|
||||
=================
|
||||
[0.6.0] - 2026-07-07
|
||||
====================
|
||||
|
||||
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.
|
||||
|
||||
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``).
|
||||
- Use xz compression for the baseline profile's bootstrap tarball so that it has more differences when compared to the
|
||||
releng profile.
|
||||
- Match network interfaces by their type, instead of name, in systemd-networkd configuration.
|
||||
@@ -21,12 +41,21 @@ Deprecated
|
||||
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.
|
||||
- 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``.
|
||||
|
||||
Removed
|
||||
-------
|
||||
|
||||
- ``configs/baseline/syslinux/syslinux-linux.cfg`` (label ``arch`` stock, orphelin et sans cap udev).
|
||||
|
||||
[87] - 2025-10-29
|
||||
=================
|
||||
|
||||
|
||||
+23
-2
@@ -2,8 +2,29 @@
|
||||
Contributing
|
||||
============
|
||||
|
||||
These are the contribution guidelines for archiso.
|
||||
All contributions fall under the terms of the GPL-3.0-or-later (see `LICENSE <LICENSE>`_).
|
||||
These are the contribution guidelines for **FWS**. FWS is a fork of `archiso
|
||||
<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
|
||||
============
|
||||
|
||||
@@ -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** 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
|
||||
|
||||
- **Base** : Arch Linux (rolling release)
|
||||
- **Installeur** : Calamares (compilé depuis l'AUR, servi via un repo local pacman)
|
||||
- **Affichage live** : Xorg + Openbox, lancement automatique de Calamares
|
||||
- **Boot** : BIOS (syslinux) + UEFI (systemd-boot)
|
||||
- **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 + 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)
|
||||
- **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)
|
||||
- **Build** : Windows + WSL (Arch) ou directement depuis Arch
|
||||
|
||||
## Prérequis
|
||||
---
|
||||
|
||||
### Côté Windows
|
||||
- Windows 10/11
|
||||
- WSL 2 avec une distribution **Arch Linux** installée (`Arch`, `ArchLinux`, `ArchWSL`…)
|
||||
- Git Bash (pour exécuter les scripts depuis Windows)
|
||||
## Ce qu'il y a dans FWS
|
||||
|
||||
### Côté Arch (WSL ou natif)
|
||||
Les scripts installent automatiquement les paquets nécessaires (`archiso`, `base-devel`, `git`, `reflector`, `dos2unix`).
|
||||
### À l'installation
|
||||
- **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
|
||||
# 1. Préparation : compile Calamares depuis l'AUR, crée le repo local,
|
||||
# patche pacman.conf et configure les services systemd (Xorg + autostart).
|
||||
./setup-calamares.sh
|
||||
# 1. Initialiser le keyring (sinon pacman refuse tout install signé)
|
||||
pacman-key --init
|
||||
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
|
||||
```
|
||||
|
||||
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)
|
||||
2. `systemd` → autologin root sur `tty1`
|
||||
3. `xorg-start.service` → `Xorg :0`
|
||||
4. `calamares.service` → `DISPLAY=:0 calamares`
|
||||
5. **Fallback** : si les services échouent, `.zprofile` relance Xorg + Openbox + Calamares manuellement
|
||||
Depuis **Git Bash sur Windows** (à la racine du repo) :
|
||||
|
||||
```bash
|
||||
# Étape 1 : compilation des paquets AUR (winboat) + PKGBUILD locaux
|
||||
# (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
|
||||
|
||||
```bash
|
||||
./scripts/run_archiso.sh -i out/fws-*.iso # BIOS
|
||||
./scripts/run_archiso.sh -u -i out/fws-*.iso # UEFI
|
||||
./scripts/run_archiso.sh -i out/FWS-*.iso # BIOS
|
||||
./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
|
||||
|
||||
- **Paquets** : éditer `configs/releng/packages.x86_64`
|
||||
- **Overlay rootfs** : déposer les fichiers dans `configs/releng/airootfs/` ou `configs/baseline/airootfs/`
|
||||
- **Modules / séquence Calamares** : `configs/baseline/airootfs/etc/calamares/`
|
||||
- **Branding ISO** : `configs/releng/profiledef.sh` (`iso_name`, `iso_label`, `iso_publisher`…)
|
||||
- **Paquets du live** : `configs/releng/packages.x86_64`
|
||||
- **Paquets baseline** : `configs/baseline/packages.x86_64`
|
||||
- **Overlay rootfs** : `configs/releng/airootfs/` ou `configs/baseline/airootfs/`
|
||||
- **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
|
||||
|
||||
- **`pacman.conf introuvable`** : vérifier que `configs/releng/pacman.conf` existe.
|
||||
- **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.
|
||||
- **`mkarchiso` échoue sur un paquet AUR** : relancer `./setup-calamares.sh` pour reconstruire le repo local.
|
||||
| Symptôme | Cause / fix |
|
||||
|---|---|
|
||||
| `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`. |
|
||||
| `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**.
|
||||
|
||||
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
+383
@@ -0,0 +1,383 @@
|
||||
#!/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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
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"
|
||||
IN_WSL=1
|
||||
else
|
||||
echo -e "\e[36mLancement du processus de build dans WSL ($DISTRO_NAME) en tant que root...\e[0m"
|
||||
# ============================================================
|
||||
# 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.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
|
||||
|
||||
if [ -z "$IN_WSL" ]; then
|
||||
# ── Depuis Git Bash ──────────────────────────────────────
|
||||
SCRIPT_DIR_WIN="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -W)"
|
||||
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')
|
||||
# ============================================================
|
||||
# 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
|
||||
}
|
||||
|
||||
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
|
||||
set -e
|
||||
WORK_DIR="${WORK_DIR_WSL}"
|
||||
echo "==> Dossier de travail : \$WORK_DIR"
|
||||
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
|
||||
}
|
||||
|
||||
# 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..."
|
||||
pacman -Sy --noconfirm reflector || 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..."
|
||||
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/
|
||||
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/
|
||||
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 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
|
||||
ln -sf /usr/lib/systemd/system/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/multi-user.target.wants/ 2>/dev/null || echo " (aucun symlink)"
|
||||
|
||||
# Copie le repo local (calamares + winboat-bin)
|
||||
if ls "\$WORK_DIR/local-repo/"*.pkg.tar.zst &>/dev/null 2>&1; then
|
||||
echo "==> Copie du repo local Calamares..."
|
||||
# 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/
|
||||
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)
|
||||
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
|
||||
> "$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
|
||||
@@ -82,79 +257,31 @@ pacman -S --needed --noconfirm dos2unix
|
||||
find /tmp/fws-build/releng -type f -exec dos2unix {} + 2>/dev/null
|
||||
|
||||
echo "==> Lancement de mkarchiso..."
|
||||
mkdir -p "\$WORK_DIR/out"
|
||||
mkarchiso -v -w /tmp/fws-build/work -o "\$WORK_DIR/out" /tmp/fws-build/releng
|
||||
mkdir -p "$WORK_DIR/out"
|
||||
# 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 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
|
||||
|
||||
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; }
|
||||
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
|
||||
FINAL="$WORK_DIR/out/$(basename "${NEW_ISO%.iso}")-$(date +%H%M%S).iso"
|
||||
echo -e "\e[33m[!] '$DEST' 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 terminé ! ISO dans \$WORK_DIR/out"
|
||||
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..."
|
||||
mkdir -p "$WORK_DIR/out"
|
||||
mkarchiso -v -w /tmp/fws-build/work -o "$WORK_DIR/out" /tmp/fws-build/releng
|
||||
|
||||
echo "==> Nettoyage..."
|
||||
rm -rf /tmp/fws-build/work
|
||||
|
||||
echo "==> Build terminé ! L'ISO se trouve dans '$WORK_DIR/out'."
|
||||
fi
|
||||
|
||||
echo -e "\e[32mScript de build terminé avec succès.\e[0m"
|
||||
echo "==> Build terminé ! ISO : $FINAL"
|
||||
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
|
||||
# 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"
|
||||
|
||||
# Openbox en arrière-plan : gestionnaire de fenêtres pour l'installateur.
|
||||
openbox &
|
||||
sleep 1
|
||||
exec calamares
|
||||
_OB_PID=$!
|
||||
|
||||
# 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).
|
||||
# La session X exécute /root/.xinitrc qui lance Openbox + Calamares.
|
||||
if [[ "$(tty)" == "/dev/tty1" && -z "$DISPLAY" ]]; then
|
||||
# Démarrage automatique dans le live FWS uniquement.
|
||||
# Sur le système installé, /run/archiso n'existe pas, donc rien ne se lance.
|
||||
|
||||
# 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
|
||||
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)
|
||||
linux /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux
|
||||
initrd /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux.img
|
||||
options archisobasedir=%INSTALL_DIR% archisosearchuuid=%ARCHISO_UUID%
|
||||
title FWS install medium (%ARCH%, UEFI)
|
||||
sort-key 01
|
||||
linux /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux
|
||||
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
|
||||
# Objectif : système live bootable + installeur Calamares
|
||||
# fonctionnel + jeu minimal d'outils de rescue.
|
||||
# Objectif : système live bootable + installateur Anaconda
|
||||
# (migration depuis Calamares) + jeu minimal d'outils de rescue.
|
||||
# ============================================================
|
||||
|
||||
# --- Base système ---
|
||||
@@ -26,6 +26,7 @@ memtest86+
|
||||
memtest86+-efi
|
||||
|
||||
# --- Filesystems ---
|
||||
squashfs-tools
|
||||
btrfs-progs
|
||||
e2fsprogs
|
||||
exfatprogs
|
||||
@@ -60,6 +61,8 @@ wget
|
||||
zsh
|
||||
grml-zsh-config
|
||||
bash
|
||||
zenity
|
||||
zram-generator
|
||||
nano
|
||||
vim
|
||||
less
|
||||
@@ -77,6 +80,7 @@ pacman-contrib
|
||||
dmidecode
|
||||
usbutils
|
||||
pciutils
|
||||
firewalld
|
||||
fastfetch
|
||||
htop
|
||||
|
||||
@@ -84,21 +88,15 @@ htop
|
||||
alsa-utils
|
||||
sof-firmware
|
||||
|
||||
# --- Xorg + Openbox (pour Calamares) ---
|
||||
# --- Xorg + Openbox (session graphique de l'installateur) ---
|
||||
xorg-server
|
||||
xorg-xinit
|
||||
xorg-xrandr
|
||||
xorg-xsetroot
|
||||
openbox
|
||||
ttf-dejavu
|
||||
|
||||
# --- Calamares (fournis par fws-local) ---
|
||||
calamares
|
||||
kpmcore
|
||||
qt5-base
|
||||
qt5-svg
|
||||
qt5-webengine
|
||||
qt6-base
|
||||
# Terminal X : debug de l'installateur + entrée « Terminals » du menu Openbox.
|
||||
xterm
|
||||
|
||||
# --- Agents VM (pratique pour tester l'ISO) ---
|
||||
qemu-guest-agent
|
||||
@@ -107,3 +105,19 @@ open-vm-tools
|
||||
|
||||
# --- FWS (fws-local) ---
|
||||
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
|
||||
#
|
||||
|
||||
@@ -14,6 +14,31 @@ pacman_conf="pacman.conf"
|
||||
airootfs_image_type="squashfs"
|
||||
airootfs_image_tool_options=('-comp' 'xz' '-Xbcj' 'x86' '-b' '1M' '-Xdict-size' '1M')
|
||||
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=(
|
||||
["/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
|
||||
UI menu.c32
|
||||
MENU TITLE Arch Linux
|
||||
MENU CLEAR
|
||||
DEFAULT select
|
||||
|
||||
DEFAULT arch
|
||||
TIMEOUT 30
|
||||
LABEL select
|
||||
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:
|
||||
https://wiki.archlinux.org/title/Installation_guide
|
||||
Welcome to [38;2;23;147;209mFWS[0m live media.
|
||||
|
||||
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 mobile broadband (WWAN) modems, connect with the [35mmmcli[0m utility.
|
||||
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
|
||||
status=$?
|
||||
if [ "${status}" -eq 0 ]; then
|
||||
fastfetch
|
||||
# NB : ce fichier est SOURCÉ par le shell de login (zsh sur le live), pas exécuté
|
||||
# → le shebang est ignoré. En zsh « status » est une variable spéciale EN LECTURE
|
||||
# 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
|
||||
|
||||
@@ -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