electron-cli 0.3.0-alpha.8 → 0.3.0-alpha.9

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.
package/Cargo.lock CHANGED
@@ -64,6 +64,12 @@ version = "1.0.102"
64
64
  source = "registry+https://github.com/rust-lang/crates.io-index"
65
65
  checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
66
66
 
67
+ [[package]]
68
+ name = "autocfg"
69
+ version = "1.5.1"
70
+ source = "registry+https://github.com/rust-lang/crates.io-index"
71
+ checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
72
+
67
73
  [[package]]
68
74
  name = "base64"
69
75
  version = "0.22.1"
@@ -76,6 +82,15 @@ version = "2.11.1"
76
82
  source = "registry+https://github.com/rust-lang/crates.io-index"
77
83
  checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3"
78
84
 
85
+ [[package]]
86
+ name = "block-buffer"
87
+ version = "0.10.4"
88
+ source = "registry+https://github.com/rust-lang/crates.io-index"
89
+ checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
90
+ dependencies = [
91
+ "generic-array",
92
+ ]
93
+
79
94
  [[package]]
80
95
  name = "camino"
81
96
  version = "1.2.2"
@@ -122,7 +137,7 @@ dependencies = [
122
137
  "heck",
123
138
  "proc-macro2",
124
139
  "quote",
125
- "syn",
140
+ "syn 2.0.117",
126
141
  ]
127
142
 
128
143
  [[package]]
@@ -137,6 +152,15 @@ version = "1.0.5"
137
152
  source = "registry+https://github.com/rust-lang/crates.io-index"
138
153
  checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570"
139
154
 
155
+ [[package]]
156
+ name = "cpufeatures"
157
+ version = "0.2.17"
158
+ source = "registry+https://github.com/rust-lang/crates.io-index"
159
+ checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
160
+ dependencies = [
161
+ "libc",
162
+ ]
163
+
140
164
  [[package]]
141
165
  name = "crc32fast"
142
166
  version = "1.5.0"
@@ -146,6 +170,16 @@ dependencies = [
146
170
  "cfg-if",
147
171
  ]
148
172
 
173
+ [[package]]
174
+ name = "crypto-common"
175
+ version = "0.1.7"
176
+ source = "registry+https://github.com/rust-lang/crates.io-index"
177
+ checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
178
+ dependencies = [
179
+ "generic-array",
180
+ "typenum",
181
+ ]
182
+
149
183
  [[package]]
150
184
  name = "deranged"
151
185
  version = "0.5.8"
@@ -155,21 +189,60 @@ dependencies = [
155
189
  "powerfmt",
156
190
  ]
157
191
 
192
+ [[package]]
193
+ name = "digest"
194
+ version = "0.10.7"
195
+ source = "registry+https://github.com/rust-lang/crates.io-index"
196
+ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
197
+ dependencies = [
198
+ "block-buffer",
199
+ "crypto-common",
200
+ ]
201
+
202
+ [[package]]
203
+ name = "either"
204
+ version = "1.16.0"
205
+ source = "registry+https://github.com/rust-lang/crates.io-index"
206
+ checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e"
207
+
158
208
  [[package]]
159
209
  name = "electron-cli"
160
- version = "0.3.0-alpha.8"
210
+ version = "0.3.0-alpha.9"
161
211
  dependencies = [
162
212
  "anyhow",
163
213
  "camino",
164
214
  "clap",
165
215
  "flate2",
166
216
  "plist",
217
+ "rpm",
167
218
  "serde",
168
219
  "serde_json",
169
220
  "tar",
170
221
  "zip",
171
222
  ]
172
223
 
224
+ [[package]]
225
+ name = "enum-display-derive"
226
+ version = "0.1.1"
227
+ source = "registry+https://github.com/rust-lang/crates.io-index"
228
+ checksum = "f16ef37b2a9b242295d61a154ee91ae884afff6b8b933b486b12481cc58310ca"
229
+ dependencies = [
230
+ "proc-macro2",
231
+ "quote",
232
+ "syn 1.0.109",
233
+ ]
234
+
235
+ [[package]]
236
+ name = "enum-primitive-derive"
237
+ version = "0.3.0"
238
+ source = "registry+https://github.com/rust-lang/crates.io-index"
239
+ checksum = "ba7795da175654fe16979af73f81f26a8ea27638d8d9823d317016888a63dc4c"
240
+ dependencies = [
241
+ "num-traits",
242
+ "quote",
243
+ "syn 2.0.117",
244
+ ]
245
+
173
246
  [[package]]
174
247
  name = "equivalent"
175
248
  version = "1.0.2"
@@ -207,6 +280,16 @@ dependencies = [
207
280
  "zlib-rs",
208
281
  ]
209
282
 
283
+ [[package]]
284
+ name = "generic-array"
285
+ version = "0.14.7"
286
+ source = "registry+https://github.com/rust-lang/crates.io-index"
287
+ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
288
+ dependencies = [
289
+ "typenum",
290
+ "version_check",
291
+ ]
292
+
210
293
  [[package]]
211
294
  name = "hashbrown"
212
295
  version = "0.17.1"
@@ -219,6 +302,12 @@ version = "0.5.0"
219
302
  source = "registry+https://github.com/rust-lang/crates.io-index"
220
303
  checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
221
304
 
305
+ [[package]]
306
+ name = "hex"
307
+ version = "0.4.3"
308
+ source = "registry+https://github.com/rust-lang/crates.io-index"
309
+ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
310
+
222
311
  [[package]]
223
312
  name = "indexmap"
224
313
  version = "2.14.0"
@@ -235,12 +324,30 @@ version = "1.70.2"
235
324
  source = "registry+https://github.com/rust-lang/crates.io-index"
236
325
  checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695"
237
326
 
327
+ [[package]]
328
+ name = "itertools"
329
+ version = "0.14.0"
330
+ source = "registry+https://github.com/rust-lang/crates.io-index"
331
+ checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285"
332
+ dependencies = [
333
+ "either",
334
+ ]
335
+
238
336
  [[package]]
239
337
  name = "itoa"
240
338
  version = "1.0.18"
241
339
  source = "registry+https://github.com/rust-lang/crates.io-index"
242
340
  checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
243
341
 
342
+ [[package]]
343
+ name = "keccak"
344
+ version = "0.1.6"
345
+ source = "registry+https://github.com/rust-lang/crates.io-index"
346
+ checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653"
347
+ dependencies = [
348
+ "cpufeatures",
349
+ ]
350
+
244
351
  [[package]]
245
352
  name = "libc"
246
353
  version = "0.2.186"
@@ -253,6 +360,12 @@ version = "0.12.1"
253
360
  source = "registry+https://github.com/rust-lang/crates.io-index"
254
361
  checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"
255
362
 
363
+ [[package]]
364
+ name = "log"
365
+ version = "0.4.30"
366
+ source = "registry+https://github.com/rust-lang/crates.io-index"
367
+ checksum = "616ec5685824bcc94416c6d4a7a446eea774a31efd7062c8480ba6fd06d7a6e5"
368
+
256
369
  [[package]]
257
370
  name = "memchr"
258
371
  version = "2.8.1"
@@ -269,12 +382,105 @@ dependencies = [
269
382
  "simd-adler32",
270
383
  ]
271
384
 
385
+ [[package]]
386
+ name = "nom"
387
+ version = "8.0.0"
388
+ source = "registry+https://github.com/rust-lang/crates.io-index"
389
+ checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405"
390
+ dependencies = [
391
+ "memchr",
392
+ ]
393
+
394
+ [[package]]
395
+ name = "num"
396
+ version = "0.4.3"
397
+ source = "registry+https://github.com/rust-lang/crates.io-index"
398
+ checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23"
399
+ dependencies = [
400
+ "num-bigint",
401
+ "num-complex",
402
+ "num-integer",
403
+ "num-iter",
404
+ "num-rational",
405
+ "num-traits",
406
+ ]
407
+
408
+ [[package]]
409
+ name = "num-bigint"
410
+ version = "0.4.6"
411
+ source = "registry+https://github.com/rust-lang/crates.io-index"
412
+ checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
413
+ dependencies = [
414
+ "num-integer",
415
+ "num-traits",
416
+ ]
417
+
418
+ [[package]]
419
+ name = "num-complex"
420
+ version = "0.4.6"
421
+ source = "registry+https://github.com/rust-lang/crates.io-index"
422
+ checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
423
+ dependencies = [
424
+ "num-traits",
425
+ ]
426
+
272
427
  [[package]]
273
428
  name = "num-conv"
274
429
  version = "0.2.2"
275
430
  source = "registry+https://github.com/rust-lang/crates.io-index"
276
431
  checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441"
277
432
 
433
+ [[package]]
434
+ name = "num-derive"
435
+ version = "0.4.2"
436
+ source = "registry+https://github.com/rust-lang/crates.io-index"
437
+ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
438
+ dependencies = [
439
+ "proc-macro2",
440
+ "quote",
441
+ "syn 2.0.117",
442
+ ]
443
+
444
+ [[package]]
445
+ name = "num-integer"
446
+ version = "0.1.46"
447
+ source = "registry+https://github.com/rust-lang/crates.io-index"
448
+ checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
449
+ dependencies = [
450
+ "num-traits",
451
+ ]
452
+
453
+ [[package]]
454
+ name = "num-iter"
455
+ version = "0.1.45"
456
+ source = "registry+https://github.com/rust-lang/crates.io-index"
457
+ checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf"
458
+ dependencies = [
459
+ "autocfg",
460
+ "num-integer",
461
+ "num-traits",
462
+ ]
463
+
464
+ [[package]]
465
+ name = "num-rational"
466
+ version = "0.4.2"
467
+ source = "registry+https://github.com/rust-lang/crates.io-index"
468
+ checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"
469
+ dependencies = [
470
+ "num-bigint",
471
+ "num-integer",
472
+ "num-traits",
473
+ ]
474
+
475
+ [[package]]
476
+ name = "num-traits"
477
+ version = "0.2.19"
478
+ source = "registry+https://github.com/rust-lang/crates.io-index"
479
+ checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
480
+ dependencies = [
481
+ "autocfg",
482
+ ]
483
+
278
484
  [[package]]
279
485
  name = "once_cell_polyfill"
280
486
  version = "1.70.2"
@@ -327,6 +533,40 @@ dependencies = [
327
533
  "proc-macro2",
328
534
  ]
329
535
 
536
+ [[package]]
537
+ name = "rpm"
538
+ version = "0.24.0"
539
+ source = "registry+https://github.com/rust-lang/crates.io-index"
540
+ checksum = "a5f8c4a1267cbbad96d1e7bf080ca20c669df79f638ef4e6c5e05a38b5d32c96"
541
+ dependencies = [
542
+ "base64",
543
+ "bitflags",
544
+ "digest",
545
+ "enum-display-derive",
546
+ "enum-primitive-derive",
547
+ "flate2",
548
+ "hex",
549
+ "itertools",
550
+ "log",
551
+ "memchr",
552
+ "nom",
553
+ "num",
554
+ "num-derive",
555
+ "num-traits",
556
+ "rpm-version",
557
+ "sha1",
558
+ "sha2",
559
+ "sha3",
560
+ "thiserror",
561
+ "zeroize",
562
+ ]
563
+
564
+ [[package]]
565
+ name = "rpm-version"
566
+ version = "0.4.0"
567
+ source = "registry+https://github.com/rust-lang/crates.io-index"
568
+ checksum = "e9274efa3f2ce8fe60fd8ea005a49955f92ddd81643eb38084b8e2c6c507018f"
569
+
330
570
  [[package]]
331
571
  name = "rustix"
332
572
  version = "1.1.4"
@@ -367,7 +607,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
367
607
  dependencies = [
368
608
  "proc-macro2",
369
609
  "quote",
370
- "syn",
610
+ "syn 2.0.117",
371
611
  ]
372
612
 
373
613
  [[package]]
@@ -383,6 +623,38 @@ dependencies = [
383
623
  "zmij",
384
624
  ]
385
625
 
626
+ [[package]]
627
+ name = "sha1"
628
+ version = "0.10.6"
629
+ source = "registry+https://github.com/rust-lang/crates.io-index"
630
+ checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
631
+ dependencies = [
632
+ "cfg-if",
633
+ "cpufeatures",
634
+ "digest",
635
+ ]
636
+
637
+ [[package]]
638
+ name = "sha2"
639
+ version = "0.10.9"
640
+ source = "registry+https://github.com/rust-lang/crates.io-index"
641
+ checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
642
+ dependencies = [
643
+ "cfg-if",
644
+ "cpufeatures",
645
+ "digest",
646
+ ]
647
+
648
+ [[package]]
649
+ name = "sha3"
650
+ version = "0.10.9"
651
+ source = "registry+https://github.com/rust-lang/crates.io-index"
652
+ checksum = "77fd7028345d415a4034cf8777cd4f8ab1851274233b45f84e3d955502d93874"
653
+ dependencies = [
654
+ "digest",
655
+ "keccak",
656
+ ]
657
+
386
658
  [[package]]
387
659
  name = "simd-adler32"
388
660
  version = "0.3.9"
@@ -395,6 +667,17 @@ version = "0.11.1"
395
667
  source = "registry+https://github.com/rust-lang/crates.io-index"
396
668
  checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
397
669
 
670
+ [[package]]
671
+ name = "syn"
672
+ version = "1.0.109"
673
+ source = "registry+https://github.com/rust-lang/crates.io-index"
674
+ checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
675
+ dependencies = [
676
+ "proc-macro2",
677
+ "quote",
678
+ "unicode-ident",
679
+ ]
680
+
398
681
  [[package]]
399
682
  name = "syn"
400
683
  version = "2.0.117"
@@ -417,6 +700,26 @@ dependencies = [
417
700
  "xattr",
418
701
  ]
419
702
 
703
+ [[package]]
704
+ name = "thiserror"
705
+ version = "2.0.18"
706
+ source = "registry+https://github.com/rust-lang/crates.io-index"
707
+ checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
708
+ dependencies = [
709
+ "thiserror-impl",
710
+ ]
711
+
712
+ [[package]]
713
+ name = "thiserror-impl"
714
+ version = "2.0.18"
715
+ source = "registry+https://github.com/rust-lang/crates.io-index"
716
+ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
717
+ dependencies = [
718
+ "proc-macro2",
719
+ "quote",
720
+ "syn 2.0.117",
721
+ ]
722
+
420
723
  [[package]]
421
724
  name = "time"
422
725
  version = "0.3.47"
@@ -454,6 +757,12 @@ version = "0.12.3"
454
757
  source = "registry+https://github.com/rust-lang/crates.io-index"
455
758
  checksum = "8e28f89b80c87b8fb0cf04ab448d5dd0dd0ade2f8891bae878de66a75a28600e"
456
759
 
760
+ [[package]]
761
+ name = "typenum"
762
+ version = "1.20.1"
763
+ source = "registry+https://github.com/rust-lang/crates.io-index"
764
+ checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20"
765
+
457
766
  [[package]]
458
767
  name = "unicode-ident"
459
768
  version = "1.0.24"
@@ -466,6 +775,12 @@ version = "0.2.2"
466
775
  source = "registry+https://github.com/rust-lang/crates.io-index"
467
776
  checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
468
777
 
778
+ [[package]]
779
+ name = "version_check"
780
+ version = "0.9.5"
781
+ source = "registry+https://github.com/rust-lang/crates.io-index"
782
+ checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
783
+
469
784
  [[package]]
470
785
  name = "windows-link"
471
786
  version = "0.2.1"
@@ -491,6 +806,12 @@ dependencies = [
491
806
  "rustix",
492
807
  ]
493
808
 
809
+ [[package]]
810
+ name = "zeroize"
811
+ version = "1.8.2"
812
+ source = "registry+https://github.com/rust-lang/crates.io-index"
813
+ checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
814
+
494
815
  [[package]]
495
816
  name = "zip"
496
817
  version = "8.6.0"
package/Cargo.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "electron-cli"
3
- version = "0.3.0-alpha.8"
3
+ version = "0.3.0-alpha.9"
4
4
  edition = "2021"
5
5
  description = "Experimental Rust CLI for Electron project diagnostics and workflow automation"
6
6
  license = "MIT"
@@ -12,6 +12,7 @@ camino = { version = "1.1", features = ["serde1"] }
12
12
  clap = { version = "4.6", features = ["derive"] }
13
13
  flate2 = { version = "1.1", default-features = false, features = ["rust_backend"] }
14
14
  plist = "1"
15
+ rpm = { version = "0.24", default-features = false, features = ["payload", "gzip-compression"] }
15
16
  serde = { version = "1.0", features = ["derive"] }
16
17
  serde_json = "1.0"
17
18
  tar = "0.4"
package/README.md CHANGED
@@ -42,10 +42,10 @@ The Rust-native flow currently owns:
42
42
  - `init --template minimal`: writes a local Electron starter without Electron Forge.
43
43
  - `start`: launches the installed Electron runtime directly.
44
44
  - `package`: copies the installed Electron runtime, app files, installed production dependency closure, app metadata, macOS icon, and extra resources into a local app bundle for the current platform and architecture.
45
- - `make`: runs `package` and writes a distributable under `out/make/<target>/<platform>/<arch>/`; ZIP works on all platforms, and `--target deb` writes a Linux Debian package.
45
+ - `make`: runs `package` and writes a distributable under `out/make/<target>/<platform>/<arch>/`; ZIP works on all platforms, while `--target deb` and `--target rpm` write Linux packages.
46
46
  - `publish`: runs `make` and publishes the distributable to a local directory with a manifest.
47
47
 
48
- Remote publishers such as GitHub Releases are not implemented yet. DMG, RPM, Windows installers, Windows/Linux icon embedding, signing, and notarization are also still TODO.
48
+ Remote publishers such as GitHub Releases are not implemented yet. DMG, Windows installers, Windows/Linux icon embedding, signing, and notarization are also still TODO.
49
49
 
50
50
  Package metadata can be configured in `package.json`:
51
51
 
@@ -99,6 +99,7 @@ cargo run -- start --dry-run
99
99
  cargo run -- package --dry-run
100
100
  cargo run -- make --dry-run
101
101
  cargo run -- make --target deb --dry-run
102
+ cargo run -- make --target rpm --dry-run
102
103
  cargo run -- publish --dry-run
103
104
  ```
104
105
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "electron-cli",
3
- "version": "0.3.0-alpha.8",
3
+ "version": "0.3.0-alpha.9",
4
4
  "description": "Experimental Rust CLI for Electron project diagnostics and workflow automation",
5
5
  "license": "MIT",
6
6
  "repository": {
package/src/cli.rs CHANGED
@@ -264,6 +264,7 @@ impl PackageManager {
264
264
  #[value(rename_all = "lower")]
265
265
  pub enum MakeTarget {
266
266
  Deb,
267
+ Rpm,
267
268
  Zip,
268
269
  }
269
270
 
@@ -271,6 +272,7 @@ impl MakeTarget {
271
272
  pub fn as_str(self) -> &'static str {
272
273
  match self {
273
274
  MakeTarget::Deb => "deb",
275
+ MakeTarget::Rpm => "rpm",
274
276
  MakeTarget::Zip => "zip",
275
277
  }
276
278
  }
@@ -8,6 +8,7 @@ use std::{
8
8
  use anyhow::{bail, Context, Result};
9
9
  use camino::Utf8PathBuf;
10
10
  use flate2::{write::GzEncoder, Compression};
11
+ use rpm::{BuildConfig, CompressionType, FileOptions, PackageBuilder};
11
12
  use serde::Serialize;
12
13
  use tar::{Builder as TarBuilder, Header as TarHeader};
13
14
  use zip::{write::SimpleFileOptions, CompressionMethod, ZipWriter};
@@ -72,9 +73,10 @@ pub(crate) fn build_report(args: &MakeArgs) -> Result<MakeReport> {
72
73
  let artifact = make_artifact_path(&make_dir, &package, args.target);
73
74
 
74
75
  let mut warnings = package.warnings().to_vec();
75
- if args.target == MakeTarget::Deb && package.platform() != "linux" {
76
+ if matches!(args.target, MakeTarget::Deb | MakeTarget::Rpm) && package.platform() != "linux" {
76
77
  warnings.push(format!(
77
- "Deb maker only supports linux packages; target platform is {}.",
78
+ "{} maker only supports linux packages; target platform is {}.",
79
+ args.target.as_str(),
78
80
  package.platform()
79
81
  ));
80
82
  }
@@ -136,6 +138,7 @@ pub(crate) fn execute_make(report: &mut MakeReport, args: &MakeArgs) -> Result<(
136
138
  write_zip_archive(Path::new(report.package.bundle_dir().as_str()), artifact)?
137
139
  }
138
140
  MakeTarget::Deb => write_deb_archive(&report.package, artifact)?,
141
+ MakeTarget::Rpm => write_rpm_archive(&report.package, artifact)?,
139
142
  }
140
143
 
141
144
  Ok(())
@@ -195,6 +198,12 @@ fn make_artifact_path(make_dir: &Path, package: &PackageReport, target: MakeTarg
195
198
  debian_version(package.project().version.as_deref()),
196
199
  debian_arch(package.arch())
197
200
  )),
201
+ MakeTarget::Rpm => make_dir.join(format!(
202
+ "{}-{}-1.{}.rpm",
203
+ rpm_package_name(&package.artifact_stem()),
204
+ rpm_version(package.project().version.as_deref()),
205
+ rpm_arch(package.arch())
206
+ )),
198
207
  }
199
208
  }
200
209
 
@@ -337,6 +346,82 @@ fn write_deb_archive(package: &PackageReport, artifact: &Path) -> Result<()> {
337
346
  )
338
347
  }
339
348
 
349
+ fn write_rpm_archive(package: &PackageReport, artifact: &Path) -> Result<()> {
350
+ if package.platform() != "linux" {
351
+ bail!(
352
+ "RPM maker only supports linux packages. Requested {}.",
353
+ package.platform()
354
+ );
355
+ }
356
+
357
+ let source = Path::new(package.bundle_dir().as_str());
358
+ if !source.exists() {
359
+ bail!("Package output does not exist: {}", source.display());
360
+ }
361
+
362
+ let parent = artifact
363
+ .parent()
364
+ .with_context(|| format!("Artifact path has no parent: {}", artifact.display()))?;
365
+ fs::create_dir_all(parent).with_context(|| format!("Could not create {}", parent.display()))?;
366
+
367
+ let rpm_package = rpm_package_name(&package.artifact_stem());
368
+ let version = rpm_version(package.project().version.as_deref());
369
+ let arch = rpm_arch(package.arch());
370
+ let executable = format!("/opt/{rpm_package}/{}", package.executable_name());
371
+ let mut builder = PackageBuilder::new(
372
+ &rpm_package,
373
+ &version,
374
+ package
375
+ .project()
376
+ .license
377
+ .as_deref()
378
+ .unwrap_or("LicenseRef-unknown"),
379
+ &arch,
380
+ &single_line(package.app_name()),
381
+ );
382
+ builder
383
+ .using_config(
384
+ BuildConfig::v4()
385
+ .compression(CompressionType::Gzip)
386
+ .reserved_space(None)
387
+ .source_date(0),
388
+ )
389
+ .release("1")
390
+ .vendor("electron-cli")
391
+ .packager("electron-cli")
392
+ .description(format!(
393
+ "{} packaged by electron-cli.",
394
+ single_line(package.app_name())
395
+ ))
396
+ .default_file_attrs(None, Some("root".to_string()), Some("root".to_string()))
397
+ .default_dir_attrs(None, Some("root".to_string()), Some("root".to_string()));
398
+
399
+ for directory in [
400
+ "/opt",
401
+ "/usr",
402
+ "/usr/bin",
403
+ "/usr/share",
404
+ "/usr/share/applications",
405
+ ] {
406
+ builder.with_dir_entry(FileOptions::dir(directory).permissions(0o755))?;
407
+ }
408
+
409
+ builder.with_dir(source, format!("/opt/{rpm_package}"), |options| options)?;
410
+ builder.with_symlink(FileOptions::symlink(
411
+ format!("/usr/bin/{rpm_package}"),
412
+ &executable,
413
+ ))?;
414
+ builder.with_file_contents(
415
+ rpm_desktop_file(package, &rpm_package, &executable),
416
+ FileOptions::new(format!("/usr/share/applications/{rpm_package}.desktop"))
417
+ .permissions(0o644),
418
+ )?;
419
+
420
+ let rpm = builder.build()?;
421
+ rpm.write_file(artifact)
422
+ .with_context(|| format!("Could not write {}", artifact.display()))
423
+ }
424
+
340
425
  fn debian_control_file(
341
426
  package: &PackageReport,
342
427
  deb_package: &str,
@@ -397,6 +482,14 @@ fn append_deb_data_tar(
397
482
  }
398
483
 
399
484
  fn debian_desktop_file(package: &PackageReport, deb_package: &str, executable: &str) -> String {
485
+ desktop_file(package, deb_package, executable)
486
+ }
487
+
488
+ fn rpm_desktop_file(package: &PackageReport, rpm_package: &str, executable: &str) -> String {
489
+ desktop_file(package, rpm_package, executable)
490
+ }
491
+
492
+ fn desktop_file(package: &PackageReport, package_name: &str, executable: &str) -> String {
400
493
  format!(
401
494
  "[Desktop Entry]\n\
402
495
  Name={name}\n\
@@ -406,7 +499,7 @@ fn debian_desktop_file(package: &PackageReport, deb_package: &str, executable: &
406
499
  StartupWMClass={wm_class}\n\
407
500
  Categories=Utility;\n",
408
501
  name = single_line(package.app_name()),
409
- wm_class = deb_package
502
+ wm_class = package_name
410
503
  )
411
504
  }
412
505
 
@@ -603,6 +696,14 @@ fn directory_size(path: &Path) -> Result<u64> {
603
696
  }
604
697
 
605
698
  fn debian_package_name(name: &str) -> String {
699
+ package_name(name)
700
+ }
701
+
702
+ fn rpm_package_name(name: &str) -> String {
703
+ package_name(name)
704
+ }
705
+
706
+ fn package_name(name: &str) -> String {
606
707
  let mut package = name
607
708
  .to_ascii_lowercase()
608
709
  .chars()
@@ -646,6 +747,28 @@ fn debian_version(version: Option<&str>) -> String {
646
747
  }
647
748
  }
648
749
 
750
+ fn rpm_version(version: Option<&str>) -> String {
751
+ let version = version.unwrap_or("0.1.0");
752
+ let sanitized = version
753
+ .chars()
754
+ .map(|char| {
755
+ if char.is_ascii_alphanumeric() || matches!(char, '.' | '+' | '_' | '~') {
756
+ char
757
+ } else {
758
+ '_'
759
+ }
760
+ })
761
+ .collect::<String>()
762
+ .trim_matches(['_', '~'])
763
+ .to_string();
764
+
765
+ if sanitized.is_empty() {
766
+ "0.1.0".to_string()
767
+ } else {
768
+ sanitized
769
+ }
770
+ }
771
+
649
772
  fn debian_arch(arch: &str) -> String {
650
773
  match arch {
651
774
  "x64" => "amd64".to_string(),
@@ -655,6 +778,16 @@ fn debian_arch(arch: &str) -> String {
655
778
  }
656
779
  }
657
780
 
781
+ fn rpm_arch(arch: &str) -> String {
782
+ match arch {
783
+ "x64" => "x86_64".to_string(),
784
+ "arm64" => "aarch64".to_string(),
785
+ "ia32" => "i386".to_string(),
786
+ "armv7l" => "armv7hl".to_string(),
787
+ arch => arch.to_string(),
788
+ }
789
+ }
790
+
658
791
  fn single_line(value: &str) -> String {
659
792
  value
660
793
  .chars()
@@ -803,6 +936,40 @@ mod tests {
803
936
  let _ = fs::remove_dir_all(root);
804
937
  }
805
938
 
939
+ #[test]
940
+ fn builds_make_report_for_rpm_target() {
941
+ let root = unique_temp_dir("rpm-plan");
942
+ write_package_json(&root);
943
+ write_app_file(&root);
944
+ write_fake_electron_dist(&root);
945
+
946
+ let args = MakeArgs {
947
+ cwd: root.clone(),
948
+ out_dir: PathBuf::from("out"),
949
+ name: None,
950
+ platform: Some("linux".to_string()),
951
+ arch: Some("x64".to_string()),
952
+ target: crate::cli::MakeTarget::Rpm,
953
+ skip_package: false,
954
+ force: false,
955
+ dry_run: true,
956
+ json: true,
957
+ };
958
+ let report = build_report(&args).expect("report should build");
959
+
960
+ assert_eq!(report.target, "rpm");
961
+ assert!(Path::new(report.artifact.as_str()).ends_with(
962
+ PathBuf::from("out")
963
+ .join("make")
964
+ .join("rpm")
965
+ .join("linux")
966
+ .join("x64")
967
+ .join("starter-app-0.1.0-1.x86_64.rpm")
968
+ ));
969
+
970
+ let _ = fs::remove_dir_all(root);
971
+ }
972
+
806
973
  #[test]
807
974
  fn makes_zip_artifact_after_packaging() {
808
975
  let root = unique_temp_dir("execute");
@@ -904,6 +1071,65 @@ mod tests {
904
1071
  let _ = fs::remove_dir_all(root);
905
1072
  }
906
1073
 
1074
+ #[test]
1075
+ fn writes_rpm_archive_with_metadata_and_payload_entries() {
1076
+ let root = unique_temp_dir("rpm-archive");
1077
+ write_package_json(&root);
1078
+ write_app_file(&root);
1079
+ write_fake_electron_dist(&root);
1080
+
1081
+ let args = MakeArgs {
1082
+ cwd: root.clone(),
1083
+ out_dir: PathBuf::from("out"),
1084
+ name: None,
1085
+ platform: Some("linux".to_string()),
1086
+ arch: Some("x64".to_string()),
1087
+ target: crate::cli::MakeTarget::Rpm,
1088
+ skip_package: false,
1089
+ force: false,
1090
+ dry_run: true,
1091
+ json: true,
1092
+ };
1093
+ let report = build_report(&args).expect("report should build");
1094
+ let bundle_dir = Path::new(report.package.bundle_dir().as_str());
1095
+ fs::create_dir_all(bundle_dir.join("resources/app"))
1096
+ .expect("fake bundle resources should be created");
1097
+ fs::write(bundle_dir.join("starter-app"), "").expect("fake binary should be written");
1098
+ fs::write(bundle_dir.join("resources/app/package.json"), "{}")
1099
+ .expect("fake app package should be written");
1100
+
1101
+ write_rpm_archive(&report.package, Path::new(report.artifact.as_str()))
1102
+ .expect("rpm should be written");
1103
+
1104
+ let rpm = rpm::Package::open(report.artifact.as_str()).expect("rpm should parse");
1105
+ assert_eq!(
1106
+ rpm.metadata.get_name().expect("name should read"),
1107
+ "starter-app"
1108
+ );
1109
+ assert_eq!(
1110
+ rpm.metadata.get_version().expect("version should read"),
1111
+ "0.1.0"
1112
+ );
1113
+ assert_eq!(
1114
+ rpm.metadata.get_release().expect("release should read"),
1115
+ "1"
1116
+ );
1117
+ assert_eq!(rpm.metadata.get_arch().expect("arch should read"), "x86_64");
1118
+
1119
+ let paths = rpm
1120
+ .metadata
1121
+ .get_file_paths()
1122
+ .expect("file paths should read")
1123
+ .into_iter()
1124
+ .map(|path| path.to_string_lossy().to_string())
1125
+ .collect::<Vec<_>>();
1126
+ assert!(paths.contains(&"/opt/starter-app/resources/app/package.json".to_string()));
1127
+ assert!(paths.contains(&"/usr/share/applications/starter-app.desktop".to_string()));
1128
+ assert!(paths.contains(&"/usr/bin/starter-app".to_string()));
1129
+
1130
+ let _ = fs::remove_dir_all(root);
1131
+ }
1132
+
907
1133
  #[test]
908
1134
  fn makes_deb_artifact_after_packaging_on_linux() {
909
1135
  if !cfg!(target_os = "linux") {
@@ -936,10 +1162,42 @@ mod tests {
936
1162
  let _ = fs::remove_dir_all(root);
937
1163
  }
938
1164
 
1165
+ #[test]
1166
+ fn makes_rpm_artifact_after_packaging_on_linux() {
1167
+ if !cfg!(target_os = "linux") {
1168
+ return;
1169
+ }
1170
+
1171
+ let root = unique_temp_dir("rpm-execute");
1172
+ write_package_json(&root);
1173
+ write_app_file(&root);
1174
+ write_fake_electron_dist(&root);
1175
+
1176
+ let args = MakeArgs {
1177
+ cwd: root.clone(),
1178
+ out_dir: PathBuf::from("out"),
1179
+ name: None,
1180
+ platform: None,
1181
+ arch: None,
1182
+ target: crate::cli::MakeTarget::Rpm,
1183
+ skip_package: false,
1184
+ force: false,
1185
+ dry_run: false,
1186
+ json: false,
1187
+ };
1188
+ let mut report = build_report(&args).expect("report should build");
1189
+
1190
+ execute_make(&mut report, &args).expect("make should succeed");
1191
+
1192
+ assert!(Path::new(report.artifact.as_str()).exists());
1193
+
1194
+ let _ = fs::remove_dir_all(root);
1195
+ }
1196
+
939
1197
  fn write_package_json(root: &Path) {
940
1198
  fs::write(
941
1199
  root.join("package.json"),
942
- r#"{"name":"starter-app","version":"0.1.0","main":"src/main.js","devDependencies":{"electron":"30.0.0"}}"#,
1200
+ r#"{"name":"starter-app","version":"0.1.0","license":"MIT","main":"src/main.js","devDependencies":{"electron":"30.0.0"}}"#,
943
1201
  )
944
1202
  .expect("package.json should be written");
945
1203
  }
@@ -252,6 +252,7 @@ mod tests {
252
252
  package_json: Some(camino::Utf8PathBuf::from("/tmp/native-app/package.json")),
253
253
  name: Some("native-app".to_string()),
254
254
  version: Some("0.1.0".to_string()),
255
+ license: None,
255
256
  main: Some("src/main.js".to_string()),
256
257
  package_manager: Some("npm".to_string()),
257
258
  scripts: BTreeMap::new(),
package/src/project.rs CHANGED
@@ -15,6 +15,7 @@ pub struct ProjectSnapshot {
15
15
  pub package_json: Option<Utf8PathBuf>,
16
16
  pub name: Option<String>,
17
17
  pub version: Option<String>,
18
+ pub license: Option<String>,
18
19
  pub main: Option<String>,
19
20
  pub package_manager: Option<String>,
20
21
  pub scripts: BTreeMap<String, String>,
@@ -128,6 +129,11 @@ pub fn inspect(cwd: &Path) -> Result<ProjectSnapshot> {
128
129
  .and_then(|package| package.get("version"))
129
130
  .and_then(Value::as_str)
130
131
  .map(ToOwned::to_owned),
132
+ license: package_json
133
+ .as_ref()
134
+ .and_then(|package| package.get("license"))
135
+ .and_then(Value::as_str)
136
+ .map(ToOwned::to_owned),
131
137
  main: package_json
132
138
  .as_ref()
133
139
  .and_then(|package| package.get("main"))