Skip to content
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

Update clap to v3 1 #1140

Closed

Conversation

CosmicHorrorDev
Copy link
Contributor

This is my initial attempt at updating clap to v3.1 (and switching over to the Derive API for it)

I kept the same external Commands for the parsed format and just used intermediate values internally. To keep the separation cleaner this involved changing parse() to be infallible where the error displaying and exiting early is now done internally within parse()

sccache appears to be fine and tests pass with cargo test for it. sccache-dist is compiling and from a surface level check things seem to be fine, but the tests for it don't pass for me on main or this branch. This PR is marked as a draft until that gets sorted out. Below is an example of the error I get:

---- test_dist_nobuilder stdout ----
thread 'test_dist_nobuilder' panicked at 'called `Result::unwrap()` on an `Err` value: AddrParseError(())', tests/harness/mod.rs:488:42
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
LOGS == (exit status: 0) ==
> sccache_dist_test_scheduler_314eee14-4948-4e30-abf4-685adf5e766a <:
## STDOUT


## STDERR
/sccache-dist: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.28' not found (required by /sccache-dist)
/sccache-dist: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.29' not found (required by /sccache-dist)
/sccache-dist: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.32' not found (required by /sccache-dist)
/sccache-dist: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.33' not found (required by /sccache-dist)
/sccache-dist: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found (required by /sccache-dist)

====
OUTPUTS == (exit status: 1) ==
> sccache_dist_test_scheduler_314eee14-4948-4e30-abf4-685adf5e766a <:
## STDOUT


## STDERR
Error response from daemon: Cannot kill container: sccache_dist_test_scheduler_314eee14-4948-4e30-abf4-685adf5e766a: Container 3681cd393c6d9e3a7a50674313ac76356f3496b3688785250c5a5dc75a06360d is not running

====
OUTPUTS == (exit status: 0) ==
> sccache_dist_test_scheduler_314eee14-4948-4e30-abf4-685adf5e766a <:
## STDOUT
sccache_dist_test_scheduler_314eee14-4948-4e30-abf4-685adf5e766a


## STDERR

====


failures:
    test_dist_nobuilder

Also just for comparison here is a comparison of the new and old help messages

sccache old

sccache 0.2.15

USAGE:
    sccache [FLAGS] [OPTIONS] [cmd]...

FLAGS:
        --dist-auth       authenticate for distributed compilation
        --dist-status     show status of the distributed client
    -h, --help            Prints help information
    -s, --show-stats      show cache statistics
        --start-server    start background server
        --stop-server     stop background server
    -V, --version         Prints version information
    -z, --zero-stats      zero statistics counters

OPTIONS:
        --package-toolchain <executable> <out>    package toolchain for distributed compilation
        --stats-format <stats-format>
            set output format of statistics [default: text]  [possible values: text, json]


ARGS:
    <cmd>...

Enabled features:
    S3:        true
    Redis:     true
    Memcached: true
    GCS:       true
    Azure:     true

sccache new

sccache 0.2.16-alpha.0

USAGE:
    sccache [OPTIONS] [--] [CMD]...

ARGS:
    <CMD>...

OPTIONS:
        --dist-auth
            authenticate for distributed compilation

        --dist-status
            show status of the distributed client

    -h, --help
            Print help information

        --package-toolchain <PACKAGE_TOOLCHAIN> <PACKAGE_TOOLCHAIN>
            package toolchain for distributed compilation

    -s, --show-stats
            show cache statistics

        --start-server
            start background server

        --stats-format <STATS_FORMAT>
            set output format of statistics [default: text] [possible values: text, json]

        --stop-server
            stop background server

    -V, --version
            Print version information

    -z, --zero-stats
            zero statistic counters

Enabled features:
    S3:        true
    Redis:     true
    Memcached: true
    GCS:       true
    Azure:     true

sccache-dist old

sccache 0.2.15

USAGE:
    sccache-dist [SUBCOMMAND]

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

SUBCOMMANDS:
    auth
    help         Prints this message or the help of the given subcommand(s)
    scheduler
    server

sccache-dist new

sccache 0.2.16-alpha.0

USAGE:
    sccache-dist <SUBCOMMAND>

OPTIONS:
    -h, --help       Print help information
    -V, --version    Print version information

SUBCOMMANDS:
    auth
    help         Print this message or the help of the given subcommand(s)
    scheduler
    server

So sccache's is a bit more spaced out and has different headings. I can set custom headings for arguments to be under if we want that to match. I tried setting the output to be more compact too, but I think the line --package-toolchain may be overriding that. Other than that things are pretty much all the same aside from color with the new output and more parsing being enforced by clap instead of bubbled up by sccache

@CosmicHorrorDev
Copy link
Contributor Author

CosmicHorrorDev commented Mar 12, 2022

Less tired now so I pushed some cleanup. From an outside user's perspective things should seem nicer because I tried pushing as much validation onto clap as possible so we get the nice error messages from it. From a contributor's perspective the changes use the derive API and I think the code looks more approachable.

Since I forgot to mention it before this requires #1137 for the MSRV bump and is part of getting #1110 finished off

I still haven't got the sccache-dist test errors sorted out and don't know enough to accurately troubleshoot things since it's failing on main and this PR for me, but I'll go ahead and mark this as ready for review since those things can get sorted out during the review process

Here's an overview comparing things (just for reference the new cli stuff has color while the old stuff doesnt)

sccache

Help pages

sccache --help

old
sccache 0.2.15

USAGE:
    sccache [FLAGS] [OPTIONS] [cmd]...

FLAGS:
        --dist-auth       authenticate for distributed compilation
        --dist-status     show status of the distributed client
    -h, --help            Prints help information
    -s, --show-stats      show cache statistics
        --start-server    start background server
        --stop-server     stop background server
    -V, --version         Prints version information
    -z, --zero-stats      zero statistics counters

OPTIONS:
        --package-toolchain <executable> <out>    package toolchain for distributed compilation
        --stats-format <stats-format>
            set output format of statistics [default: text]  [possible values: text, json]


ARGS:
    <cmd>...

Enabled features:
    S3:        true
    Redis:     true
    Memcached: true
    GCS:       true
    Azure:     true
new
sccache 0.2.16-alpha.0

USAGE:
    sccache [OPTIONS] <--dist-auth|--dist-status|--show-stats|--start-server|--stop-server|--zero-stats|--package-toolchain <EXECUTABLE> <OUT>|CMD> [--]

ARGS:
    <CMD>...

OPTIONS:
        --dist-auth
            authenticate for distributed compilation

        --dist-status
            show status of the distributed client

    -h, --help
            Print help information

        --package-toolchain <EXECUTABLE> <OUT>
            package toolchain for distributed compilation

    -s, --show-stats
            show cache statistics

        --start-server
            start background server

        --stats-format <FORMAT>
            set output format of statistics [default: text] [possible values: text, json]

        --stop-server
            stop background server

    -V, --version
            Print version information

    -z, --zero-stats
            zero statistic counters

Enabled features:
    S3:        true
    Redis:     true
    Memcached: true
    GCS:       true
    Azure:     true

Errors

No command - sccache

Note: It's not clear from the old cli usage what a "command" is, while the new cli shows in the usage and help messages

Pushing this and too many commands validation onto clap did involve a bit of hackiness. The reason for it being hacky is that clap doesn't support an "arg" that is just a env variable, but I wanted to include SCCACHE_START_SERVER=1 in the "one and only one" arg group since it is one of the commands and doesn't make sense to be used with many of the other commands.

My "fix" to handle this is to smuggle the value in under the start_server arg and hide it from listing the command-line option with hide_env. When SCCACHE_START_SERVER=1 then --start-server is manually unset since it is set automatically by clap. When SCCACHE_START_SERVER != 1 then the env var is removed since it would count as being present for --start-server and need some other command to be used. If the env var isn't present then things can run as normal

This is a bit of a hacky way to handle things, but I think the end result from a user's perspective is worth it since it makes correct usage much more obvious. Having SCCACHE_START_SERVER linked to some unlikely-to-be-called flag that has hide set would be nicer, but the flag name still shows up in usage strings and error suggestions which is a bit annoying. I figured out that you can set the long flag name to "\x08\x08\x08" (backspace, backspace, backspace). This makes things look fine when hide is set since an empty long name would add |-- to the usage string so three backspaces makes it render like it doesn't exist, but I figured that was too cursed to be used

old
sccache: No command specified
sccache 0.2.15

USAGE:
    sccache [FLAGS] [OPTIONS] [cmd]...

FLAGS:
        --dist-auth       authenticate for distributed compilation
        --dist-status     show status of the distributed client
    -h, --help            Prints help information
    -s, --show-stats      show cache statistics
        --start-server    start background server
        --stop-server     stop background server
    -V, --version         Prints version information
    -z, --zero-stats      zero statistics counters

OPTIONS:
        --package-toolchain <executable> <out>    package toolchain for distributed compilation
        --stats-format <stats-format>
            set output format of statistics [default: text]  [possible values: text, json]


ARGS:
    <cmd>...

Enabled features:
    S3:        true
    Redis:     true
    Memcached: true
    GCS:       true
    Azure:     true
new
error: The following required arguments were not provided:
    <--dist-auth|--dist-status|--show-stats|--start-server|--stop-server|--zero-stats|--package-toolchain <EXECUTABLE> <OUT>|CMD>

USAGE:
    sccache [OPTIONS] <--dist-auth|--dist-status|--show-stats|--start-server|--stop-server|--zero-stats|--package-toolchain <EXECUTABLE> <OUT>|CMD> [--]

For more information try --help

Too many commands - sccache --start-server --stop-server

old
sccache: Too many commands specified
sccache 0.2.15

USAGE:
    sccache [FLAGS] [OPTIONS] [cmd]...

FLAGS:
        --dist-auth       authenticate for distributed compilation
        --dist-status     show status of the distributed client
    -h, --help            Prints help information
    -s, --show-stats      show cache statistics
        --start-server    start background server
        --stop-server     stop background server
    -V, --version         Prints version information
    -z, --zero-stats      zero statistics counters

OPTIONS:
        --package-toolchain <executable> <out>    package toolchain for distributed compilation
        --stats-format <stats-format>
            set output format of statistics [default: text]  [possible values: text, json]


ARGS:
    <cmd>...

Enabled features:
    S3:        true
    Redis:     true
    Memcached: true
    GCS:       true
    Azure:     true
new
error: The argument '--start-server' cannot be used with '--stop-server'

USAGE:
    sccache <--dist-auth|--dist-status|--show-stats|--start-server|--stop-server|--zero-stats|--package-toolchain <EXECUTABLE> <OUT>|CMD>

For more information try --help

sccache-dist

Help pages

sccache-dist --help

old
sccache 0.2.15

USAGE:
    sccache-dist [SUBCOMMAND]

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

SUBCOMMANDS:
    auth
    help         Prints this message or the help of the given subcommand(s)
    scheduler
    server
new
sccache 0.2.16-alpha.0

USAGE:
    sccache-dist <SUBCOMMAND>

OPTIONS:
    -h, --help       Print help information
    -V, --version    Print version information

SUBCOMMANDS:
    auth
    help         Print this message or the help of the given subcommand(s)
    scheduler
    server

sccache-dist auth --help

old
sccache-dist-auth

USAGE:
    sccache-dist auth [SUBCOMMAND]

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

SUBCOMMANDS:
    generate-jwt-hs256-key
    generate-jwt-hs256-server-token
    generate-shared-token
    help                               Prints this message or the help of the given subcommand(s)
new
sccache-dist-auth 0.2.16-alpha.0

USAGE:
    sccache-dist auth <SUBCOMMAND>

OPTIONS:
    -h, --help       Print help information
    -V, --version    Print version information

SUBCOMMANDS:
    generate-jwt-hs256-key
    generate-jwt-hs256-token
    generate-shared-token
    help                        Print this message or the help of the given subcommand(s)

sccache-dist auth generate-jwt-hs256-key --help

old
sccache-dist-auth-generate-jwt-hs256-key

USAGE:
    sccache-dist auth generate-jwt-hs256-key

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information
new
sccache-dist-auth-generate-jwt-hs256-key 0.2.16-alpha.0

USAGE:
    sccache-dist auth generate-jwt-hs256-key

OPTIONS:
    -h, --help       Print help information
    -V, --version    Print version information

sccache-dist auth generate-jwt-hs256-server-token --help

old
sccache-dist-auth-generate-jwt-hs256-server-token

USAGE:
    sccache-dist auth generate-jwt-hs256-server-token --config <PATH> --secret-key <KEY> --server <SERVER_ADDR>

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

OPTIONS:
        --config <PATH>           Use the key from the scheduler config file
        --secret-key <KEY>        Use specified key to create the token
        --server <SERVER_ADDR>    Generate a key for the specified server
new
sccache-dist-auth-generate-jwt-hs256-server-token 0.2.16-alpha.0

USAGE:
    sccache-dist auth generate-jwt-hs256-server-token --server <SERVER_ADDR> <--secret-key <KEY>|--config <PATH>>

OPTIONS:
        --config <PATH>           Use the key from the scheduler config file at PATH
    -h, --help                    Print help information
        --secret-key <KEY>        Use specified key to create the token
        --server <SERVER_ADDR>    Generate a key for the specified server
    -V, --version                 Print version information

sccache-dist auth generate-shared-token --help

old
sccache-dist-auth-generate-shared-token

USAGE:
    sccache-dist auth generate-shared-token [OPTIONS]

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

OPTIONS:
        --bits <BITS>    Use the specified number of bits of randomness [default: 256]
new
sccache-dist-auth-generate-shared-token 0.2.16-alpha.0

USAGE:
    sccache-dist auth generate-shared-token [OPTIONS]

OPTIONS:
        --bits <BITS>    Use the specified number of bits of randomness [default: 256]
    -h, --help           Print help information
    -V, --version        Print version information

sccache-dist scheduler --help

old
sccache-dist-scheduler

USAGE:
    sccache-dist scheduler [OPTIONS] --config <PATH>

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

OPTIONS:
        --config <PATH>     Use the scheduler config file at PATH
        --syslog <LEVEL>    Log to the syslog with LEVEL [possible values: error, warn, info, debug, trace]
new
sccache-dist-scheduler 0.2.16-alpha.0

USAGE:
    sccache-dist scheduler --config <PATH> --syslog <LEVEL>

OPTIONS:
        --config <PATH>     Use the scheduler config file at PATH
    -h, --help              Print help information
        --syslog <LEVEL>    Log to the syslog with LEVEL [possible values: error, warn, info, debug, trace]
    -V, --version           Print version information

sccache-dist server --help

old
sccache-dist-server

USAGE:
    sccache-dist server [OPTIONS] --config <PATH>

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

OPTIONS:
        --config <PATH>     Use the server config file at PATH
        --syslog <LEVEL>    Log to the syslog with LEVEL [possible values: error, warn, info, debug, trace]
new
sccache-dist-server 0.2.16-alpha.0

USAGE:
    sccache-dist server --config <PATH> --syslog <LEVEL>

OPTIONS:
        --config <PATH>     Use the server config file at PATH
    -h, --help              Print help information
        --syslog <LEVEL>    Log to the syslog with LEVEL [possible values: error, warn, info, debug, trace]
    -V, --version           Print version information

Errors

Server Token conflict - sccache-dist auth generate-jwt-hs256-server-token --server 127.0.0.1:8080 --config some_config --secret-key some_key

Note: From the implementation it appears that --config and --secret-key are meant to be mutually exclusive, but the old cli parsing would allow both to be passed and would just ignore --secret-key which isn't intuitive

old
sccache-dist: Could not load config
sccache 0.2.15

USAGE:
    sccache [SUBCOMMAND]

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

SUBCOMMANDS:
    auth
    help         Prints this message or the help of the given subcommand(s)
    scheduler
    server
new
error: The argument '--config <PATH>' cannot be used with '--secret-key <KEY>'

USAGE:
    sccache-dist auth generate-jwt-hs256-server-token --server <SERVER_ADDR> --server <SERVER_ADDR> <--secret-key <KEY>|--config <PATH>>

For more information try --help

Invalid Shared Token bit value - sccache-dist auth generate-shared-token --bits 70

Note: New implementation points out that the invalid value is from the --bits option specifically

old
sccache-dist: Number of bits must be divisible by 8, greater than 64 and less than 4096
sccache 0.2.15

USAGE:
    sccache [SUBCOMMAND]

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

SUBCOMMANDS:
    auth
    help         Prints this message or the help of the given subcommand(s)
    scheduler
    server
new
error: Invalid value "70" for '--bits <BITS>': Number of bits must be divisible by 8, greater than 64 and less than 4096

For more information try --help

@CosmicHorrorDev CosmicHorrorDev marked this pull request as ready for review March 12, 2022 08:31
@CosmicHorrorDev
Copy link
Contributor Author

Thinking on it more there are still issues present with how SCCACHE_START_SERVER is currently added to the arg group. I'll push out a fix for that tomorrow

@CosmicHorrorDev
Copy link
Contributor Author

As promised here is the fix. The issue was that the following wouldn't be allowed on main, but was allowed from this PR

$ SCCACHE_START_SERVER=1 sccache --start-server

Along with that error messages from SCCACHE_START_SERVER conflicting with other commands would be confusing because it would mention --start-server even when it wasn't used.

The fix clears up error messages when an arg conflict occurs and SCCACHE_START_SERVER is present by making explicit note of it:

$ SCCACHE_START_SERVER=1 ./sccache --start-server
sccache: `SCCACHE_START_SERVER=1` can't be used with other commands

$ SCCACHE_START_SERVER=1 ./sccache some command
sccache: `SCCACHE_START_SERVER=1` can't be used with other commands

Along with that the error with SCCACHE_START_SERVER being allowed with --start-server was fixed (as can be seen above) by inspecting the source of how start-server was set. If SCCACHE_START_SERVER was present and the source was from the flag then an error is returned then we know both were set which should be an error. This works because flags take precedence over env vars, so if both are present then the source should always be the flag.

@codecov-commenter
Copy link

codecov-commenter commented Mar 14, 2022

Codecov Report

Merging #1140 (b746b3d) into main (5032a83) will decrease coverage by 0.20%.
The diff coverage is 30.39%.

❗ Current head b746b3d differs from pull request most recent head 4b9d5bd. Consider uploading reports for the commit 4b9d5bd to get more accurate results

@@            Coverage Diff             @@
##             main    #1140      +/-   ##
==========================================
- Coverage   35.11%   34.91%   -0.21%     
==========================================
  Files          47       47              
  Lines       12774    12794      +20     
  Branches     6637     6640       +3     
==========================================
- Hits         4486     4467      -19     
- Misses       3986     3990       +4     
- Partials     4302     4337      +35     
Impacted Files Coverage Δ
src/commands.rs 16.61% <0.00%> (ø)
src/lib.rs 37.93% <28.57%> (+0.89%) ⬆️
src/cmdline.rs 27.35% <31.39%> (-1.95%) ⬇️
src/test/utils.rs 36.36% <0.00%> (-3.04%) ⬇️
src/compiler/gcc.rs 55.72% <0.00%> (-1.79%) ⬇️
src/util.rs 41.35% <0.00%> (-0.76%) ⬇️
src/cache/azure.rs 31.11% <0.00%> (-0.75%) ⬇️
src/mock_command.rs 52.39% <0.00%> (-0.37%) ⬇️
src/compiler/args.rs 60.21% <0.00%> (-0.36%) ⬇️
... and 8 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 5032a83...4b9d5bd. Read the comment docs.

@mitchhentges
Copy link
Contributor

Thanks for the patch! Looks good so far, but I'll do a more complete review tomorrow most likely.

The only concern I have off the top of my head is that the new, non-compact help menu is a bit of a bummer, but you've already noticed and addressed this:

I tried setting the output to be more compact too, but I think the line --package-toolchain may be overriding that.

@CosmicHorrorDev
Copy link
Contributor Author

I'll poke around at some more settings to see if I can get things to be more compact again

@CosmicHorrorDev
Copy link
Contributor Author

So enabling the wrap_help feature and switching the value name in package_toolchain from EXECUTABLE to EXE condenses down the help message when the terminal is a reasonable width and falls back to long help on narrower terminals. Another way of handling this could be to separate out --package-toolchain and --stats-format to a different heading like how it is by default in clap v2. Here's how things currently look as long as your terminal is wide enough to fit it (usage never seems to wrap which is fine)

sccache 0.2.16-alpha.0

USAGE:
    sccache [OPTIONS] <--dist-auth|--dist-status|--show-stats|--start-server|--stop-server|--zero-stats|--package-toolchain <EXE> <OUT>|CMD> [--]

ARGS:
    <CMD>...

OPTIONS:
        --dist-auth                        authenticate for distributed compilation
        --dist-status                      show status of the distributed client
    -h, --help                             Print help information
        --package-toolchain <EXE> <OUT>    package toolchain for distributed compilation
    -s, --show-stats                       show cache statistics
        --start-server                     start background server
        --stats-format <FORMAT>            set output format of statistics [default: text] [possible values:
                                           text, json]
        --stop-server                      stop background server
    -V, --version                          Print version information
    -z, --zero-stats                       zero statistic counters

Enabled features:
    S3:        true
    Redis:     true
    Memcached: true
    GCS:       true
    Azure:     true

Copy link
Contributor

@mitchhentges mitchhentges left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So enabling the wrap_help feature and switching the value name in package_toolchain from EXECUTABLE to EXE condenses down the help message when the terminal is a reasonable width and falls back to long help on narrower terminals.

This looks great! The touch of colour is pretty nice too 👍

Another way of handling this could be to separate out --package-toolchain and --stats-format to a different heading like how it is by default in clap v2.

I think that separating "options" from "flags" was a very pedantic (and potentially confusing) distinction, so I really like how you've set it up.

Too many commands - sccache --start-server --stop-server

I really like how you've made this more obvious: rather than a confusing "Too many commands specified" error (which is ambiguous with the "you have provided an unexpectedly large number of command-like arguments"), it tells you specifically which two arguments are unacceptably provided together. Nice 👍


I think that the improvements you've made in updating clap and strengthening the restrictions we define (such as start-server and stop-server mutual exclusivity) are strong enhancements. However, the third, significant change that you've made in this patch - the migration to clap's "derive" API - isn't something that I'm confident is an improvement for sccache.

This project is midsized, and is starting to sprout weird behaviours that are harder to represent with the "derive" interface: you're seeing this yourself with how much legwork you had to do to make SCCACHE_START_SERVER play nicely with the other options. The flexibility offered by the "builder" API is something that sccache is already leveraging, and may need to lean on even more in the future.

The other part that makes "derive" tricky is that it is very magical. This can make debugging and tweaking clap's behaviour a bit of a headache. For example, it took me some nontrivial digging to figure out what the attributes on parse::Opts was. Posted here for convenience:

#[derive(Parser)]
#[clap(version)]
#[clap(propagate_version = true)]
struct Opts { ... }

Two parts here were confusing:

  • What does clap(version) do? Looking up version on docs.rs didn't point me in the right direction. I had to find the "Derive Reference", at which point the documented behaviour of "magic attributes" became clear. I think that this journey would be much less treacherous with the more traditional API.
  • Where does clap(propagate_version = true) affect? Fortunately, propagate_version had an entry in the documentation, but I still second-guessed myself for a minute because the function definition I found was associated with a deprecated struct.

I can see the appeal of leveraging the "attribute" language feature to try to tighten the coupling between parsing and the generated struct containing the refined arguments. However, I think that its costs aren't worth the benefits today.


Would you be interested in simplifying this patch to be specifically about updating clap and improving our handling of specific incompatible arguments, such as --start-server, --stop-server, and the others?

src/bin/sccache-dist/cmdline/mod.rs Outdated Show resolved Hide resolved
tests/test-crate/Cargo.lock Outdated Show resolved Hide resolved
@CosmicHorrorDev
Copy link
Contributor Author

Thanks for all the feedback! I can push out changes to address your comments (including switching back to the builder API) either later today or tomorrow

@CosmicHorrorDev
Copy link
Contributor Author

Would you be interested in simplifying this patch to be specifically about updating clap and improving our handling of specific incompatible arguments, such as --start-server, --stop-server, and the others?

The last push is all I have time for atm. It implements the above where we are back to the bulider api (barring some ArgEnums where it is used to generate the list of possible values. This can be done manually or through other libraries of course).

Things should still follow the same strictness as was enforced by the derive implementation. The SCCACHE_START_SERVER env var bit is handled essentially the same way (I switched to no longer smuggling the env var in an unrelated arg and just looked for a different error kind from clap. This isn't specific to changing back to the builder API. I just felt like smuggling a hidden env var into an ArgGroup was hackier than how things are done now). Beyond that the subcommand requirements, flag requirements, and value validity (--bits, --stats-format) should all be enforced with nice error messages from clap still

A notable difference from the clap v2 based builder API is that the old implementation made heavy usage of Arg::from_usage(<usage string>) which is now deprecated. It's new incarnation is the arg!(<psuedo usage>) macro so that more issues can be found at compile-time, but I opted for just building off of Args since I was running into some annoyances with arg!() that made it seem like it wasn't really pulling its weight

I did take the time to start implementing some unit tests for the arg parsing. I only had time to go through a decent bit of sccache-dist's CLI. Starting tomorrow I'll be visiting family / focusing on work due to lack of time from visiting family, so I'll have a short 2-or-so week hiatus from OSS. If you want then feel free to finish off any final changes you want, or you can wait until I'm off of my break and I'll be happy to address any final comments :). I'll be around for responding to comments, just won't have any time for making changes

@mitchhentges
Copy link
Contributor

That sounds great, thanks! I'll take a look at this tomorrow most likely.

Starting tomorrow I'll be visiting family / focusing on work due to lack of time from visiting family, so I'll have a short 2-or-so week hiatus from OSS. If you want then feel free to finish off any final changes you want, or you can wait until I'm off of my break and I'll be happy to address any final comments :). I'll be around for responding to comments, just won't have any time for making changes

I appreciate that, thanks! There isn't a rush to get this landed, especially considering that it's blocked on our next release (which should be going out in the next week or so).

Copy link
Contributor

@mitchhentges mitchhentges left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but I opted for just building off of Args since I was running into some annoyances with arg!() that made it seem like it wasn't really pulling its weight

Would you mind elaborating here in this PR with a comment for what specific annoyances you were running into?


Three other things:

  • I'll still need to do one more pass to look at the non-dist handling, but I'll handle it after you've addressed this first round here
  • For future patches, I'd highly recommend trying to keep your diff smaller. Right now, you've significantly changed the clap configuration logic, but you've also moved a bunch of code. It would be much easier to review if that was split into either two, self-contained commits, or two separate PRs.
  • Thanks for the patch, this is looking great so far 😁

Cargo.toml Outdated Show resolved Hide resolved
tests/test-crate/Cargo.lock Outdated Show resolved Hide resolved
src/bin/sccache-dist/cmdline/parse.rs Outdated Show resolved Hide resolved
src/bin/sccache-dist/cmdline/parse.rs Outdated Show resolved Hide resolved
src/bin/sccache-dist/cmdline/parse.rs Show resolved Hide resolved
src/bin/sccache-dist/cmdline/parse.rs Show resolved Hide resolved
src/bin/sccache-dist/cmdline/parse.rs Show resolved Hide resolved
src/bin/sccache-dist/cmdline/parse.rs Outdated Show resolved Hide resolved
src/bin/sccache-dist/cmdline/parse.rs Outdated Show resolved Hide resolved
@CosmicHorrorDev
Copy link
Contributor Author

Would you mind elaborating here in this PR with a comment for what specific annoyances you were running into?

Sure! Just for reference here is the current docs section for arg!()

// Doesn't work
clap::arg!(--some-flag);
// Works
clap::arg!(--"some-flag");
  • Multiple values aren't currently supported (has a nice error at least), so --package-toolchain <EXE> <OUT> would need to use .value_names() still. The error message when trying to use it for reference
thread 'main' panicked at 'assertion failed: `(left == right)`
  left: `Some(["EXE"])`,
 right: `None`: Multiple values not yet supported', src/main.rs
  • The docs for "Help String" which are below seem to be outdated. Single quotes were used for the old ::from_usage() initialization, but are not allowed for the current macro implementation

The help string is denoted between a pair of single quotes '' and may contain any characters.

All of this just ended up leading to a very bumpy start, so it seemed easiest to just avoid the macro-magic and stick with the straight-forward (and well documented) builder pattern


  • For future patches, I'd highly recommend trying to keep your diff smaller. Right now, you've significantly changed the clap configuration logic, but you've also moved a bunch of code. It would be much easier to review if that was split into either two, self-contained commits, or two separate PRs.

👍


All the changes seem more than reasonable! I'll work through them when I get back to OSS again

@CosmicHorrorDev
Copy link
Contributor Author

I believe the recent commits address all your current requested changes, so this should be good for another review whenever you are able!

Copy link
Contributor

@mitchhentges mitchhentges left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me, nice work! Thanks again for this patch and your collaboration, this is great!

I'm going to wait to land this until v0.3.0, which is unfortunately taking longer than I had hoped. I'm looking forward to merging this :)

src/bin/sccache-dist/cmdline/parse.rs Outdated Show resolved Hide resolved
src/cmdline.rs Show resolved Hide resolved
src/cmdline.rs Show resolved Hide resolved
src/cmdline.rs Outdated Show resolved Hide resolved
Copy link
Collaborator

@drahnr drahnr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice 👍 , just a few questions, other than that I'd be happy to merge if you don't want to go the annotation route :)

src/bin/sccache-dist/cmdline/parse.rs Outdated Show resolved Hide resolved
Comment on lines +34 to +92
#[derive(Clone, Copy)]
enum LogLevel {
Error,
Warn,
Info,
Debug,
Trace,
}

impl LogLevel {
fn as_str(&self) -> &'static str {
match self {
Self::Error => "error",
Self::Warn => "warn",
Self::Info => "info",
Self::Debug => "debug",
Self::Trace => "trace",
}
}

fn values() -> &'static [Self] {
&[
Self::Error,
Self::Warn,
Self::Info,
Self::Debug,
Self::Trace,
]
}
}

impl FromStr for LogLevel {
type Err = anyhow::Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
let variant = match s {
"error" => Self::Error,
"warn" => Self::Warn,
"info" => Self::Info,
"debug" => Self::Debug,
"trace" => Self::Trace,
_ => bail!("Unknown log level: {:?}", s),
};

Ok(variant)
}
}

impl From<LogLevel> for log::LevelFilter {
fn from(log_level: LogLevel) -> Self {
match log_level {
LogLevel::Error => Self::Error,
LogLevel::Warn => Self::Warn,
LogLevel::Info => Self::Info,
LogLevel::Debug => Self::Debug,
LogLevel::Trace => Self::Trace,
}
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is the crate https://crates.io/crates/clap-verbosity-flag that already does this :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TIL, I'll switch over to that!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Took a look at clap-verbosity-flag and noticed that it is for the more traditional -q and -v* style of verbosity flags while sccache-dist currently takes --syslog <LEVEL> instead. This means that switching to clap-verbosity-flag would be a breaking change and as v0.3 was released under a month ago, I'm guessing that another breaking change isn't intended quite this soon (and could merit looking into potentially revamping sccache's CLI structure as well)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're probably right one that, I am tempted to defer that change to another PR, but still strongly in favor of making it. I am not aware of other programs using that naming.

src/bin/sccache-dist/cmdline/parse.rs Show resolved Hide resolved
@mkatychev
Copy link

@drahnr this is slightly tangential but is there a reason why --flags listed in the helpdoc are actually used as args/commands?

sccache 0.3.0

USAGE:
    sccache [FLAGS] [OPTIONS] [cmd]...

FLAGS:
    -s, --show-stats      show cache statistics
        --start-server    start background server
        ...
ARGS:
    <cmd>...

It seems very confusing to see --start-server under flags only to later realize that it's a subcommand of sccache.

Here is POSIX documentation talking about flags/options:

It is followed by options, option-arguments, and operands. The arguments that consist of characters and single letters or digits, such as 'a', are known as "options" (or, historically, "flags").

docopt makes the same distinction

@CosmicHorrorDev
Copy link
Contributor Author

@drahnr Thanks for the review! I'm stretched a bit thin this week, but should be able to address everything over this weekend

@drahnr
Copy link
Collaborator

drahnr commented May 25, 2022

@drahnr this is slightly tangential but is there a reason why --flags listed in the helpdoc are actually used as args/commands?

sccache 0.3.0

USAGE:
    sccache [FLAGS] [OPTIONS] [cmd]...

FLAGS:
    -s, --show-stats      show cache statistics
        --start-server    start background server
        ...
ARGS:
    <cmd>...

It seems very confusing to see --start-server under flags only to later realize that it's a subcommand of sccache.

Here is POSIX documentation talking about flags/options:

It is followed by options, option-arguments, and operands. The arguments that consist of characters and single letters or digits, such as 'a', are known as "options" (or, historically, "flags").

docopt makes the same distinction

I'll look into this more closely, thanks for noting!

@drahnr
Copy link
Collaborator

drahnr commented Jun 23, 2022

I'll give this another go early next week :)

The only thing with not using the macros, is that now the logic is split into declaration and evaluation, which makes it harder to maintain imho. I am aware that this opposes what @mitchhentges suggested. Let me dig into this one last time, and please don't force push so we can use the "old" macro based approach just in case.

@sylvestre
Copy link
Collaborator

@drahnr are you still working on it? thanks

@drahnr
Copy link
Collaborator

drahnr commented Oct 12, 2022

I am a bit short on time recently. I'm wary of incompatibilities, other than that, it looks good. Sorry for the delay. I'll fix it up and get it done in the next few days.

@drahnr drahnr mentioned this pull request Oct 13, 2022
@drahnr
Copy link
Collaborator

drahnr commented Oct 13, 2022

I reviewed this again and #1354 is hence ready to merge @sylvestre

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants