1mod cli;
2mod commands;
3mod config;
4mod errors;
5mod project;
6pub mod runner;
7mod sdk;
8mod template;
9
10use std::ffi::OsString;
11use std::io::{self, Write};
12use std::path::Path;
13
14use clap::Parser;
15use cli::{Cli, Commands};
16pub use errors::{HarmonyAppError, OhosAppError, Result};
17use runner::RealCommandRunner;
18
19pub fn main_entry() -> Result<()> {
20 let args = std::env::args_os().collect::<Vec<_>>();
21 let cwd = std::env::current_dir().map_err(HarmonyAppError::from)?;
22 let mut runner = RealCommandRunner;
23 let mut stdout = io::stdout().lock();
24 run_with(args, &cwd, &mut runner, &mut stdout)
25}
26
27pub fn run_with<I, S, R, W>(args: I, cwd: &Path, runner: &mut R, stdout: &mut W) -> Result<()>
28where
29 I: IntoIterator<Item = S>,
30 S: Into<OsString>,
31 R: runner::CommandRunner,
32 W: Write,
33{
34 let cli = Cli::parse_from(normalize_args(args));
35 match &cli.command {
36 Commands::Init(command) => commands::init::run(command, cwd, runner, stdout),
37 Commands::Build(command) => commands::build::run(command, cwd, runner, stdout),
38 Commands::Package(command) => commands::package::run(command, cwd, runner, stdout),
39 }
40}
41
42fn normalize_args<I, S>(args: I) -> Vec<OsString>
43where
44 I: IntoIterator<Item = S>,
45 S: Into<OsString>,
46{
47 let mut args = args.into_iter().map(Into::into).collect::<Vec<_>>();
48 if matches!(
49 args.get(1).and_then(|value| value.to_str()),
50 Some("ohos-app" | "harmony-app")
51 ) {
52 args.remove(1);
53 }
54 args
55}
56
57#[cfg(test)]
58mod tests {
59 use super::normalize_args;
60 use std::ffi::OsString;
61
62 #[test]
63 fn strips_cargo_forwarded_subcommand_name() {
64 for subcommand in ["ohos-app", "harmony-app"] {
65 let args = normalize_args([
66 OsString::from("cargo-ohos-app"),
67 OsString::from(subcommand),
68 OsString::from("init"),
69 ]);
70 let rendered = args
71 .iter()
72 .map(|value| value.to_string_lossy().to_string())
73 .collect::<Vec<_>>();
74 assert_eq!(rendered, vec!["cargo-ohos-app", "init"]);
75 }
76 }
77}