-
Notifications
You must be signed in to change notification settings - Fork 87
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enable Fuchsia safe command line tool analytics #82
Conversation
…es that is safe for analytics tracking
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you also make sure that this flag shows up in --help
?
README.md
Outdated
@@ -174,4 +174,9 @@ struct SubCommandTwo { | |||
} | |||
``` | |||
|
|||
It is also possible to retrieve just the names of the arguments and switches | |||
passed at runtime, by including the switch `--dump_args_passed` in the args, similarly |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than --dump_args_passed
, I think it'd be more aligned with the style guide as --dump-args-passed
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
name updated to match style in latest commit.
Could you also make sure that this flag shows up in
--help
?
Should this be included in --help output or would it confuse an end user of a tool built using argh since it mirrors back to them the options and subcommands they entered?
@@ -291,7 +291,18 @@ fn impl_from_args_struct( | |||
} else { | |||
__remaining_args | |||
}; | |||
#name = Some(<#ty as argh::FromArgs>::from_args(&__command, __remaining_args)?); | |||
if __dump_args { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we make this a feature we have to opt into, rather than it being on by default? I figure this would only be used in certain situations. Something like this (or some better name):
#[derive(FromArgs)]
#[argh(with_dump_args_passed)]
struct Cmd {
...
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems reasonable to reduce code generated by the macro expansion.
One question, in the ffx case, e.g. open-ended set of plugins in separate files defining their own argh subcommand, is there any ordering guarantee in compilation such that the developer would only have to annotate the TopLevel struct with opt-in, or, would each plugin developer need to add the annotation to opt-in as well? I am thinking the latter.
FFX may be a non-standard use case. Do most users of argh define all args in one file?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good question. According to the ffx docs, all the plugins are declared as subcommands
, like:
#[ffx_command()]
#[derive(FromArgs, Debug, PartialEq)]
#[argh(subcommand, name = "example", description = "an example")]
pub struct ExampleCommand {
#[argh(positional)]
/// example optional positional string parameter
pub example: Option<String>,
}
I would imagine we'd want something like #[argh(with_dump_args_passed)]
would be specified on the main entry point. Do you know how this feature interacts with subcommands?
@@ -291,7 +291,18 @@ fn impl_from_args_struct( | |||
} else { | |||
__remaining_args | |||
}; | |||
#name = Some(<#ty as argh::FromArgs>::from_args(&__command, __remaining_args)?); | |||
if __dump_args { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This command seems pretty specialized. Could we make this an opt-in feature, with something like:
#[derive(FromArgs)]
#[argh(description = "", dump_passed_args)]
struct Cmd { ... }
Happy for suggestions on a better attribute name. We could even make it such that this flag was customizable, with something like:
#[derive(FromArgs)]
#[argh(description = "", dump_passed_args="--dump-passed-args")]
struct Cmd { ... }
To make it easier for people to customize.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See above question about a TopLevel opt-in versus per subcommand.
Is the benefit that the macro expansion will not generate the bits of logic to accumulate the passed_args if the user has opted out?
Thanks for the quick turnaround. I updated all the names to comply with the style guide and had a question or two about opt-in and about including a description in the help output. |
Ping |
Please enter the commit message for your changes. Lines starting
/// The first argument `command_name` is the identifier for the current | ||
/// command, treating each segment as space-separated. The second argument, | ||
/// args, is the rest of the command line arguments. | ||
fn to_args(command_name: &[&str], args: &[&str]) -> String; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did you end up using a static method here? I imagined this more to be fn to_args(&self) -> Vec<String>;
. This has two advantages:
- The arguments need to be fully parsed first.
- This would allow the caller to escape the arguments as necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Err, I mean:
fn to_args(&self) -> Vec<String> {
vec![]
}
We need to have this be a default method for two reasons. First, adding a non-default method to a trait is not backwards compatible. Second, this defaults custom implementations to not return anything, which is more private.
It is also possible to retrieve just the names of the arguments and switches | ||
passed at runtime, by including the switch `--dump-args-passed` in the args, similarly | ||
to how `--help` can be passed. This elides any user values passed and creates an | ||
output for safely collecting data for analytics. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need --dump-args-passed
now that we have FromArgs::to_args()
. Then it's up to the caller whether or not to call this function to trigger this functionality, with something like:
#[derive(FromArgs)]
struct Cmd {
#[argh(rename = "dumped-args-passed")]
dump_args: bool,
...
}
fn main() {
let cmd = argh::from_env();
if cmd.dump_args {
let dumped_args = cmd.to_args();
println!("{}", cmd.to_args().map(escape_arg).join(" "));
std::process::exit(0);
}
}
fn escpe_arg(&str) -> String { ... }
@@ -291,7 +291,18 @@ fn impl_from_args_struct( | |||
} else { | |||
__remaining_args | |||
}; | |||
#name = Some(<#ty as argh::FromArgs>::from_args(&__command, __remaining_args)?); | |||
if __dump_args { | |||
__args_dump.push(__subcommand.name.to_string().replace(" ", "\\ ")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As mentioned below, I think we should keep the arguments as a vector to allow callers to escape arguments if necessary.
} | ||
)* | ||
unreachable!("no subcommand matched") | ||
} | ||
|
||
// Note: This can never get called because enums are only SubCommand containers | ||
fn to_args(command_name: &[&str], args: &[&str]) -> String { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't we need to recurse into the enum variants?
/// The first argument `command_name` is the identifier for the current | ||
/// command, treating each segment as space-separated. The second argument, | ||
/// args, is the rest of the command line arguments. | ||
fn to_args(command_name: &[&str], args: &[&str]) -> String; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Err, I mean:
fn to_args(&self) -> Vec<String> {
vec![]
}
We need to have this be a default method for two reasons. First, adding a non-default method to a trait is not backwards compatible. Second, this defaults custom implementations to not return anything, which is more private.
Closing in favor of #91. |
This PR allows Fuchsia DX tools to collect analytics without collecting any user passed data.
Any tool that wants to collect analytics can re-parse the args with an extra flag, "--dump_args_passed" to retrieve a string of the command options suitable for posting to analytics.