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
118
119
120
121
122
123
124
125
126
127
/* Several function to retrieve version information.
 */

const MAJOR: usize = 3;
const MINOR: usize = 5;
const MICRO: usize = 0;
const RELEASELEVEL: &str = "alpha";
const SERIAL: usize = 0;

#[pystruct_sequence(name = "version_info")]
#[derive(Default, Debug)]
pub struct VersionInfo {
    major: usize,
    minor: usize,
    micro: usize,
    releaselevel: &'static str,
    serial: usize,
}
extern crate chrono;
use chrono::prelude::DateTime;
use chrono::Local;
use std::time::{Duration, UNIX_EPOCH};

pub fn get_version() -> String {
    format!(
        "{:.80} ({:.80}) {:.80}",
        get_version_number(),
        get_build_info(),
        get_compiler()
    )
}

pub fn get_version_info() -> VersionInfo {
    VersionInfo {
        major: MAJOR,
        minor: MINOR,
        micro: MICRO,
        releaselevel: RELEASELEVEL,
        serial: SERIAL,
    }
}

pub fn get_version_number() -> String {
    format!("{}.{}.{}{}", MAJOR, MINOR, MICRO, RELEASELEVEL)
}

pub fn get_compiler() -> String {
    let rustc_version = rustc_version_runtime::version_meta();
    format!("\n[rustc {}]", rustc_version.semver)
}

pub fn get_build_info() -> String {
    // See: https://reproducible-builds.org/docs/timestamps/
    let git_revision = get_git_revision();
    let separator = if git_revision.is_empty() { "" } else { ":" };

    let git_identifier = get_git_identifier();

    format!(
        "{id}{sep}{revision}, {date:.20}, {time:.9}",
        id = if git_identifier.is_empty() {
            "default".to_owned()
        } else {
            git_identifier
        },
        sep = separator,
        revision = git_revision,
        date = get_git_date(),
        time = get_git_time(),
    )
}

pub fn get_git_revision() -> String {
    option_env!("RUSTPYTHON_GIT_HASH").unwrap_or("").to_owned()
}

pub fn get_git_tag() -> String {
    option_env!("RUSTPYTHON_GIT_TAG").unwrap_or("").to_owned()
}

pub fn get_git_branch() -> String {
    option_env!("RUSTPYTHON_GIT_BRANCH")
        .unwrap_or("")
        .to_owned()
}

pub fn get_git_identifier() -> String {
    let git_tag = get_git_tag();
    let git_branch = get_git_branch();

    if git_tag.is_empty() || git_tag == "undefined" {
        git_branch
    } else {
        git_tag
    }
}

fn get_git_timestamp_datetime() -> DateTime<Local> {
    let timestamp = option_env!("RUSTPYTHON_GIT_TIMESTAMP")
        .unwrap_or("")
        .to_owned();
    let timestamp = timestamp.parse::<u64>().unwrap_or(0);

    let datetime = UNIX_EPOCH + Duration::from_secs(timestamp);
    let datetime = DateTime::<Local>::from(datetime);

    datetime
}

pub fn get_git_date() -> String {
    let datetime = get_git_timestamp_datetime();

    datetime.format("%b %e %Y").to_string()
}

pub fn get_git_time() -> String {
    let datetime = get_git_timestamp_datetime();

    datetime.format("%H:%M:%S").to_string()
}

pub fn get_git_datetime() -> String {
    let date = get_git_date();
    let time = get_git_time();

    format!("{} {}", date, time)
}