electron-cli 0.3.0-alpha.3 → 0.3.0-alpha.5
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 +96 -1
- package/Cargo.toml +2 -1
- package/README.md +12 -3
- package/package.json +1 -1
- package/src/cli.rs +130 -0
- package/src/commands/make.rs +449 -0
- package/src/commands/mod.rs +2 -0
- package/src/commands/package.rs +41 -3
- package/src/commands/plan.rs +21 -2
- package/src/commands/publish.rs +432 -0
- package/src/main.rs +2 -0
|
@@ -0,0 +1,449 @@
|
|
|
1
|
+
use std::{
|
|
2
|
+
fs,
|
|
3
|
+
fs::File,
|
|
4
|
+
io::{self, BufWriter},
|
|
5
|
+
path::{Path, PathBuf},
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
use anyhow::{bail, Context, Result};
|
|
9
|
+
use camino::Utf8PathBuf;
|
|
10
|
+
use serde::Serialize;
|
|
11
|
+
use zip::{write::SimpleFileOptions, CompressionMethod, ZipWriter};
|
|
12
|
+
|
|
13
|
+
use crate::{
|
|
14
|
+
cli::{MakeArgs, PackageArgs},
|
|
15
|
+
commands::package::{self, PackageReport},
|
|
16
|
+
output,
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
#[derive(Debug, Serialize)]
|
|
20
|
+
pub(crate) struct MakeReport {
|
|
21
|
+
package: PackageReport,
|
|
22
|
+
target: String,
|
|
23
|
+
skip_package: bool,
|
|
24
|
+
dry_run: bool,
|
|
25
|
+
make_dir: Utf8PathBuf,
|
|
26
|
+
artifact: Utf8PathBuf,
|
|
27
|
+
artifact_size: Option<u64>,
|
|
28
|
+
status: MakeStatus,
|
|
29
|
+
warnings: Vec<String>,
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
#[derive(Debug, Serialize)]
|
|
33
|
+
#[serde(rename_all = "kebab-case")]
|
|
34
|
+
enum MakeStatus {
|
|
35
|
+
Planned,
|
|
36
|
+
Made,
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
pub fn run(args: MakeArgs) -> Result<()> {
|
|
40
|
+
let mut report = build_report(&args)?;
|
|
41
|
+
|
|
42
|
+
if args.dry_run {
|
|
43
|
+
return print_report(&report, args.json);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
execute_make(&mut report, &args)?;
|
|
47
|
+
report.mark_made()?;
|
|
48
|
+
|
|
49
|
+
print_report(&report, args.json)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
pub(crate) fn build_report(args: &MakeArgs) -> Result<MakeReport> {
|
|
53
|
+
let package_args = PackageArgs {
|
|
54
|
+
cwd: args.cwd.clone(),
|
|
55
|
+
out_dir: args.out_dir.clone(),
|
|
56
|
+
name: args.name.clone(),
|
|
57
|
+
platform: args.platform.clone(),
|
|
58
|
+
arch: args.arch.clone(),
|
|
59
|
+
force: args.force,
|
|
60
|
+
dry_run: false,
|
|
61
|
+
json: false,
|
|
62
|
+
};
|
|
63
|
+
let snapshot = crate::project::inspect(&package_args.cwd)?;
|
|
64
|
+
let package = package::build_report(snapshot, &package_args)?;
|
|
65
|
+
let make_dir = Path::new(package.output_dir().as_str())
|
|
66
|
+
.join("make")
|
|
67
|
+
.join(args.target.as_str())
|
|
68
|
+
.join(package.platform())
|
|
69
|
+
.join(package.arch());
|
|
70
|
+
let artifact = make_dir.join(format!(
|
|
71
|
+
"{}-{}-{}.zip",
|
|
72
|
+
package.artifact_stem(),
|
|
73
|
+
package.platform(),
|
|
74
|
+
package.arch()
|
|
75
|
+
));
|
|
76
|
+
|
|
77
|
+
let mut warnings = package.warnings().to_vec();
|
|
78
|
+
if args.skip_package && !Path::new(package.bundle_dir().as_str()).exists() {
|
|
79
|
+
warnings.push(format!(
|
|
80
|
+
"Package output does not exist: {}.",
|
|
81
|
+
package.bundle_dir()
|
|
82
|
+
));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if artifact.exists() && !args.force {
|
|
86
|
+
warnings.push(format!(
|
|
87
|
+
"Make artifact already exists: {}. Use --force to overwrite it.",
|
|
88
|
+
artifact.display()
|
|
89
|
+
));
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
Ok(MakeReport {
|
|
93
|
+
package,
|
|
94
|
+
target: args.target.as_str().to_string(),
|
|
95
|
+
skip_package: args.skip_package,
|
|
96
|
+
dry_run: args.dry_run,
|
|
97
|
+
make_dir: utf8_path(make_dir)?,
|
|
98
|
+
artifact: utf8_path(artifact)?,
|
|
99
|
+
artifact_size: None,
|
|
100
|
+
status: MakeStatus::Planned,
|
|
101
|
+
warnings,
|
|
102
|
+
})
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
pub(crate) fn execute_make(report: &mut MakeReport, args: &MakeArgs) -> Result<()> {
|
|
106
|
+
if !args.skip_package {
|
|
107
|
+
package::execute_package(&report.package, args.force)?;
|
|
108
|
+
report.package.mark_packaged();
|
|
109
|
+
} else if !Path::new(report.package.bundle_dir().as_str()).exists() {
|
|
110
|
+
bail!(
|
|
111
|
+
"Package output does not exist: {}. Run without --skip-package or run electron-cli package first.",
|
|
112
|
+
report.package.bundle_dir()
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
let artifact = Path::new(report.artifact.as_str());
|
|
117
|
+
if artifact.exists() {
|
|
118
|
+
if args.force {
|
|
119
|
+
fs::remove_file(artifact)
|
|
120
|
+
.with_context(|| format!("Could not remove {}", artifact.display()))?;
|
|
121
|
+
} else {
|
|
122
|
+
bail!(
|
|
123
|
+
"Make artifact already exists: {}. Use --force to overwrite it.",
|
|
124
|
+
artifact.display()
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
fs::create_dir_all(report.make_dir.as_str())
|
|
130
|
+
.with_context(|| format!("Could not create {}", report.make_dir))?;
|
|
131
|
+
write_zip_archive(Path::new(report.package.bundle_dir().as_str()), artifact)?;
|
|
132
|
+
|
|
133
|
+
Ok(())
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
fn print_report(report: &MakeReport, json: bool) -> Result<()> {
|
|
137
|
+
if json {
|
|
138
|
+
return output::json(report);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
println!("electron-cli make");
|
|
142
|
+
println!();
|
|
143
|
+
println!("Project");
|
|
144
|
+
println!(" root: {}", report.package.project().root);
|
|
145
|
+
match report.package.project().package_label() {
|
|
146
|
+
Some(label) => println!(" package: {label}"),
|
|
147
|
+
None => println!(" package: not found"),
|
|
148
|
+
}
|
|
149
|
+
println!(" app name: {}", report.package.app_name());
|
|
150
|
+
println!(
|
|
151
|
+
" target: {} {} {}",
|
|
152
|
+
report.target,
|
|
153
|
+
report.package.platform(),
|
|
154
|
+
report.package.arch()
|
|
155
|
+
);
|
|
156
|
+
println!(" status: {}", report.status.as_str());
|
|
157
|
+
|
|
158
|
+
println!();
|
|
159
|
+
println!("Artifact");
|
|
160
|
+
println!(" {}", report.artifact);
|
|
161
|
+
if let Some(size) = report.artifact_size {
|
|
162
|
+
println!(" size: {size} bytes");
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if !report.warnings.is_empty() {
|
|
166
|
+
println!();
|
|
167
|
+
println!("Warnings");
|
|
168
|
+
for warning in &report.warnings {
|
|
169
|
+
println!(" {warning}");
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
Ok(())
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
fn write_zip_archive(source: &Path, artifact: &Path) -> Result<()> {
|
|
177
|
+
if !source.exists() {
|
|
178
|
+
bail!("Package output does not exist: {}", source.display());
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
let parent = artifact
|
|
182
|
+
.parent()
|
|
183
|
+
.with_context(|| format!("Artifact path has no parent: {}", artifact.display()))?;
|
|
184
|
+
fs::create_dir_all(parent).with_context(|| format!("Could not create {}", parent.display()))?;
|
|
185
|
+
|
|
186
|
+
let file = File::create(artifact)
|
|
187
|
+
.with_context(|| format!("Could not create {}", artifact.display()))?;
|
|
188
|
+
let mut writer = ZipWriter::new(BufWriter::new(file));
|
|
189
|
+
let base = source
|
|
190
|
+
.parent()
|
|
191
|
+
.with_context(|| format!("Package output has no parent: {}", source.display()))?;
|
|
192
|
+
|
|
193
|
+
add_path_to_zip(source, base, &mut writer)?;
|
|
194
|
+
writer
|
|
195
|
+
.finish()
|
|
196
|
+
.with_context(|| format!("Could not finish {}", artifact.display()))?;
|
|
197
|
+
|
|
198
|
+
Ok(())
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
fn add_path_to_zip(
|
|
202
|
+
path: &Path,
|
|
203
|
+
base: &Path,
|
|
204
|
+
writer: &mut ZipWriter<BufWriter<File>>,
|
|
205
|
+
) -> Result<()> {
|
|
206
|
+
let metadata =
|
|
207
|
+
fs::metadata(path).with_context(|| format!("Could not stat {}", path.display()))?;
|
|
208
|
+
let relative_path = zip_relative_path(path, base)?;
|
|
209
|
+
|
|
210
|
+
if metadata.is_dir() {
|
|
211
|
+
if !relative_path.is_empty() {
|
|
212
|
+
let directory_name = format!("{relative_path}/");
|
|
213
|
+
writer
|
|
214
|
+
.add_directory(directory_name, directory_options(&metadata))
|
|
215
|
+
.with_context(|| format!("Could not add {} to archive", path.display()))?;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
let mut entries = fs::read_dir(path)
|
|
219
|
+
.with_context(|| format!("Could not read {}", path.display()))?
|
|
220
|
+
.collect::<Result<Vec<_>, io::Error>>()?;
|
|
221
|
+
entries.sort_by_key(|entry| entry.path());
|
|
222
|
+
|
|
223
|
+
for entry in entries {
|
|
224
|
+
add_path_to_zip(&entry.path(), base, writer)?;
|
|
225
|
+
}
|
|
226
|
+
} else {
|
|
227
|
+
writer
|
|
228
|
+
.start_file(relative_path, file_options(&metadata))
|
|
229
|
+
.with_context(|| format!("Could not add {} to archive", path.display()))?;
|
|
230
|
+
let mut file =
|
|
231
|
+
File::open(path).with_context(|| format!("Could not open {}", path.display()))?;
|
|
232
|
+
io::copy(&mut file, writer)
|
|
233
|
+
.with_context(|| format!("Could not write {} to archive", path.display()))?;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
Ok(())
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
fn zip_relative_path(path: &Path, base: &Path) -> Result<String> {
|
|
240
|
+
let relative = path.strip_prefix(base).with_context(|| {
|
|
241
|
+
format!(
|
|
242
|
+
"Could not make {} relative to {}",
|
|
243
|
+
path.display(),
|
|
244
|
+
base.display()
|
|
245
|
+
)
|
|
246
|
+
})?;
|
|
247
|
+
Ok(relative
|
|
248
|
+
.components()
|
|
249
|
+
.map(|component| component.as_os_str().to_string_lossy())
|
|
250
|
+
.collect::<Vec<_>>()
|
|
251
|
+
.join("/"))
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
fn file_options(metadata: &fs::Metadata) -> SimpleFileOptions {
|
|
255
|
+
SimpleFileOptions::default()
|
|
256
|
+
.compression_method(CompressionMethod::Deflated)
|
|
257
|
+
.unix_permissions(unix_mode(metadata, 0o644))
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
fn directory_options(metadata: &fs::Metadata) -> SimpleFileOptions {
|
|
261
|
+
SimpleFileOptions::default()
|
|
262
|
+
.compression_method(CompressionMethod::Stored)
|
|
263
|
+
.unix_permissions(unix_mode(metadata, 0o755))
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
#[cfg(unix)]
|
|
267
|
+
fn unix_mode(metadata: &fs::Metadata, _fallback: u32) -> u32 {
|
|
268
|
+
use std::os::unix::fs::PermissionsExt;
|
|
269
|
+
|
|
270
|
+
metadata.permissions().mode()
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
#[cfg(not(unix))]
|
|
274
|
+
fn unix_mode(_metadata: &fs::Metadata, fallback: u32) -> u32 {
|
|
275
|
+
fallback
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
fn utf8_path(path: PathBuf) -> Result<Utf8PathBuf> {
|
|
279
|
+
Utf8PathBuf::from_path_buf(path).map_err(|path| {
|
|
280
|
+
anyhow::anyhow!(
|
|
281
|
+
"Path contains invalid UTF-8 and cannot be represented in JSON: {}",
|
|
282
|
+
path.display()
|
|
283
|
+
)
|
|
284
|
+
})
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
impl MakeStatus {
|
|
288
|
+
fn as_str(&self) -> &'static str {
|
|
289
|
+
match self {
|
|
290
|
+
MakeStatus::Planned => "planned",
|
|
291
|
+
MakeStatus::Made => "made",
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
impl MakeReport {
|
|
297
|
+
pub(crate) fn mark_made(&mut self) -> Result<()> {
|
|
298
|
+
self.status = MakeStatus::Made;
|
|
299
|
+
self.artifact_size = Some(
|
|
300
|
+
fs::metadata(self.artifact.as_str())
|
|
301
|
+
.with_context(|| format!("Could not stat {}", self.artifact))?
|
|
302
|
+
.len(),
|
|
303
|
+
);
|
|
304
|
+
Ok(())
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
pub(crate) fn package(&self) -> &PackageReport {
|
|
308
|
+
&self.package
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
pub(crate) fn target(&self) -> &str {
|
|
312
|
+
&self.target
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
pub(crate) fn artifact(&self) -> &Utf8PathBuf {
|
|
316
|
+
&self.artifact
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
pub(crate) fn warnings(&self) -> &[String] {
|
|
320
|
+
&self.warnings
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
#[cfg(test)]
|
|
325
|
+
mod tests {
|
|
326
|
+
use super::*;
|
|
327
|
+
use zip::ZipArchive;
|
|
328
|
+
|
|
329
|
+
#[test]
|
|
330
|
+
fn builds_make_report_for_zip_target() {
|
|
331
|
+
let root = unique_temp_dir("plan");
|
|
332
|
+
write_package_json(&root);
|
|
333
|
+
write_app_file(&root);
|
|
334
|
+
write_fake_electron_dist(&root);
|
|
335
|
+
|
|
336
|
+
let args = MakeArgs {
|
|
337
|
+
cwd: root.clone(),
|
|
338
|
+
out_dir: PathBuf::from("out"),
|
|
339
|
+
name: None,
|
|
340
|
+
platform: None,
|
|
341
|
+
arch: None,
|
|
342
|
+
target: crate::cli::MakeTarget::Zip,
|
|
343
|
+
skip_package: false,
|
|
344
|
+
force: false,
|
|
345
|
+
dry_run: true,
|
|
346
|
+
json: true,
|
|
347
|
+
};
|
|
348
|
+
let report = build_report(&args).expect("report should build");
|
|
349
|
+
|
|
350
|
+
assert_eq!(report.target, "zip");
|
|
351
|
+
let expected_suffix = PathBuf::from("out")
|
|
352
|
+
.join("make")
|
|
353
|
+
.join("zip")
|
|
354
|
+
.join(report.package.platform())
|
|
355
|
+
.join(report.package.arch())
|
|
356
|
+
.join(format!(
|
|
357
|
+
"starter-app-{}-{}.zip",
|
|
358
|
+
report.package.platform(),
|
|
359
|
+
report.package.arch()
|
|
360
|
+
));
|
|
361
|
+
assert!(Path::new(report.artifact.as_str()).ends_with(expected_suffix));
|
|
362
|
+
|
|
363
|
+
let _ = fs::remove_dir_all(root);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
#[test]
|
|
367
|
+
fn makes_zip_artifact_after_packaging() {
|
|
368
|
+
let root = unique_temp_dir("execute");
|
|
369
|
+
write_package_json(&root);
|
|
370
|
+
write_app_file(&root);
|
|
371
|
+
write_fake_electron_dist(&root);
|
|
372
|
+
|
|
373
|
+
let args = MakeArgs {
|
|
374
|
+
cwd: root.clone(),
|
|
375
|
+
out_dir: PathBuf::from("out"),
|
|
376
|
+
name: None,
|
|
377
|
+
platform: None,
|
|
378
|
+
arch: None,
|
|
379
|
+
target: crate::cli::MakeTarget::Zip,
|
|
380
|
+
skip_package: false,
|
|
381
|
+
force: false,
|
|
382
|
+
dry_run: false,
|
|
383
|
+
json: false,
|
|
384
|
+
};
|
|
385
|
+
let mut report = build_report(&args).expect("report should build");
|
|
386
|
+
|
|
387
|
+
execute_make(&mut report, &args).expect("make should succeed");
|
|
388
|
+
|
|
389
|
+
let file = File::open(report.artifact.as_str()).expect("artifact should exist");
|
|
390
|
+
let mut archive = ZipArchive::new(file).expect("zip should open");
|
|
391
|
+
let app_entry = if report.package.platform() == "darwin" {
|
|
392
|
+
"starter-app.app/Contents/Resources/app/package.json".to_string()
|
|
393
|
+
} else {
|
|
394
|
+
format!(
|
|
395
|
+
"starter-app-{}-{}/resources/app/package.json",
|
|
396
|
+
report.package.platform(),
|
|
397
|
+
report.package.arch()
|
|
398
|
+
)
|
|
399
|
+
};
|
|
400
|
+
|
|
401
|
+
archive
|
|
402
|
+
.by_name(&app_entry)
|
|
403
|
+
.expect("app package.json should be archived");
|
|
404
|
+
|
|
405
|
+
let _ = fs::remove_dir_all(root);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
fn write_package_json(root: &Path) {
|
|
409
|
+
fs::write(
|
|
410
|
+
root.join("package.json"),
|
|
411
|
+
r#"{"name":"starter-app","version":"0.1.0","main":"src/main.js","devDependencies":{"electron":"30.0.0"}}"#,
|
|
412
|
+
)
|
|
413
|
+
.expect("package.json should be written");
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
fn write_app_file(root: &Path) {
|
|
417
|
+
fs::create_dir_all(root.join("src")).expect("src should be created");
|
|
418
|
+
fs::write(root.join("src/main.js"), "console.log('hello');")
|
|
419
|
+
.expect("main file should be written");
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
fn write_fake_electron_dist(root: &Path) {
|
|
423
|
+
let dist = root.join("node_modules/electron/dist");
|
|
424
|
+
if cfg!(target_os = "macos") {
|
|
425
|
+
let app = dist.join("Electron.app/Contents/MacOS");
|
|
426
|
+
fs::create_dir_all(&app).expect("fake macOS electron app should be created");
|
|
427
|
+
fs::write(app.join("Electron"), "").expect("fake macOS binary should be written");
|
|
428
|
+
} else if cfg!(target_os = "windows") {
|
|
429
|
+
fs::create_dir_all(&dist).expect("fake electron dist should be created");
|
|
430
|
+
fs::write(dist.join("electron.exe"), "").expect("fake exe should be written");
|
|
431
|
+
} else {
|
|
432
|
+
fs::create_dir_all(&dist).expect("fake electron dist should be created");
|
|
433
|
+
fs::write(dist.join("electron"), "").expect("fake binary should be written");
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
fn unique_temp_dir(label: &str) -> PathBuf {
|
|
438
|
+
let nanos = std::time::SystemTime::now()
|
|
439
|
+
.duration_since(std::time::UNIX_EPOCH)
|
|
440
|
+
.expect("clock should be after epoch")
|
|
441
|
+
.as_nanos();
|
|
442
|
+
let path = std::env::temp_dir().join(format!(
|
|
443
|
+
"electron-cli-make-{label}-{}-{nanos}",
|
|
444
|
+
std::process::id()
|
|
445
|
+
));
|
|
446
|
+
fs::create_dir_all(&path).expect("temp dir should be created");
|
|
447
|
+
path
|
|
448
|
+
}
|
|
449
|
+
}
|
package/src/commands/mod.rs
CHANGED
package/src/commands/package.rs
CHANGED
|
@@ -10,7 +10,7 @@ use serde::Serialize;
|
|
|
10
10
|
use crate::{cli::PackageArgs, output, project::ProjectSnapshot};
|
|
11
11
|
|
|
12
12
|
#[derive(Debug, Serialize)]
|
|
13
|
-
struct PackageReport {
|
|
13
|
+
pub(crate) struct PackageReport {
|
|
14
14
|
project: ProjectSnapshot,
|
|
15
15
|
app_name: String,
|
|
16
16
|
executable_name: String,
|
|
@@ -54,7 +54,7 @@ pub fn run(args: PackageArgs) -> Result<()> {
|
|
|
54
54
|
print_report(&report, args.json)
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
fn build_report(snapshot: ProjectSnapshot, args: &PackageArgs) -> Result<PackageReport> {
|
|
57
|
+
pub(crate) fn build_report(snapshot: ProjectSnapshot, args: &PackageArgs) -> Result<PackageReport> {
|
|
58
58
|
let root = Path::new(snapshot.root.as_str());
|
|
59
59
|
let platform = args.platform.clone().unwrap_or_else(current_platform);
|
|
60
60
|
let arch = args.arch.clone().unwrap_or_else(current_arch);
|
|
@@ -150,7 +150,7 @@ fn build_report(snapshot: ProjectSnapshot, args: &PackageArgs) -> Result<Package
|
|
|
150
150
|
})
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
-
fn execute_package(report: &PackageReport, force: bool) -> Result<()> {
|
|
153
|
+
pub(crate) fn execute_package(report: &PackageReport, force: bool) -> Result<()> {
|
|
154
154
|
if report.project.package_json.is_none() {
|
|
155
155
|
bail!("No package.json found. Run electron-cli package inside an Electron project.");
|
|
156
156
|
}
|
|
@@ -508,6 +508,44 @@ impl PackageStatus {
|
|
|
508
508
|
}
|
|
509
509
|
}
|
|
510
510
|
|
|
511
|
+
impl PackageReport {
|
|
512
|
+
pub(crate) fn project(&self) -> &ProjectSnapshot {
|
|
513
|
+
&self.project
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
pub(crate) fn mark_packaged(&mut self) {
|
|
517
|
+
self.status = PackageStatus::Packaged;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
pub(crate) fn app_name(&self) -> &str {
|
|
521
|
+
&self.app_name
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
pub(crate) fn artifact_stem(&self) -> String {
|
|
525
|
+
sanitize_artifact_name(&self.app_name)
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
pub(crate) fn platform(&self) -> &str {
|
|
529
|
+
&self.platform
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
pub(crate) fn arch(&self) -> &str {
|
|
533
|
+
&self.arch
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
pub(crate) fn output_dir(&self) -> &Utf8PathBuf {
|
|
537
|
+
&self.output_dir
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
pub(crate) fn bundle_dir(&self) -> &Utf8PathBuf {
|
|
541
|
+
&self.bundle_dir
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
pub(crate) fn warnings(&self) -> &[String] {
|
|
545
|
+
&self.warnings
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
|
|
511
549
|
#[cfg(test)]
|
|
512
550
|
mod tests {
|
|
513
551
|
use super::*;
|
package/src/commands/plan.rs
CHANGED
|
@@ -106,10 +106,18 @@ fn build_report(snapshot: &project::ProjectSnapshot) -> PlanReport {
|
|
|
106
106
|
);
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
-
if
|
|
109
|
+
if matches!(project_type, ProjectType::Electron) && snapshot.main.is_some() {
|
|
110
|
+
recommended_commands.insert("make".to_string(), "electron-cli make".to_string());
|
|
111
|
+
} else if let Some(script) = first_script(snapshot, &["make", "dist"]) {
|
|
110
112
|
recommended_commands.insert("make".to_string(), run_script(snapshot, script));
|
|
111
113
|
}
|
|
112
114
|
|
|
115
|
+
if matches!(project_type, ProjectType::Electron) && snapshot.main.is_some() {
|
|
116
|
+
recommended_commands.insert("publish".to_string(), "electron-cli publish".to_string());
|
|
117
|
+
} else if let Some(script) = first_script(snapshot, &["publish", "release"]) {
|
|
118
|
+
recommended_commands.insert("publish".to_string(), run_script(snapshot, script));
|
|
119
|
+
}
|
|
120
|
+
|
|
113
121
|
recommended_commands.insert(
|
|
114
122
|
"diagnostics".to_string(),
|
|
115
123
|
"electron-cli doctor --json".to_string(),
|
|
@@ -140,7 +148,7 @@ fn build_report(snapshot: &project::ProjectSnapshot) -> PlanReport {
|
|
|
140
148
|
if matches!(project_type, ProjectType::ElectronForge) {
|
|
141
149
|
notes.push("Electron Forge was detected; its scripts remain the safest path for Forge-managed apps today.".to_string());
|
|
142
150
|
} else if snapshot.electron_dependency.is_some() {
|
|
143
|
-
notes.push("Electron was detected without Forge; electron-cli can start and
|
|
151
|
+
notes.push("Electron was detected without Forge; electron-cli can start, package, make, and publish local artifacts directly.".to_string());
|
|
144
152
|
} else {
|
|
145
153
|
notes.push("This does not currently look like an Electron app.".to_string());
|
|
146
154
|
}
|
|
@@ -270,5 +278,16 @@ mod tests {
|
|
|
270
278
|
.map(String::as_str),
|
|
271
279
|
Some("electron-cli package")
|
|
272
280
|
);
|
|
281
|
+
assert_eq!(
|
|
282
|
+
report.recommended_commands.get("make").map(String::as_str),
|
|
283
|
+
Some("electron-cli make")
|
|
284
|
+
);
|
|
285
|
+
assert_eq!(
|
|
286
|
+
report
|
|
287
|
+
.recommended_commands
|
|
288
|
+
.get("publish")
|
|
289
|
+
.map(String::as_str),
|
|
290
|
+
Some("electron-cli publish")
|
|
291
|
+
);
|
|
273
292
|
}
|
|
274
293
|
}
|