cargo_version/
lib.rs

1use std::io;
2use std::process::Command;
3
4mod bump_level;
5pub use bump_level::{BumpLevel, BumpLevelError};
6
7mod toml;
8use toml::{TomlSemverExtensions, TomlError};
9
10mod derive_next_version;
11use derive_next_version::derive_next_version;
12
13extern crate semver;
14
15use semver::Version;
16pub use semver::SemVerError;
17
18pub enum CargoVersionError {
19    GitNotClean,
20    IoError(io::Error),
21    NoVersionFound,
22    SemVerError(semver::SemVerError),
23}
24
25impl From<TomlError> for CargoVersionError {
26    fn from(err: TomlError) -> CargoVersionError {
27        match err {
28            TomlError::NoVersionFound => CargoVersionError::NoVersionFound,
29            TomlError::IoError(err) => CargoVersionError::IoError(err),
30            TomlError::SemVerError(err) => CargoVersionError::SemVerError(err),
31        }
32    }
33}
34
35fn require_clean_git() -> Result<(), ()> {
36    Command::new("git")
37        .arg("status")
38        .arg("--porcelain=v1")
39        .arg("--untracked-files=no")
40        .output()
41        .map(|output| output.stdout.len() > 0)
42        .map(|dirty| if dirty { Err(()) } else { Ok(()) })
43        .expect("Failed to read git status")
44}
45
46pub fn create_version(level: BumpLevel) -> Result<(), CargoVersionError> {
47    // 1. Check that git is clean
48    try!(require_clean_git().map_err(|_| CargoVersionError::GitNotClean));
49
50    // 2. Read the current version
51    let current_version = try!(Version::read_from_toml("Cargo.toml"));
52
53    // 3. Compute the next version
54    let next_version = derive_next_version(current_version, level);
55
56    // 4. Update version in Cargo.toml
57    try!(next_version.write_to_toml("Cargo.toml"));
58
59    // 5. Regenerate the lockfile
60    Command::new("cargo")
61        .arg("generate-lockfile")
62        .spawn()
63        .expect("Failed to regenerate lockfile")
64        .wait()
65        .expect("Failed to regenerate lockfile");
66
67    // 6. Build package in release mode
68    Command::new("cargo")
69        .arg("build")
70        .arg("--release")
71        .spawn()
72        .expect("Failed to build package")
73        .wait()
74        .expect("Failed to build package");
75
76    // 7. Stage modified files
77    Command::new("git")
78        .arg("add")
79        .arg("Cargo.toml")
80        .arg("Cargo.lock")
81        .spawn()
82        .expect("Failed to add files to the git staging area")
83        .wait()
84        .expect("Failed to add files to the git staging area");
85
86    // 8. Create a commit
87    Command::new("git")
88        .arg("commit")
89        .arg("-m")
90        .arg(format!("🚢 {}", next_version))
91        .spawn()
92        .expect("Failed to create a git commit")
93        .wait()
94        .expect("Failed to create a git commit");
95
96    // 9. Create git tag
97    Command::new("git")
98        .arg("tag")
99        .arg(format!("v{}", next_version))
100        .arg("-am")
101        .arg(format!("🚢 {}", next_version))
102        .spawn()
103        .expect("Failed to create a git tag")
104        .wait()
105        .expect("Failed to create a git tag");
106
107    Ok(())
108}