iquery/commands/
show.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use crate::commands::types::*;
use crate::commands::utils;
use crate::text_formatter;
use crate::types::Error;
use argh::{ArgsInfo, FromArgs};
use derivative::Derivative;
use diagnostics_data::{Inspect, InspectData};
use serde::Serialize;
use std::cmp::Ordering;
use std::fmt;
use std::ops::Deref;

#[derive(Derivative, Serialize, PartialEq)]
#[derivative(Eq)]
pub struct ShowResultItem(InspectData);

impl Deref for ShowResultItem {
    type Target = InspectData;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl PartialOrd for ShowResultItem {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl Ord for ShowResultItem {
    fn cmp(&self, other: &Self) -> Ordering {
        self.moniker.cmp(&other.moniker).then_with(|| {
            let this_name = self.metadata.name.as_ref();
            let other_name = other.metadata.name.as_ref();
            this_name.cmp(other_name)
        })
    }
}

#[derive(Serialize)]
pub struct ShowResult(Vec<ShowResultItem>);

impl fmt::Display for ShowResult {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        for item in self.0.iter() {
            text_formatter::output_schema(f, &item.0)?;
        }
        Ok(())
    }
}

/// Prints the inspect hierarchies that match the given selectors.
/// See https://fuchsia.dev/fuchsia-src/development/diagnostics/inspect#userspace_tools for more.
#[derive(ArgsInfo, FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "show")]
pub struct ShowCommand {
    #[argh(positional)]
    /// queries for accessing Inspect data.
    /// If no selectors are provided, Inspect data for the whole system will be returned.
    pub selectors: Vec<String>,

    #[argh(option)]
    /// DEPRECATED: use `--component` instead.
    pub manifest: Option<String>,

    #[argh(option)]
    /// a fuzzy-search query. May include URL, moniker, or manifest fragments. No selector-escaping
    /// for moniker is needed in this query. Selectors following --component should omit the
    /// component selector, as they will be spliced together by the tool with the correct escaping.
    pub component: Option<String>,

    #[argh(option)]
    /// A string specifying what `fuchsia.diagnostics.ArchiveAccessor` to connect to.
    /// This can be copied from the output of `ffx inspect list-accessors`.
    /// The selector will be in the form of:
    /// <moniker>:fuchsia.diagnostics.ArchiveAccessorName
    pub accessor: Option<String>,

    #[argh(option)]
    /// specifies a tree published by a component by name.
    ///
    /// If a selector is also provided, the specified name will be added to the selector.
    pub name: Option<String>,
}

impl Command for ShowCommand {
    type Result = ShowResult;

    async fn execute<P: DiagnosticsProvider>(self, provider: &P) -> Result<Self::Result, Error> {
        if self.manifest.is_some() {
            panic!("ERROR: option `--manifest` is deprecated, please use `--component` instead");
        }
        let mut selectors = if let Some(component) = self.component {
            utils::process_component_query_with_partial_selectors(
                component,
                self.selectors.into_iter(),
                provider,
            )
            .await?
        } else if let Some(manifest) = self.manifest {
            utils::get_selectors_for_manifest(
                manifest,
                self.selectors,
                self.accessor.clone(),
                provider,
            )
            .await?
        } else {
            utils::process_fuzzy_inputs(self.selectors, provider).await?
        };

        utils::ensure_tree_field_is_set(&mut selectors, self.name)?;
        let inspect_data_iter =
            provider.snapshot::<Inspect>(self.accessor.as_deref(), selectors).await?.into_iter();

        let mut results = inspect_data_iter
            .map(|mut d: InspectData| {
                if let Some(hierarchy) = &mut d.payload {
                    hierarchy.sort();
                }
                ShowResultItem(d)
            })
            .collect::<Vec<_>>();

        results.sort();
        Ok(ShowResult(results))
    }
}