Skip to main content

package/
lib.rs

1// Copyright 2024 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use anyhow::{Context as _, anyhow};
6use fidl_fuchsia_dash as fdash;
7use fuchsia_component::client::connect_to_protocol;
8use futures::stream::StreamExt as _;
9
10mod args;
11
12pub async fn exec() -> anyhow::Result<()> {
13    let args: args::PackageArgs = argh::from_env();
14
15    match args.subcommand {
16        crate::args::PackageSubcommand::Explore(args) => {
17            // TODO(https://fxbug.dev/296283299): Verify that the optional Launcher protocol is
18            // available before connecting.
19            let dash_launcher = connect_to_protocol::<fdash::LauncherMarker>()?;
20            // TODO(https://fxbug.dev/42077838): Use Stdout::raw when a command is not provided.
21            let stdout = socket_to_stdio::Stdout::buffered();
22
23            explore_cmd(args, dash_launcher, stdout).await
24        }
25    }
26}
27
28async fn explore_cmd(
29    args: crate::args::ExploreArgs,
30    dash_launcher: fdash::LauncherProxy,
31    stdout: socket_to_stdio::Stdout<'_>,
32) -> anyhow::Result<()> {
33    let crate::args::ExploreArgs { url, subpackages, tools, command, fuchsia_pkg_resolver } = args;
34    let (client, server) = fidl::Socket::create_stream();
35    let () = dash_launcher
36        .explore_package_over_socket2(
37            fuchsia_pkg_resolver,
38            &url,
39            &subpackages,
40            server,
41            &tools,
42            command.as_deref(),
43        )
44        .await
45        .context("fuchsia.dash/Launcher.ExplorePackageOverSocket2 fidl error")?
46        .map_err(|e| match e {
47            fdash::LauncherError::ResolveTargetPackage => {
48                anyhow!("No package found matching '{url}' {}.", subpackages.join(" "))
49            }
50            e => anyhow!("Error exploring package: {e:?}"),
51        })?;
52
53    let () = socket_to_stdio::connect_socket_to_stdio(client, stdout).await?;
54
55    let exit_code = wait_for_shell_exit(&dash_launcher).await?;
56    std::process::exit(exit_code);
57}
58
59async fn wait_for_shell_exit(launcher_proxy: &fdash::LauncherProxy) -> anyhow::Result<i32> {
60    match launcher_proxy.take_event_stream().next().await {
61        Some(Ok(fdash::LauncherEvent::OnTerminated { return_code })) => Ok(return_code),
62        Some(Err(e)) => Err(anyhow!("OnTerminated event error: {e:?}")),
63        None => Err(anyhow!("didn't receive an expected OnTerminated event")),
64    }
65}