aboutsummaryrefslogtreecommitdiff
path: root/development/tools/cargo-workspace2/src/ops/publish/exec.rs
blob: 3f2d36863bcf9dd51d10e369b32f7a41414a6ec0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
//! Publishing executor

use super::{Publish, PublishMod as Mod, PublishType};
use crate::{
    models::{CrateId, DepGraph},
    ops::verify_user,
};
use semver::Version;
use textwrap;

pub(in crate::ops) fn run(p: Publish, set: Vec<CrateId>, g: &mut DepGraph) {
    let Publish { ref tt, devel } = p;

    let vec = set.into_iter().fold(vec![], |mut vec, id| {
        let c = g.mut_crate(id);
        let c_name = c.name().clone();
        let curr_ver = c.version();
        let new_ver = bump(&curr_ver, tt);
        c.publish(new_ver.clone());
        eprintln!("Bumping `{}`: `{}` ==> `{}`", c.name(), &curr_ver, new_ver);
        drop(c);

        g.get_dependents(id).into_iter().for_each(|id| {
            let dep = g.mut_crate(id);
            dep.change_dependency(&c_name, &new_ver);
            eprintln!("Changing dependency `{}`: {} = {{ version = `{}`, ... }} ==> {{ version = `{}`, ... }}",
                      dep.name(),
                      c_name,
                      &curr_ver,
                      new_ver);
            vec.push(id);
        });

        vec.push(id);
        vec
    });

    // If we make it past this point the user is sure
    verify_user();

    vec.into_iter().for_each(|(id)| {
        let c = g.mut_crate(id);
        c.sync();
    });

    eprintln!("{}", textwrap::fill("Publish complete. Check that everything is in order, \
                                    then run `cargo publish` to upload to crates.io!", 80));
}

/// Bump a version number according to some rules
fn bump(v: &String, tt: &PublishType) -> String {
    let mut ver = Version::parse(&v).unwrap();
    let ver = match tt {
        PublishType::Fixed(ref ver) => Version::parse(ver).unwrap(),
        PublishType::Major(_) => {
            ver.increment_major();
            ver
        }
        PublishType::Minor(_) => {
            ver.increment_minor();
            ver
        }
        PublishType::Patch(_) => {
            ver.increment_patch();
            ver
        }
    };

    // If a mod applies, handle it...
    if let Some(_mod) = tt._mod() {
        if ver.is_prerelease() {
            let v = ver.clone().to_string();
            let num = v.split(".").last().unwrap();
            let num: usize = num.parse().unwrap();
            ver.clone()
                .to_string()
                .replace(&format!("{}", num), &format!("{}", num + 1))
                .to_string()
        } else {
            format!(
                "{}-{}",
                ver.to_string(),
                match _mod {
                    Mod::Alpha => "alpha.0",
                    Mod::Beta => "beta.0",
                    Mod::Rc => "rc.0",
                    _ => unreachable!(),
                }
            )
        }
    } else {
        ver.to_string()
    }
}

macro_rules! assert_bump {
    ($input:expr, $level_mod:expr, $expect:expr) => {
        assert_eq!(bump(&$input.to_owned(), $level_mod), $expect.to_string());
    };
}

#[cfg(test)]
use super::{PublishMod::*, PublishType::*};

#[test]
fn bump_major() {
    assert_bump!("1.0.0", &Major(None), "2.0.0");
    assert_bump!("1.5.4", &Major(None), "2.0.0");
    assert_bump!("1.3.0", &Major(Alpha), "2.0.0-alpha.0");
}

#[test]
fn bump_minor() {
    assert_bump!("1.1.0", &Minor(None), "1.2.0");
    assert_bump!("1.5.4", &Minor(Beta), "1.6.0-beta.0");
    assert_bump!("1.5.4-beta.0", &Minor(Beta), "1.6.0-beta.0");
}