message: detect outdated xargo version
diff: extern crate cargo_metadata;
  use std::path::{PathBuf, Path};
  -use std::io::{self, Write};
  +use std::io::{self, Write, BufRead};
  use std::process::Command;
  use std::fs::{self, File};
  @@ -114,6 +114,36 @@ fn list_targets() -> impl Iterator<Item=cargo_metadata::Target> {
  package.targets.into_iter()
  }
  +fn xargo_version() -> Option<(u32, u32, u32)> {
  + let out = Command::new("xargo").arg("--version").output().ok()?;
  + if !out.status.success() {
  + return None;
  + }
  + // Parse output. The first line looks like "xargo 0.3.12 (b004f1c 2018-12-13)".
  + let line = out.stderr.lines().nth(0)
  + .expect("malformed `xargo --version` output: not at least one line")
  + .expect("malformed `xargo --version` output: error reading first line");
  + let version = line.split(' ').nth(1)
  + .expect("malformed `xargo --version` output: not at least two words");
  + let mut version_pieces = version.split('.');
  + let major = version_pieces.next()
  + .expect("malformed `xargo --version` output: not a major version piece")
  + .parse()
  + .expect("malformed `xargo --version` output: major version is not an integer");
  + let minor = version_pieces.next()
  + .expect("malformed `xargo --version` output: not a minor version piece")
  + .parse()
  + .expect("malformed `xargo --version` output: minor version is not an integer");
  + let patch = version_pieces.next()
  + .expect("malformed `xargo --version` output: not a patch version piece")
  + .parse()
  + .expect("malformed `xargo --version` output: patch version is not an integer");
  + if !version_pieces.next().is_none() {
  + panic!("malformed `xargo --version` output: more than three pieces in version");
  + }
  + Some((major, minor, patch))
  +}
  +
  fn ask(question: &str) {
  let mut buf = String::new();
  print!("{} [Y/n] ", question);
  @@ -134,14 +164,14 @@ fn setup(ask_user: bool) {
  }
  // First, we need xargo
  - if Command::new("xargo").arg("--version").output().is_err()
  - {
  + let xargo = xargo_version();
  + if xargo.map_or(true, |v| v < (0, 3, 13)) {
  if ask_user {
  - ask("It seems you do not have xargo installed. I will run `cargo install xargo`. Proceed?");
  + ask("It seems you do not have a recent enough xargo installed. I will run `cargo install xargo -f`. Proceed?");
  } else {
  - println!("Installing xargo: `cargo install xargo`");
  + println!("Installing xargo: `cargo install xargo -f`");
  }
  - if !Command::new("cargo").args(&["install", "xargo"]).status().unwrap().success() {
  + if !Command::new("cargo").args(&["install", "xargo", "-f"]).status().unwrap().success() {
  show_error(format!("Failed to install xargo"));
  }
  }
  