Skip to content

Commit 0c0824d

Browse files
committed
WIP: include logic to deprecate output option
1 parent c96bdd0 commit 0c0824d

File tree

6 files changed

+75
-60
lines changed

6 files changed

+75
-60
lines changed

src/cli.rs

+28-10
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
use camino::Utf8PathBuf;
2-
use clap::{Parser, ValueEnum};
2+
use clap::{error::ErrorKind as ClapErrorKind, Parser, ValueEnum};
33
use lazycell::{AtomicLazyCell, LazyCell};
44
use reqwest::blocking::Client;
55
use serde::Serialize;
66

77
use crate::command::output::JsonOutput;
88
use crate::command::{self, RoverOutput};
9+
use crate::options::OutputType;
910
use crate::utils::{
1011
client::{ClientBuilder, ClientTimeout, StudioClientConfig},
1112
env::{RoverEnv, RoverEnvKey},
@@ -14,6 +15,7 @@ use crate::utils::{
1415
};
1516
use crate::RoverResult;
1617

18+
use clap::CommandFactory;
1719
use config::Config;
1820
use houston as config;
1921
use rover_client::shared::GitContext;
@@ -62,12 +64,12 @@ pub struct Rover {
6264
log_level: Option<Level>,
6365

6466
/// Specify Rover's format type
65-
#[arg(long = "format", default_value = "plain", global = true)]
66-
format_type: FormatType,
67+
#[arg(long = "format", global = true)]
68+
format_type: Option<FormatType>,
6769

6870
/// Specify a file to write Rover's output to
6971
#[arg(long = "output", global = true)]
70-
output_type: OutputType,
72+
output_type: Option<OutputType>,
7173

7274
/// Accept invalid certificates when performing HTTPS requests.
7375
///
@@ -118,9 +120,24 @@ impl Rover {
118120
Rover::parse().run()
119121
}
120122

123+
pub fn validate_options(&self) {
124+
match (&self.format_type, &self.output_type) {
125+
(Some(_), Some(OutputType::LegacyOutputType(_))) => {
126+
let mut cmd = Rover::command();
127+
cmd.error(
128+
ClapErrorKind::ArgumentConflict,
129+
"The argument '--output' cannot be used with '--format' when '--output' is not a file",
130+
)
131+
.exit();
132+
},
133+
_ => ()
134+
}
135+
}
136+
121137
pub fn run(&self) -> io::Result<()> {
122138
timber::init(self.log_level);
123139
tracing::trace!(command_structure = ?self);
140+
self.validate_options();
124141

125142
// attempt to create a new `Session` to capture anonymous usage data
126143
let rover_output = match Session::new(self) {
@@ -157,15 +174,16 @@ impl Rover {
157174
match rover_output {
158175
Ok(output) => {
159176
match self.format_type {
160-
FormatType::Plain => output.print()?,
161-
FormatType::Json => JsonOutput::from(output).print()?,
162-
}
177+
Some(FormatType::Plain)| None => output.get_stdout()?,
178+
Some(FormatType::Json) => JsonOutput::from(output).print()?,
179+
_ => None
180+
};
163181
process::exit(0);
164182
}
165183
Err(error) => {
166184
match self.format_type {
167-
FormatType::Json => JsonOutput::from(error).print()?,
168-
FormatType::Plain => {
185+
Some(FormatType::Json) => JsonOutput::from(error).print()?,
186+
Some(FormatType::Plain) | None => {
169187
tracing::debug!(?error);
170188
error.print()?;
171189
}
@@ -225,7 +243,7 @@ impl Rover {
225243
}
226244

227245
pub(crate) fn get_json(&self) -> bool {
228-
matches!(self.format_type, FormatType::Json)
246+
matches!(self.format_type, Some(FormatType::Json)) || matches!(self.output_type, Some(OutputType::LegacyOutputType(FormatType::Json)))
229247
}
230248

231249
pub(crate) fn get_rover_config(&self) -> RoverResult<Config> {

src/command/output.rs

+37-43
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use std::collections::BTreeMap;
22
use std::fmt::{self, Debug, Display};
33
use std::io;
44

5+
use crate::cli::FormatType;
56
use crate::command::supergraph::compose::CompositionOutput;
67
use crate::utils::table::{self, row};
78
use crate::RoverError;
@@ -27,7 +28,7 @@ use termimad::MadSkin;
2728
/// RoverOutput defines all of the different types of data that are printed
2829
/// to `stdout`. Every one of Rover's commands should return `saucer::Result<RoverOutput>`
2930
/// If the command needs to output some type of data, it should be structured
30-
/// in this enum, and its print logic should be handled in `RoverOutput::print`
31+
/// in this enum, and its print logic should be handled in `RoverOutput::get_stdout`
3132
///
3233
/// Not all commands will output machine readable information, and those should
3334
/// return `Ok(RoverOutput::EmptySuccess)`. If a new command is added and it needs to
@@ -78,8 +79,8 @@ pub enum RoverOutput {
7879
}
7980

8081
impl RoverOutput {
81-
pub fn print(&self) -> io::Result<()> {
82-
match self {
82+
pub fn get_stdout(&self) -> io::Result<Option<String>> {
83+
Ok(match self {
8384
RoverOutput::DocsList(shortlinks) => {
8485
stderrln!(
8586
"You can open any of these documentation pages by running {}.\n",
@@ -92,14 +93,14 @@ impl RoverOutput {
9293
for (shortlink_slug, shortlink_description) in shortlinks {
9394
table.add_row(row![shortlink_slug, shortlink_description]);
9495
}
95-
stdoutln!("{}", table)?;
96+
Some(format!("{}", table))
9697
}
9798
RoverOutput::FetchResponse(fetch_response) => {
9899
match fetch_response.sdl.r#type {
99100
SdlType::Graph | SdlType::Subgraph { .. } => print_descriptor("SDL")?,
100101
SdlType::Supergraph => print_descriptor("Supergraph SDL")?,
101102
}
102-
print_content(&fetch_response.sdl.contents)?;
103+
Some(format!("{}", &fetch_response.sdl.contents))
103104
}
104105
RoverOutput::GraphPublishResponse {
105106
graph_ref,
@@ -112,7 +113,7 @@ impl RoverOutput {
112113
publish_response.change_summary
113114
)?;
114115
print_one_line_descriptor("Schema Hash")?;
115-
print_content(&publish_response.api_schema_hash)?;
116+
Some(format!("{}", &&publish_response.api_schema_hash))
116117
}
117118
RoverOutput::SubgraphPublishResponse {
118119
graph_ref,
@@ -147,6 +148,7 @@ impl RoverOutput {
147148
stderrln!("{} The following build errors occurred:", warn_prefix)?;
148149
stderrln!("{}", &publish_response.build_errors)?;
149150
}
151+
None
150152
}
151153
RoverOutput::SubgraphDeleteResponse {
152154
graph_ref,
@@ -196,10 +198,11 @@ impl RoverOutput {
196198
stderrln!("{}", &delete_response.build_errors)?;
197199
}
198200
}
201+
None
199202
}
200203
RoverOutput::CoreSchema(csdl) => {
201204
print_descriptor("CoreSchema")?;
202-
print_content(csdl)?;
205+
Some(format!("{}", csdl))
203206
}
204207
RoverOutput::CompositionResult(composition_output) => {
205208
let warn_prefix = Style::HintPrefix.paint("HINT:");
@@ -213,7 +216,7 @@ impl RoverOutput {
213216
stderrln!("{}", hints_string)?;
214217

215218
print_descriptor("CoreSchema")?;
216-
print_content(&composition_output.supergraph_sdl)?;
219+
Some(format!("{}", &composition_output.supergraph_sdl))
217220
}
218221
RoverOutput::SubgraphList(details) => {
219222
let mut table = table::get_table();
@@ -240,13 +243,10 @@ impl RoverOutput {
240243

241244
table.add_row(row![subgraph.name, url, formatted_updated_at]);
242245
}
243-
244-
stdoutln!("{}", table)?;
245-
stdoutln!(
246-
"View full details at {}/graph/{}/service-list",
247-
details.root_url,
248-
details.graph_ref.name
249-
)?;
246+
Some(format!(
247+
"{}/n View full details at {}/graph/{}/service-list",
248+
table, details.root_url, details.graph_ref.name
249+
))
250250
}
251251
RoverOutput::TemplateList(templates) => {
252252
let mut table = table::get_table();
@@ -263,78 +263,72 @@ impl RoverOutput {
263263
]);
264264
}
265265

266-
stdoutln!("{}", table)?;
266+
Some(format!("{}", table))
267267
}
268268
RoverOutput::TemplateUseSuccess { template, path } => {
269269
print_descriptor("Project generated")?;
270-
stdoutln!(
271-
"Successfully created a new project from the '{template_id}' template in {path}",
272-
template_id = Style::Command.paint(template.id),
273-
path = Style::Path.paint(path.as_str())
274-
)?;
275-
stdoutln!(
276-
"Read the generated '{readme}' file for next steps.",
277-
readme = Style::Path.paint("README.md")
278-
)?;
270+
let template_id = Style::Command.paint(template.id);
271+
let path = Style::Path.paint(path.as_str());
272+
let readme = Style::Path.paint("README.md");
279273
let forum_call_to_action = Style::CallToAction.paint(
280274
"Have a question or suggestion about templates? Let us know at \
281275
https://community.apollographql.com",
282276
);
283-
stdoutln!("{}", forum_call_to_action)?;
277+
Some(format!("Successfully created a new project from the '{}' template in {}/n Read the generated '{}' file for next steps./n{}",
278+
template_id,
279+
path,
280+
readme,
281+
forum_call_to_action))
284282
}
285283
RoverOutput::CheckResponse(check_response) => {
286284
print_descriptor("Check Result")?;
287-
print_content(check_response.get_table())?;
285+
Some(format!("{}", check_response.get_table()))
288286
}
289287
RoverOutput::AsyncCheckResponse(check_response) => {
290288
print_descriptor("Check Started")?;
291-
stdoutln!(
292-
"Check successfully started with workflow ID: {}",
293-
check_response.workflow_id,
294-
)?;
295-
stdoutln!("View full details at {}", check_response.target_url)?;
289+
Some(format!(
290+
"Check successfully started with workflow ID: {}/nView full details at {}",
291+
check_response.workflow_id, check_response.target_url
292+
))
296293
}
297294
RoverOutput::Profiles(profiles) => {
298295
if profiles.is_empty() {
299296
stderrln!("No profiles found.")?;
300297
} else {
301298
print_descriptor("Profiles")?;
302299
}
303-
304-
for profile in profiles {
305-
stdoutln!("{}", profile)?;
306-
}
300+
Some(format!("{}", profiles.join("\n")))
307301
}
308302
RoverOutput::Introspection(introspection_response) => {
309303
print_descriptor("Introspection Response")?;
310-
print_content(introspection_response)?;
304+
Some(format!("{}", introspection_response))
311305
}
312306
RoverOutput::ErrorExplanation(explanation) => {
313307
// underline bolded md
314308
let mut skin = MadSkin::default();
315309
skin.bold.add_attr(Underlined);
316310

317-
stdoutln!("{}", skin.inline(explanation))?;
311+
Some(format!("{}", skin.inline(explanation)))
318312
}
319313
RoverOutput::ReadmeFetchResponse {
320314
graph_ref: _,
321315
content,
322316
last_updated_time: _,
323317
} => {
324318
print_descriptor("Readme")?;
325-
print_content(content)?;
319+
Some(format!("{}", content))
326320
}
327321
RoverOutput::ReadmePublishResponse {
328322
graph_ref,
329323
new_content: _,
330324
last_updated_time: _,
331325
} => {
332326
stderrln!("Readme for {} published successfully", graph_ref,)?;
327+
None
333328
}
334-
RoverOutput::EmptySuccess => (),
335-
};
336-
Ok(())
337-
}
329+
RoverOutput::EmptySuccess => None,
330+
}
331+
) }
338332

339333
pub(crate) fn get_internal_data_json(&self) -> Value {
340334
match self {

src/command/subgraph/delete.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use clap::Parser;
22
use serde::Serialize;
33

4+
use crate::cli::FormatType;
45
use crate::options::{GraphRefOpt, ProfileOpt, SubgraphOpt};
56
use crate::utils::client::StudioClientConfig;
67
use crate::{RoverOutput, RoverResult};
@@ -56,7 +57,7 @@ impl Delete {
5657
dry_run,
5758
delete_response: delete_dry_run_response,
5859
}
59-
.print()?;
60+
.get_stdout()?;
6061

6162
// I chose not to error here, since this is a perfectly valid path
6263
if !prompt::confirm_delete()? {

src/options/introspect.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@ impl IntrospectOpts {
4444
if was_updated {
4545
let output = RoverOutput::Introspection(sdl.to_string());
4646
if json {
47-
let _ = JsonOutput::from(output).print();
47+
let _ = output.get_stdout();
4848
} else {
49-
let _ = output.print();
49+
let _ = output.get_stdout();
5050
}
5151
}
5252
last_result = Some(sdl);
@@ -61,7 +61,7 @@ impl IntrospectOpts {
6161
}
6262
if was_updated {
6363
if json {
64-
let _ = JsonOutput::from(error).print();
64+
let _ = error.print();
6565
} else {
6666
let _ = error.print();
6767
}

src/options/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ pub(crate) use compose::*;
1414
pub(crate) use graph::*;
1515
pub(crate) use introspect::*;
1616
pub(crate) use license::*;
17+
pub(crate) use output::*;
1718
pub(crate) use profile::*;
1819
pub(crate) use schema::*;
1920
pub(crate) use subgraph::*;

src/options/output.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use std::str::FromStr;
22

33
use camino::Utf8PathBuf;
4-
use clap::Parser;
4+
use clap::{Parser, ValueEnum};
5+
use serde::Serialize;
56

67
use crate::cli::FormatType;
78

@@ -12,7 +13,7 @@ pub struct Output {
1213
output: OutputType,
1314
}
1415

15-
#[derive(Debug, Clone, Eq, PartialEq)]
16+
#[derive(Debug, Clone, Eq, PartialEq, Serialize)]
1617
pub enum OutputType {
1718
LegacyOutputType(FormatType),
1819
File(Utf8PathBuf),
@@ -22,7 +23,7 @@ impl FromStr for OutputType {
2223
type Err = anyhow::Error;
2324

2425
fn from_str(s: &str) -> Result<Self, Self::Err> {
25-
if let Ok(format_type) = FormatType::from_str(s) {
26+
if let Ok(format_type) = FormatType::from_str(s, true) {
2627
Ok(Self::LegacyOutputType(format_type))
2728
} else {
2829
Ok(Self::File(Utf8PathBuf::from(s)))

0 commit comments

Comments
 (0)