Structopt: Consider support for the vergen crate

Created on 27 Jun 2019  路  7Comments  路  Source: TeXitoi/structopt

I have a fork of structopt with this simple change that accomplishes this for my needs, but at the cost of the default behavior for everyone else:

https://github.com/TeXitoi/structopt/compare/master...wez:vergen

That causes the version output by -h to show as the git hash for my project, which I prefer over the default semver version:

$ ./target/debug/wezterm -h
wezterm 20190626-162911-cc019ce-4-g9a7edb7
...

It does this via the https://docs.rs/vergen/3.0.4/vergen/ crate which is pulled in via the build.rs file in my app.

I'd like to find a way to integrate support for vergen to structopt so that I don't have to maintain a forked version of structopt_derive, but I don't know how best to accommodate such an optional feature.

What do you think?

Most helpful comment

use lazy_static::lazy_static;
use structopt::StructOpt;

lazy_static! {
    static ref VERSION: String = format!("{}-{}", env!("VERGEN_SEMVER"), env!("VERGEN_SHA_SHORT"));
}

#[derive(Debug, StructOpt)]
#[structopt(raw(version = "VERSION.as_str()"))]
struct Opt {}

fn main() {
    println!("{:#?}", Opt::from_args());
}

All 7 comments

Just use raw with env!():

$ cat src/main.rs 
use structopt::StructOpt;

#[derive(StructOpt, Debug)]
#[structopt(raw(version = r#"env!("VERSION")"#))]
struct Opt {
}

fn main() {
    let opt = Opt::from_args();
    println!("{:?}", opt);
}
$ touch src/main.rs 
$ VERSION=42 cargo build && cargo run -- --version
   Compiling test-rs v0.1.0 (/home/gpinot/dev/test-rs)
    Finished dev [unoptimized + debuginfo] target(s) in 0.53s
    Finished dev [unoptimized + debuginfo] target(s) in 0.03s
     Running `target/debug/test-rs --version`
test-rs 42
$ 

Teaser, in the v0.3, you'll just

use structopt::StructOpt;

#[derive(StructOpt, Debug)]
#[structopt(version = env!("VERSION"))]
struct Opt {
}

fn main() {
    let opt = Opt::from_args();
    println!("{:?}", opt);
}

Ah, much easier; thanks!

@TeXitoi How about if we want a combined version string like this? I've played this with serval attempts including using lazy_static, but never success.

raw(version = r#"format!("{}-{}", env!("VERGEN_SEMVER"), env!("VERGEN_SHA_SHORT"))"#)
use lazy_static::lazy_static;
use structopt::StructOpt;

lazy_static! {
    static ref VERSION: String = format!("{}-{}", env!("VERGEN_SEMVER"), env!("VERGEN_SHA_SHORT"));
}

#[derive(Debug, StructOpt)]
#[structopt(raw(version = "VERSION.as_str()"))]
struct Opt {}

fn main() {
    println!("{:#?}", Opt::from_args());
}

That's so weird, I definitively tried this and had got lifetime or trait not implemented issues. However it works now. Thank you very much!

lazy_static wrap the object, thus a simple &VERSION will not work. You'll have to &**VERSION to fix the type error, but using VERSION.as_str() is IMHO cleaner, and working thanks to autoderef. Maybe you had such a conversion problem when you tried this solution.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

swfsql picture swfsql  路  3Comments

lucab picture lucab  路  9Comments

mbrobbel picture mbrobbel  路  5Comments

yoshuawuyts picture yoshuawuyts  路  7Comments

TedDriggs picture TedDriggs  路  6Comments