rafia_stpa_cli/
main.rs

1// *****************************************************************************
2// Copyright (c) 2025 Codethink
3//
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// http://www.eclipse.org/legal/epl-2.0.
7//
8// This Source Code may also be made available under the following Secondary
9// Licenses when the conditions for such availability set forth in the Eclipse
10// Public License, v. 2.0 are satisfied: GNU General Public License, version 2
11// with the GNU Classpath Exception which is
12// available at https://www.gnu.org/software/classpath/license.html.
13//
14// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15// *****************************************************************************
16use std::{path::PathBuf, process::ExitCode};
17
18use clap::{Parser, Subcommand};
19use rafia_stpa::stpa::{constraints::RefType, StpaData, StpaProject};
20
21#[derive(Parser)]
22#[command(version, about, long_about = None)]
23struct Cli {
24    #[arg(long)]
25    project: PathBuf,
26
27    #[clap(subcommand)]
28    command: Command,
29}
30
31#[derive(Subcommand)]
32enum Command {
33    /// Lint the graph
34    Lint,
35
36    /// Convert to different outputs
37    Convert {
38        #[arg(long)]
39        convert_yaml: Option<PathBuf>,
40        #[arg(long, requires("trudag_group"))]
41        convert_trudag: Option<PathBuf>,
42        #[arg(long, requires("convert_trudag"))]
43        trudag_group: Option<String>,
44        #[arg(long, requires("convert_trudag"), default_value_t = RefType::File )]
45        trudag_reference: RefType,
46        #[arg(long, requires("convert_trudag"), default_value_t = false)]
47        trudag_mark_valid: bool,
48    },
49
50    /// Describe part of the graph
51    Describe {
52        /// The element of the graph to describe
53        element: String,
54    },
55}
56
57fn main() -> ExitCode {
58    let cli = Cli::parse();
59
60    let project = StpaProject::from_file(&cli.project).unwrap();
61    let stpa_data = StpaData::try_from(project.clone()).unwrap();
62    match cli.command {
63        Command::Lint => {
64            println!("Successfully parsed project");
65            // nothing to do, parsing the project was enough
66        }
67        Command::Convert {
68            convert_yaml,
69            convert_trudag,
70            trudag_group,
71            trudag_reference,
72            trudag_mark_valid,
73        } => {
74            println!("Successfully parsed project");
75            if let Some(root) = convert_yaml {
76                stpa_data.save_project(&root);
77            }
78            if let Some(root) = convert_trudag {
79                stpa_data
80                    .constraints
81                    .to_trudag(
82                        &root,
83                        &project,
84                        trudag_group.as_ref().unwrap(),
85                        trudag_reference,
86                        trudag_mark_valid,
87                    )
88                    .unwrap();
89            }
90        }
91        Command::Describe { element } => {
92            let data = match stpa_data.describe(&element) {
93                Ok(data) => data,
94                Err(e) => {
95                    eprintln!("{e}");
96                    return ExitCode::FAILURE;
97                }
98            };
99
100            println!("{data}");
101        }
102    }
103
104    ExitCode::SUCCESS
105}