penguins-eggs 25.12.15 → 26.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/.oclif.manifest.json +192 -192
  2. package/README.md +109 -489
  3. package/README.pdf +3174 -19913
  4. package/addons/eggs/theme/applications/install-system.desktop +3 -9
  5. package/assets/calamares/install-system.sh +23 -22
  6. package/assets/penguins-krill.desktop +5 -23
  7. package/dist/classes/distro.js +2 -1
  8. package/dist/classes/incubation/incubator.js +21 -8
  9. package/dist/classes/ovary.d/create-xdg-autostart.d.ts +3 -3
  10. package/dist/classes/ovary.d/create-xdg-autostart.js +139 -149
  11. package/dist/classes/ovary.d/luks-home-support-systemd.d.ts +12 -0
  12. package/dist/classes/ovary.d/luks-home-support-systemd.js +70 -0
  13. package/dist/classes/ovary.d/luks-home-support.d.ts +1 -0
  14. package/dist/classes/ovary.d/luks-home-support.js +101 -24
  15. package/dist/classes/ovary.d/produce.js +2 -2
  16. package/dist/classes/ovary.d/user-create-live.js +6 -1
  17. package/dist/classes/ovary.d/xorriso-command.js +11 -21
  18. package/dist/classes/utils.js +3 -0
  19. package/dist/classes/xdg.d.ts +6 -1
  20. package/dist/classes/xdg.js +119 -108
  21. package/dist/commands/export/appimage.js +2 -1
  22. package/dist/commands/export/pkg.js +16 -8
  23. package/dist/commands/update.js +1 -1
  24. package/dist/krill/classes/prepare.d/users.js +6 -6
  25. package/dist/krill/classes/prepare.js +6 -2
  26. package/dist/krill/classes/sequence.d/remove-homecrypt-hack.d.ts +13 -0
  27. package/dist/krill/classes/sequence.d/remove-homecrypt-hack.js +65 -0
  28. package/dist/krill/classes/sequence.d.ts +2 -0
  29. package/dist/krill/classes/sequence.js +7 -2
  30. package/dist/krill/components/users.js +4 -4
  31. package/dist/krill/lib/get_userfullname.js +1 -1
  32. package/dist/krill/lib/get_username.js +3 -3
  33. package/package.json +16 -15
  34. package/perrisbrewery/template/dependencies.yaml +3 -0
@@ -15,18 +15,23 @@ const __filename = fileURLToPath(import.meta.url);
15
15
  const __dirname = dirname(__filename);
16
16
  /**
17
17
  * Installa i file necessari per sbloccare home.img LUKS durante il boot
18
+ * Supporta sia Systemd (Debian/Ubuntu) che SysVinit (Devuan)
18
19
  */
19
20
  export function installHomecryptSupport(squashfsRoot, homeImgPath) {
20
21
  Utils.warning('installing encrypted home support...');
21
- // console.log("squashfsRoot:", squashfsRoot)
22
- // console.log("homeImgPath:", homeImgPath)
23
- // Leggi il template bash
22
+ // 1. PREPARAZIONE SCRIPT DI MONTAGGIO (Il "Motore")
24
23
  const templatePath = path.join(__dirname, '../../../scripts/mount-encrypted-home.sh');
25
24
  let bashScript = fs.readFileSync(templatePath, 'utf8');
26
- // Sostituisci il placeholder con il path reale
27
25
  bashScript = bashScript.replace('__HOME_IMG_PATH__', homeImgPath);
28
- // Systemd service
29
- const systemdService = `[Unit]
26
+ const mountScriptPath = path.join(squashfsRoot, 'usr/local/bin/mount-encrypted-home.sh');
27
+ fs.mkdirSync(path.dirname(mountScriptPath), { recursive: true });
28
+ fs.writeFileSync(mountScriptPath, bashScript);
29
+ fs.chmodSync(mountScriptPath, 0o755);
30
+ // ---------------------------------------------------------
31
+ // RAMO SYSTEMD (Invariato - funziona bene con i .service)
32
+ // ---------------------------------------------------------
33
+ if (Utils.isSystemd()) {
34
+ const systemdService = `[Unit]
30
35
  Description=Unlock and mount encrypted home.img
31
36
  DefaultDependencies=no
32
37
  After=systemd-udev-settle.service local-fs-pre.target
@@ -48,23 +53,95 @@ ExecStop=/bin/bash -c 'umount /home && cryptsetup close live-home'
48
53
  [Install]
49
54
  WantedBy=local-fs.target
50
55
  `;
51
- // Percorsi di destinazione
52
- const scriptPath = path.join(squashfsRoot, 'usr/local/bin/mount-encrypted-home.sh');
53
- const servicePath = path.join(squashfsRoot, 'etc/systemd/system/mount-encrypted-home.service');
54
- const symlinkDir = path.join(squashfsRoot, 'etc/systemd/system/local-fs.target.wants');
55
- const symlinkPath = path.join(symlinkDir, 'mount-encrypted-home.service');
56
- // Create dirs
57
- fs.mkdirSync(path.dirname(scriptPath), { recursive: true });
58
- fs.mkdirSync(path.dirname(servicePath), { recursive: true });
59
- fs.mkdirSync(symlinkDir, { recursive: true });
60
- // Scrivi lo script
61
- fs.writeFileSync(scriptPath, bashScript);
62
- fs.chmodSync(scriptPath, 0o755);
63
- // Scrivi il service
64
- fs.writeFileSync(servicePath, systemdService);
65
- // Crea il symlink per abilitare il service
66
- if (fs.existsSync(symlinkPath)) {
67
- fs.unlinkSync(symlinkPath);
56
+ const servicePath = path.join(squashfsRoot, 'etc/systemd/system/mount-encrypted-home.service');
57
+ const symlinkDir = path.join(squashfsRoot, 'etc/systemd/system/local-fs.target.wants');
58
+ const symlinkPath = path.join(symlinkDir, 'mount-encrypted-home.service');
59
+ fs.mkdirSync(path.dirname(servicePath), { recursive: true });
60
+ fs.mkdirSync(symlinkDir, { recursive: true });
61
+ fs.writeFileSync(servicePath, systemdService);
62
+ if (fs.existsSync(symlinkPath))
63
+ fs.unlinkSync(symlinkPath);
64
+ fs.symlinkSync('../mount-encrypted-home.service', symlinkPath);
65
+ }
66
+ // ---------------------------------------------------------
67
+ // RAMO SYSVINIT (DEVUAN) - METODO INITTAB HIJACK
68
+ // ---------------------------------------------------------
69
+ else if (Utils.isSysvinit()) {
70
+ Utils.warning('Configuring SysVinit via /etc/inittab hijacking (Persistent Method)...');
71
+ // A. Creiamo un Wrapper Script che fa: Sblocco -> Poi lancia Login
72
+ // Questo script prenderà il posto di 'agetty' su tty1
73
+ const wrapperScript = `#!/bin/sh
74
+ # Wrapper per sbloccare la home prima del login su TTY1
75
+
76
+ # 1. Setup ambiente minimale
77
+ export TERM=linux
78
+ export PATH=/sbin:/usr/sbin:/bin:/usr/bin
79
+
80
+ # 2. Pulizia schermo e stop Plymouth
81
+ clear
82
+ if [ -x /bin/plymouth ] && /bin/plymouth --ping; then
83
+ /bin/plymouth quit
84
+ fi
85
+
86
+ # 3. Attesa dispositivi (importante per USB)
87
+ echo "Waiting for devices..."
88
+ /sbin/udevadm settle
89
+
90
+ # 4. Esecuzione script di sblocco
91
+ echo "------------------------------------------------"
92
+ echo " CHECKING ENCRYPTED HOME STORAGE"
93
+ echo "------------------------------------------------"
94
+ /usr/local/bin/mount-encrypted-home.sh
95
+
96
+ # 5. Controllo esito (visivo)
97
+ if mountpoint -q /home; then
98
+ echo ">> Home mounted successfully."
99
+ sleep 1
100
+ else
101
+ echo ">> Home NOT mounted. Continuing unencrypted..."
102
+ sleep 2
103
+ fi
104
+
105
+ # 6. LANCIO DEL VERO LOGIN (Sostituisce questo processo)
106
+ # Nota: --noclear evita di cancellare i messaggi di errore precedenti
107
+ exec /sbin/agetty --noclear tty1 linux
108
+ `;
109
+ const wrapperPath = path.join(squashfsRoot, 'usr/local/bin/tty1-unlock-wrapper.sh');
110
+ fs.writeFileSync(wrapperPath, wrapperScript);
111
+ fs.chmodSync(wrapperPath, 0o755);
112
+ // B. Modifichiamo /etc/inittab per usare il nostro wrapper
113
+ const inittabPath = path.join(squashfsRoot, 'etc/inittab');
114
+ if (fs.existsSync(inittabPath)) {
115
+ let content = fs.readFileSync(inittabPath, 'utf8');
116
+ // La riga standard è solitamente: 1:2345:respawn:/sbin/getty 38400 tty1
117
+ // Oppure su Devuan: 1:2345:respawn:/sbin/agetty --noclear tty1 linux
118
+ // Cerchiamo qualsiasi riga che inizia con "1:" (tty1)
119
+ const regexTTY1 = /^1:.*$/m;
120
+ // La nuova riga che lancia il nostro wrapper invece di agetty diretto
121
+ const newLine = `1:2345:respawn:/usr/local/bin/tty1-unlock-wrapper.sh`;
122
+ if (regexTTY1.test(content)) {
123
+ content = content.replace(regexTTY1, newLine);
124
+ Utils.warning('Patched /etc/inittab to run home unlock on TTY1');
125
+ }
126
+ else {
127
+ // Se non la trova, la aggiungiamo in fondo (caso raro ma possibile)
128
+ content += `\n${newLine}\n`;
129
+ }
130
+ fs.writeFileSync(inittabPath, content);
131
+ }
132
+ // C. Pulizia vecchi tentativi (Rimuoviamo script init.d se presenti per evitare conflitti)
133
+ const badSymlinks = [
134
+ path.join(squashfsRoot, 'etc/rcS.d/S05mount-encrypted-home'),
135
+ path.join(squashfsRoot, 'etc/rcS.d/S20mount-encrypted-home'),
136
+ path.join(squashfsRoot, 'etc/rc2.d/S02mount-encrypted-home')
137
+ ];
138
+ badSymlinks.forEach(link => {
139
+ if (fs.existsSync(link))
140
+ fs.unlinkSync(link);
141
+ });
142
+ // Rimuoviamo anche lo script init.d stesso se esiste, non serve più
143
+ const initdFile = path.join(squashfsRoot, 'etc/init.d/mount-encrypted-home');
144
+ if (fs.existsSync(initdFile))
145
+ fs.unlinkSync(initdFile);
68
146
  }
69
- fs.symlinkSync('../mount-encrypted-home.service', symlinkPath);
70
147
  }
@@ -231,7 +231,7 @@ export async function produce(kernel = '', clone = false, homecrypt = false, ful
231
231
  // mistero della Fede
232
232
  await this.editLiveFs();
233
233
  /**
234
- * Autologin solse per non clone
234
+ * Autologin solo se per non clone
235
235
  */
236
236
  if (!(this.clone || this.homecrypt || this.fullcrypt)) {
237
237
  await this.usersRemove();
@@ -246,7 +246,7 @@ export async function produce(kernel = '', clone = false, homecrypt = false, ful
246
246
  }
247
247
  }
248
248
  /**
249
- * configurazione homecrytp
249
+ * configurazione homecrypt
250
250
  */
251
251
  if (this.homecrypt) {
252
252
  // Occorre forzare il login CLI
@@ -22,7 +22,7 @@ export default async function userCreateLive() {
22
22
  sysUsers.load();
23
23
  // 2. DEFINIZIONE UTENTE LIVE
24
24
  const username = this.settings.config.user_opt || 'live';
25
- const password = 'evolution'; // Password default live
25
+ const password = this.settings.config.user_opt_passwd || 'evolution';
26
26
  // Shell detection
27
27
  let shell = '/bin/bash';
28
28
  if (!fs.existsSync(path.join(target, 'bin/bash')) && fs.existsSync(path.join(target, 'bin/ash'))) {
@@ -92,4 +92,9 @@ export default async function userCreateLive() {
92
92
  }
93
93
  }
94
94
  console.log(`Live user '${username}' created successfully via SysUser Master.`);
95
+ // Importante: la password di root
96
+ const rootPassword = this.settings.config.root_passwd || 'evolution';
97
+ sysUsers.setPassword('root', rootPassword);
98
+ await sysUsers.save();
99
+ console.log(`Password of root updated successfully.`);
95
100
  }
@@ -43,11 +43,9 @@ export async function xorrisoCommand(clone = false, homecrypt = false, fullcrypt
43
43
  console.log('isoFilename:', this.settings.isoFilename);
44
44
  const output = this.settings.config.snapshot_mnt + this.settings.isoFilename;
45
45
  let command = '';
46
- // const appid = `-appid "${this.settings.distro.distroId}" `
47
- // const publisher = `-publisher "${this.settings.distro.distroId}/${this.settings.distro.codenameId}" `
48
- // const preparer = '-preparer "prepared by eggs <https://penguins-eggs.net>" '
46
+ // Isohybrid MBR: solo se non siamo su arm64 o riscv64
49
47
  let isoHybridMbr = '';
50
- if (this.settings.config.make_isohybrid) {
48
+ if (this.settings.config.make_isohybrid && process.arch !== 'arm64' && process.arch !== 'riscv64') {
51
49
  const bootloaders = Diversions.bootloaders(this.familyId);
52
50
  const isohybridFile = path.resolve(bootloaders, `ISOLINUX/isohdpfx.bin`);
53
51
  if (fs.existsSync(isohybridFile)) {
@@ -58,18 +56,15 @@ export async function xorrisoCommand(clone = false, homecrypt = false, fullcrypt
58
56
  process.exit();
59
57
  }
60
58
  }
61
- // su arm no isolinux
59
+ // Gestione parametri Bootloader x86
62
60
  let isolinuxBin = '';
63
61
  let isolinuxCat = '';
64
- let noemulboot = '';
65
- let bootloadsize = '';
66
- let bootinfotable = '';
67
- if (process.arch !== 'arm64') {
62
+ let x86_boot_params = '';
63
+ if (process.arch !== 'arm64' && process.arch !== 'riscv64') {
68
64
  isolinuxBin = `-b isolinux/isolinux.bin`;
69
65
  isolinuxCat = `-c isolinux/boot.cat`;
70
- noemulboot = '-no-emul-boot';
71
- bootloadsize = '-boot-load-size 4';
72
- bootinfotable = '-boot-info-table';
66
+ // Questi sono i parametri che su RISC-V causano il fallimento di xorriso
67
+ x86_boot_params = '-no-emul-boot -boot-load-size 4 -boot-info-table';
73
68
  }
74
69
  if (Pacman.packageIsInstalled('xorriso')) {
75
70
  let uefi_elToritoAltBoot = '';
@@ -82,14 +77,10 @@ export async function xorrisoCommand(clone = false, homecrypt = false, fullcrypt
82
77
  uefi_isohybridGptBasdat = '-isohybrid-gpt-basdat';
83
78
  uefi_noEmulBoot = '-no-emul-boot';
84
79
  }
85
- // <<< INIZIO BLOCCO AGGIUNTO >>>
86
- let luksPartitionParam = ''; // Inizializziamo la variabile per il parametro LUKS
80
+ let luksPartitionParam = '';
87
81
  if (fullcrypt) {
88
- // Costruiamo il percorso del file luks.img all'interno della directory di build
89
82
  const luksImagePath = path.join(this.settings.iso_work, 'live', this.luksMappedName);
90
- // Verifichiamo che il file esista prima di aggiungerlo
91
83
  if (fs.existsSync(luksImagePath)) {
92
- // Costruiamo il parametro per aggiungere la partizione 3
93
84
  luksPartitionParam = `-append_partition 3 0x80 ${luksImagePath}`;
94
85
  }
95
86
  else {
@@ -97,7 +88,7 @@ export async function xorrisoCommand(clone = false, homecrypt = false, fullcrypt
97
88
  process.exit();
98
89
  }
99
90
  }
100
- // <<< FINE BLOCCO AGGIUNTO >>>
91
+ // Il comando ora usa x86_boot_params che sarà vuoto su RISC-V
101
92
  command = `xorriso -as mkisofs \
102
93
  -J \
103
94
  -joliet-long \
@@ -108,13 +99,12 @@ export async function xorrisoCommand(clone = false, homecrypt = false, fullcrypt
108
99
  -V ${this.volid} \
109
100
  ${isolinuxBin} \
110
101
  ${isolinuxCat} \
111
- -no-emul-boot \
112
- -boot-load-size 4 \
113
- -boot-info-table \
102
+ ${x86_boot_params} \
114
103
  ${uefi_elToritoAltBoot} \
115
104
  ${uefi_e} \
116
105
  ${uefi_isohybridGptBasdat} \
117
106
  ${uefi_noEmulBoot} \
107
+ ${luksPartitionParam} \
118
108
  -o ${output} ${this.settings.iso_work}`;
119
109
  }
120
110
  return command;
@@ -333,6 +333,9 @@ export default class Utils {
333
333
  else if (process.arch === 'arm64') {
334
334
  arch = 'arm64';
335
335
  }
336
+ else if (process.arch === 'riscv64') {
337
+ arch = 'riscv64';
338
+ }
336
339
  return arch;
337
340
  }
338
341
  /**
@@ -16,7 +16,12 @@ export default class Xdg {
16
16
  * @param newuser
17
17
  * @param chroot
18
18
  */
19
- static autologin(olduser: string, newuser: string, chroot?: string): Promise<void>;
19
+ /**
20
+ * Forza l'autologin per il nuovo utente (live) su diversi Display Manager
21
+ * @param newuser Nome dell'utente live da loggare automaticamente
22
+ * @param chroot Percorso della root (default '/')
23
+ */
24
+ static autologin(newuser: string, chroot?: string): Promise<void>;
20
25
  /**
21
26
  *
22
27
  * @param user
@@ -25,128 +25,139 @@ export default class Xdg {
25
25
  * @param newuser
26
26
  * @param chroot
27
27
  */
28
- static async autologin(olduser, newuser, chroot = '/') {
29
- // console.log("old: " + olduser, "new: " + newuser, "chroot: " + chroot)
30
- if (Pacman.isInstalledGui()) {
31
- /**
32
- * SLIM & SLIMSKI
33
- */
34
- let slimConf = '';
35
- if (Pacman.packageIsInstalled('slim')) {
36
- slimConf = 'slim.conf';
37
- if (fs.existsSync('/etc/slim.local.conf')) {
38
- slimConf = 'slim.local.conf';
28
+ /**
29
+ * Forza l'autologin per il nuovo utente (live) su diversi Display Manager
30
+ * @param newuser Nome dell'utente live da loggare automaticamente
31
+ * @param chroot Percorso della root (default '/')
32
+ */
33
+ static async autologin(newuser, chroot = '/') {
34
+ if (!Pacman.isInstalledGui())
35
+ return;
36
+ /**
37
+ * SLIM & SLIMSKI
38
+ */
39
+ let slimConf = '';
40
+ if (Pacman.packageIsInstalled('slim')) {
41
+ slimConf = fs.existsSync(`${chroot}/etc/slim.local.conf`) ? 'slim.local.conf' : 'slim.conf';
42
+ }
43
+ else if (Pacman.packageIsInstalled('slimski')) {
44
+ slimConf = fs.existsSync(`${chroot}/etc/slimski.local.conf`) ? 'slimski.local.conf' : 'slimski.conf';
45
+ }
46
+ if (slimConf !== '') {
47
+ let content = fs.readFileSync(`${chroot}/etc/${slimConf}`, 'utf8');
48
+ content = content.replace(/^#?auto_login\s+.*/m, 'auto_login yes');
49
+ content = content.replace(/^#?default_user\s+.*/m, `default_user ${newuser}`);
50
+ fs.writeFileSync(`${chroot}/etc/${slimConf}`, content, 'utf8');
51
+ }
52
+ /**
53
+ * LIGHTDM
54
+ */
55
+ else if (Pacman.packageIsInstalled('lightdm')) {
56
+ const confPath = `${chroot}/etc/lightdm/lightdm.conf`;
57
+ if (fs.existsSync(confPath)) {
58
+ let content = fs.readFileSync(confPath, 'utf8');
59
+ if (!content.includes('[Seat:*]')) {
60
+ content += '\n[Seat:*]\n';
39
61
  }
62
+ // Rimuove eventuali righe esistenti e le aggiunge pulite sotto [Seat:*]
63
+ content = content.replace(/^autologin-user=.*/gm, '');
64
+ content = content.replace(/^autologin-user-timeout=.*/gm, '');
65
+ content = content.replace('[Seat:*]', `[Seat:*]\nautologin-user=${newuser}\nautologin-user-timeout=0`);
66
+ fs.writeFileSync(confPath, content.replace(/\n\n+/g, '\n\n'), 'utf8');
40
67
  }
41
- if (Pacman.packageIsInstalled('slimski')) {
42
- slimConf = 'slimski.conf';
43
- if (fs.existsSync('/etc/slimski.local.conf')) {
44
- slimConf = 'slimski.local.conf';
45
- }
68
+ }
69
+ /**
70
+ * LXDM
71
+ */
72
+ else if (Pacman.packageIsInstalled('lxdm')) {
73
+ const lxdmConf = `${chroot}/etc/lxdm/lxdm.conf`;
74
+ if (fs.existsSync(lxdmConf)) {
75
+ let content = fs.readFileSync(lxdmConf, 'utf8');
76
+ content = content.replace(/^#?\s*autologin=.*/m, `autologin=${newuser}`);
77
+ fs.writeFileSync(lxdmConf, content, 'utf8');
46
78
  }
47
- if (slimConf !== '') {
48
- let content = fs.readFileSync(`${chroot}/etc/${slimConf}`, 'utf8');
49
- const regexAutoLogin = new RegExp(`auto_login\\s*no`, 'g');
50
- content = content.replaceAll(regexAutoLogin, 'auto_login yes');
51
- const regexDefaultUser = new RegExp(`default_user\\s*${olduser}`, 'g');
52
- content = content.replace(regexDefaultUser, `default_user ${newuser}`);
53
- fs.writeFileSync(`${chroot}/etc/${slimConf}`, content, 'utf8');
54
- /**
55
- * LIGHTDM
56
- */
79
+ }
80
+ /**
81
+ * SDDM (Modern approach con file dedicato)
82
+ */
83
+ else if (Pacman.packageIsInstalled('sddm')) {
84
+ const confDir = `${chroot}/etc/sddm.conf.d`;
85
+ if (!fs.existsSync(confDir)) {
86
+ fs.mkdirSync(confDir, { recursive: true });
57
87
  }
58
- else if (Pacman.packageIsInstalled('lightdm')) {
59
- const dc = `${chroot}/etc/lightdm/`;
60
- const files = fs.readdirSync(dc);
61
- for (const elem of files) {
62
- const curFile = dc + elem;
63
- if (!fs.statSync(`/${curFile}`).isDirectory()) {
64
- let content = fs.readFileSync(curFile, 'utf8');
65
- const find = '[Seat:*]';
66
- if (content.includes(find)) {
67
- const regex = new RegExp(`autologin-user\\s*=\\s*${olduser}`, 'g'); // remove spaces
68
- content = content.replace(regex, `autologin-user=${newuser}`);
69
- fs.writeFileSync(curFile, content, 'utf8');
70
- }
71
- }
72
- }
88
+ let session = 'plasma';
89
+ if (Pacman.isInstalledWayland()) {
90
+ session = fs.existsSync(`${chroot}/usr/share/wayland-sessions/cosmic.desktop`) ? 'cosmic' : 'plasma-wayland';
73
91
  }
74
- else if (Pacman.packageIsInstalled('lxdm')) {
75
- let lxdmConf = '/etc/lxdm/lxdm.conf';
76
- if (fs.existsSync(lxdmConf)) {
77
- let content = fs.readFileSync(lxdmConf, 'utf8');
78
- const regex = new RegExp(`autologin\\s*=\\s*${olduser}`, 'g'); // remove spaces
79
- content = content.replace(regex, `autologin=${newuser}`);
80
- fs.writeFileSync(lxdmConf, content, 'utf8');
92
+ const content = `[Autologin]\nUser=${newuser}\nSession=${session}\n`;
93
+ fs.writeFileSync(`${confDir}/eggs-autologin.conf`, content, 'utf8');
94
+ }
95
+ /**
96
+ * GDM / GDM3 (Pop!_OS, Ubuntu, Debian)
97
+ */
98
+ else if (Pacman.packageIsInstalled('gdm') || Pacman.packageIsInstalled('gdm3')) {
99
+ let gdmFile = '';
100
+ const possiblePaths = [
101
+ `${chroot}/etc/gdm3/daemon.conf`,
102
+ `${chroot}/etc/gdm3/custom.conf`,
103
+ `${chroot}/etc/gdm/custom.conf`
104
+ ];
105
+ for (const p of possiblePaths) {
106
+ if (fs.existsSync(p)) {
107
+ gdmFile = p;
108
+ break;
81
109
  }
82
110
  }
83
- else if (Pacman.packageIsInstalled('sddm')) {
84
- /**
85
- * SDDM
86
- */
87
- let sddmChanged = false;
88
- const curFile = `${chroot}/etc/sddm.conf`;
89
- if (fs.existsSync(curFile)) {
90
- let content = fs.readFileSync(curFile, 'utf8');
91
- const find = '[Autologin]';
92
- if (content.includes(find)) {
93
- const regex = new RegExp(`User\\s*=\\s*${olduser}`, 'g'); // replace space
94
- content = content.replace(regex, `User=${newuser}`);
95
- fs.writeFileSync(curFile, content, 'utf8');
96
- sddmChanged = true;
97
- }
98
- }
99
- if (!sddmChanged) {
100
- const dc = `${chroot}/etc/sddm.conf.d/`;
101
- if (fs.existsSync(dc)) {
102
- const files = fs.readdirSync(dc);
103
- for (const elem of files) {
104
- const curFile = dc + elem;
105
- let content = fs.readFileSync(curFile, 'utf8');
106
- const find = '[Autologin]';
107
- if (content.includes(find)) {
108
- const regex = new RegExp(`User\\s*=\\s*${olduser}`, 'g'); // replace space
109
- content = content.replace(regex, `User=${newuser}`);
110
- fs.writeFileSync(curFile, content, 'utf8');
111
- sddmChanged = true;
112
- }
113
- }
114
- }
111
+ if (gdmFile) {
112
+ let content = fs.readFileSync(gdmFile, 'utf8');
113
+ if (!content.includes('[daemon]'))
114
+ content = "[daemon]\n" + content;
115
+ // Abilitazione chirurgica
116
+ if (content.match(/^#?AutomaticLoginEnable=.*/m)) {
117
+ content = content.replace(/^#?AutomaticLoginEnable=.*/m, 'AutomaticLoginEnable=true');
115
118
  }
116
- // sddm.conf don't exists, generate it
117
- if (!sddmChanged) {
118
- let session = 'plasma';
119
- if (Pacman.isInstalledWayland()) {
120
- session = 'plasma-wayland';
121
- }
122
- const content = `[Autologin]\nUser=${newuser}\nSession=${session}\n`;
123
- const curFile = `${chroot}/etc/sddm.conf`;
124
- fs.writeFileSync(curFile, content, 'utf8');
125
- }
126
- }
127
- else if (Pacman.packageIsInstalled('gdm') || Pacman.packageIsInstalled('gdm3')) {
128
- /**
129
- * GDM/GDM3
130
- * in manjaro è /etc/gdm/custom.conf
131
- */
132
- let gdmConf = `${chroot}/etc/gdm3`;
133
- if (Pacman.packageIsInstalled('gdm3')) {
134
- gdmConf = `${chroot}/etc/gdm3`;
119
+ else {
120
+ content = content.replace('[daemon]', '[daemon]\nAutomaticLoginEnable=true');
135
121
  }
136
- else if (Pacman.packageIsInstalled('gdm')) {
137
- gdmConf = `${chroot}/etc/gdm`;
122
+ if (content.match(/^#?AutomaticLogin=.*/m)) {
123
+ content = content.replace(/^#?AutomaticLogin=.*/m, `AutomaticLogin=${newuser}`);
138
124
  }
139
- if (fs.existsSync(`${gdmConf}/custom.conf`)) {
140
- gdmConf += '/custom.conf';
125
+ else {
126
+ content = content.replace('AutomaticLoginEnable=true', `AutomaticLoginEnable=true\nAutomaticLogin=${newuser}`);
141
127
  }
142
- else if (fs.existsSync(`${gdmConf}/daemon.conf`)) {
143
- gdmConf += '/daemon.conf';
128
+ fs.writeFileSync(gdmFile, content, 'utf8');
129
+ }
130
+ /**
131
+ * GREETD / COSMIC (Pop!_OS COSMIC)
132
+ */
133
+ }
134
+ else if (Pacman.packageIsInstalled('greetd')) {
135
+ const greetdPath = `${chroot}/etc/greetd/cosmic-greeter.toml`;
136
+ // Se esiste la configurazione specifica di COSMIC
137
+ if (fs.existsSync(greetdPath)) {
138
+ let content = fs.readFileSync(greetdPath, 'utf8');
139
+ // Se la sezione [initial_session] esiste già, la aggiorniamo, altrimenti la aggiungiamo
140
+ const initialSessionRegex = /\[initial_session\][^\[]*/;
141
+ const newInitialSession = `[initial_session]\ncommand = "start-cosmic"\nuser = "${newuser}"\n\n`;
142
+ if (initialSessionRegex.test(content)) {
143
+ content = content.replace(initialSessionRegex, newInitialSession);
144
144
  }
145
145
  else {
146
- gdmConf = `}/etc/${gdmConf}/custom.conf`;
146
+ // La aggiungiamo in testa o dopo la sezione general
147
+ content = newInitialSession + content;
148
+ }
149
+ fs.writeFileSync(greetdPath, content, 'utf8');
150
+ }
151
+ // Fallback per greetd standard (config.toml) se non è COSMIC specifico
152
+ else if (fs.existsSync(`${chroot}/etc/greetd/config.toml`)) {
153
+ const configPath = `${chroot}/etc/greetd/config.toml`;
154
+ let content = fs.readFileSync(configPath, 'utf8');
155
+ // Configurazione per il login automatico su greetd generico
156
+ const autologinConfig = `[initial_session]\ncommand = "start-cosmic"\nuser = "${newuser}"\n`;
157
+ if (!content.includes('[initial_session]')) {
158
+ content = autologinConfig + content;
159
+ fs.writeFileSync(configPath, content, 'utf8');
147
160
  }
148
- const content = `[daemon]\nAutomaticLoginEnable=true\nAutomaticLogin=${newuser}\n`;
149
- Utils.write(gdmConf, content);
150
161
  }
151
162
  }
152
163
  }
@@ -46,7 +46,8 @@ export default class ExportAppimage extends Command {
46
46
  const remoteMountpoint = `/tmp/eggs-${(Math.random() + 1).toString(36).slice(7)}`;
47
47
  let localPath = "$HOME/penguins-eggs";
48
48
  let remotePath = "/eggs/";
49
- let filter = `penguins-eggs-[0-9][0-9].[0-9]*.[0-9]*-*.AppImage`;
49
+ let filter = `penguins-eggs-+([0-9.])-*.AppImage`;
50
+ //let filter = `penguins-eggs-[0-9][0-9].[0-9]*.[0-9]*-*.AppImage`
50
51
  let cmd = `#!/bin/bash\n`;
51
52
  cmd += `set -e\n`;
52
53
  cmd += 'shopt -s extglob\n';
@@ -63,7 +63,8 @@ export default class ExportPkg extends Command {
63
63
  Utils.warning(`exporting Alpine APK packages`);
64
64
  localPath = `/home/${this.user}/packages/aports/${arch}`;
65
65
  remotePath = `${this.Tu.config.remotePathPackages}/alpine/${arch}`;
66
- filter = `penguins-eggs-*[0-9][0-9].@([0-9]|[0-1][0-9]).@([0-9]|[0-3][0-9])-*.apk`;
66
+ filter = `penguins-eggs-+([0-9.])-*.apk`;
67
+ // filter = `penguins-eggs-*[0-9][0-9].@([0-9]|[0-1][0-9]).@([0-9]|[0-3][0-9])-*.apk`
67
68
  /**
68
69
  * Arch/Manjaro
69
70
  */
@@ -76,7 +77,8 @@ export default class ExportPkg extends Command {
76
77
  Utils.warning(`exporting Manjaro .pkg.tar.zst packages`);
77
78
  localPath = `/home/${this.user}/penguins-packs/manjaro/penguins-eggs`;
78
79
  remotePath = this.Tu.config.remotePathPackages + "/manjaro";
79
- filter = `penguins-eggs-[0-9][0-9].@([0-9]|[0-1][0-9]).@([0-9]|[0-3][0-9])-*-any.pkg.tar.*`;
80
+ filter = `penguins-eggs-+([0-9.])-*-any.pkg.tar.*`;
81
+ // filter = `penguins-eggs-[0-9][0-9].@([0-9]|[0-1][0-9]).@([0-9]|[0-3][0-9])-*-any.pkg.tar.*`
80
82
  /**
81
83
  * Arch
82
84
  */
@@ -85,7 +87,8 @@ export default class ExportPkg extends Command {
85
87
  Utils.warning(`exporting Arch .pkg.tar.zst packages`);
86
88
  localPath = `/home/${this.user}/penguins-packs/aur/penguins-eggs`;
87
89
  remotePath = this.Tu.config.remotePathPackages + "/aur";
88
- filter = `penguins-eggs-[0-9][0-9].@([0-9]|[0-1][0-9]).@([0-9]|[0-3][0-9])-*-any.pkg.tar.zst`;
90
+ filter = `penguins-eggs-+([0-9.])-*-any.pkg.tar.zst`;
91
+ //filter = `penguins-eggs-[0-9][0-9].@([0-9]|[0-1][0-9]).@([0-9]|[0-3][0-9])-*-any.pkg.tar.zst`
89
92
  }
90
93
  /**
91
94
  * Debian
@@ -99,7 +102,8 @@ export default class ExportPkg extends Command {
99
102
  if (this.all) {
100
103
  arch = '*';
101
104
  }
102
- filter = `penguins-eggs_[0-9][0-9].@([0-9]|[0-1][0-9]).@([0-9]|[0-3][0-9])-*_${arch}.deb`;
105
+ //filter = `penguins-eggs_[0-9][0-9].@([0-9]|[0-1][0-9]).@([0-9]|[0-3][0-9])-*_${arch}.deb`
106
+ filter = `penguins-eggs-+([0-9.])-*${arch}.deb`;
103
107
  /**
104
108
  * fedora
105
109
  */
@@ -111,12 +115,13 @@ export default class ExportPkg extends Command {
111
115
  if (distro.distroId !== 'Fedora') {
112
116
  repo = 'el9';
113
117
  ftype = `el?`;
114
- warning = `exporting Almalinux/Rocky RPM packages`;
118
+ warning = `exporting Almalinux/RHEL/Rocky RPM packages`;
115
119
  }
116
- filter = `penguins-eggs-[0-9][0-9].[0-9]*.[0-9]*-*.${ftype}.x86_64.rpm`;
117
120
  Utils.warning(warning);
118
121
  localPath = `/home/${this.user}/rpmbuild/RPMS/x86_64`;
119
122
  remotePath = this.Tu.config.remotePathPackages + `/` + repo;
123
+ filter = `penguins-eggs-+([0-9.])-*.${ftype}.x86_64.rpm`;
124
+ //filter = `penguins-eggs-[0-9][0-9].[0-9]*.[0-9]*-*.${ftype}.x86_64.rpm`
120
125
  /**
121
126
  * openmamba
122
127
  */
@@ -125,7 +130,8 @@ export default class ExportPkg extends Command {
125
130
  Utils.warning(`exporting Openmamba RPM packages`);
126
131
  localPath = `/home/${this.user}/rpmbuild/RPMS/x86_64`;
127
132
  remotePath = this.Tu.config.remotePathPackages + "/openmamba";
128
- filter = `penguins-eggs-[0-9][0-9].@([0-9]|[0-1][0-9]).@([0-9]|[0-3][0-9])-*mamba.*.rpm`;
133
+ filter = `penguins-eggs-+([0-9.])-*.mamba.*.rpm`;
134
+ // filter = `penguins-eggs-[0-9][0-9].@([0-9]|[0-1][0-9]).@([0-9]|[0-3][0-9])-*mamba.*.rpm`
129
135
  /**
130
136
  * opensuse
131
137
  */
@@ -134,7 +140,8 @@ export default class ExportPkg extends Command {
134
140
  Utils.warning(`exporting OpenSuSE RPM packages`);
135
141
  localPath = `/home/${this.user}/rpmbuild/RPMS/x86_64`;
136
142
  remotePath = this.Tu.config.remotePathPackages + "/opensuse";
137
- filter = `penguins-eggs-[0-9][0-9].[0-9]*.[0-9]*-*.opensuse.x86_64.rpm`;
143
+ filter = `penguins-eggs-+([0-9.])-*.rpm`;
144
+ // filter = `penguins-eggs-[0-9][0-9].[0-9]*.[0-9]*-*.opensuse.x86_64.rpm`
138
145
  }
139
146
  let cmd = `#!/bin/bash\n`;
140
147
  cmd += `set -e\n`;
@@ -154,6 +161,7 @@ export default class ExportPkg extends Command {
154
161
  cmd += `rm -f ${remoteMountpoint}/${archDest}${filter}\n`;
155
162
  }
156
163
  cmd += `# Export packages\n`;
164
+ cmd += `shopt -s extglob\n`;
157
165
  cmd += `cp ${localPath}/${filter} ${remoteMountpoint}\n`;
158
166
  cmd += 'sync\n';
159
167
  cmd += `\n`;
@@ -167,7 +167,7 @@ export default class Update extends Command {
167
167
  }
168
168
  else if (this.distro.familyId === "debian") {
169
169
  repo = 'debs';
170
- filter = `penguins-eggs_??.*.*-?_${Utils.uefiArch()}.deb`;
170
+ filter = `penguins-eggs-??.*.*-?_${Utils.uefiArch()}.deb`;
171
171
  copy = `scp ${Tu.config.remoteUser}@${Tu.config.remoteHost}:${Tu.config.remotePathPackages}/${repo}/${filter} /tmp`;
172
172
  install = `apt reinstall /tmp/${filter}`;
173
173
  /**