cargo-workspace2 0.2.2

A tool to query and manage complex cargo workspaces
Documentation
use super::{Op, Print, Publish, PublishMod as Mod, PublishType::*};
use semver::Version;

/// Parse a argument line into an operation
pub(super) fn run(mut line: Vec<String>) -> Option<Op> {
    let op = line.remove(0);

    match op.as_str() {
        "print" => parse_print(line),
        "publish" => parse_publish(line),
        op => {
            eprintln!("[ERROR]: Unrecognised operation `{}`", op);
            None
        }
    }
}

fn parse_print(line: Vec<String>) -> Option<Op> {
    let abs = line
        .get(1)
        .map(|abs| match abs.as_str() {
            "abs" | "absolute" => true,
            _ => false,
        })
        .unwrap_or(false);

    match line.get(0).map(|s| s.as_str()) {
        Some("path") => Some(Op::Print(Print::Path { abs })),
        Some("both") => Some(Op::Print(Print::Both { abs })),
        Some("name") | None => Some(Op::Print(Print::Name)),
        Some(val) => {
            eprintln!("[ERROR]: Unrecognised param: `{}`", val);
            None
        }
    }
}

fn publish_error() -> Option<Op> {
    eprintln!(
        "[ERROR]: Missing or invalid operands!
Usage: cargo ws2 <QUERY LANG> publish <level> [modifier] [devel]\n
  Valid <level>: major, minor, patch, or '=<VERSION>' to set an override version.\n
  Valid [modifier]: alpha, beta, rc\n
  [devel]: after publishing, set crate version to <VERSION>-devel"
    );
    None
}

fn parse_publish(mut line: Vec<String>) -> Option<Op> {
    line.reverse();
    let tt = match line.pop() {
        Some(tt) => tt,
        None => {
            return publish_error();
        }
    };

    let _mod = line.pop();
    let tt = match (tt.as_str(), _mod.as_ref().map(|s| s.as_str())) {
        ("major", Some("alpha")) => Major(Mod::Alpha),
        ("major", Some("beta")) => Major(Mod::Beta),
        ("major", Some("rc")) => Major(Mod::Rc),
        ("minor", Some("alpha")) => Minor(Mod::Alpha),
        ("minor", Some("beta")) => Minor(Mod::Beta),
        ("minor", Some("rc")) => Minor(Mod::Rc),
        ("patch", Some("alpha")) => Patch(Mod::Alpha),
        ("patch", Some("beta")) => Patch(Mod::Beta),
        ("patch", Some("rc")) => Patch(Mod::Rc),
        ("major", Some(_)) | ("major", None) => Major(Mod::None),
        ("minor", Some(_)) | ("minor", None) => Minor(Mod::None),
        ("patch", Some(_)) | ("patch", None) => Patch(Mod::None),
        (v, _) if v.trim().starts_with("=") => {
            let vers = v.replace("=", "").to_string();
            if vers.as_str() == "" {
                return publish_error();
            } else {
                Fixed(vers)
            }
        }
        (_, _) => {
            return publish_error();
        }
    };

    let devel = match tt {
        // Means _mod was not a mod
        Major(Mod::None) | Minor(Mod::None) | Patch(Mod::None) => {
            if let Some(devel) = _mod {
                if devel == "devel" {
                    true
                } else {
                    return publish_error();
                }
            } else {
                false
            }
        }
        _ => {
            if let Some(devel) = line.pop() {
                if devel == "devel" {
                    true
                } else {
                    false
                }
            } else {
                false
            }
        }
    };

    Some(Op::Publish(Publish { tt, devel }))
}