z1info_rust/
lib.rs

1//! Add extra information to the binary package through `cargo run [...] z1info=extra_information`
2//!
3//! # Use
4//!
5//! ### add code
6//! 
7//! ### add dependencies
8//! - z1info_rust = "0.1.3"
9//!
10//! ```no_run
11//! fn main() {
12//!     z1info_rust::run("z1template");
13//!     // z1info_test::run("z1_info:{z1_info},git_info:{git_info},build_time:{build_time}");
14//! }
15//! ```
16//! ### run command
17//!
18//! `z1info=` must be placed at the end of the command line,`cargo run`will write extra information to tmp file.
19//! - `cargo run p1 p2 z1info=version:1.2.3,compiler:myzero1`
20//! ### build
21//! - cargo clean && cargo build
22//! - OR cargo clean && cargo build --release
23//!
24//! # Result
25//! ### run command or run `builded binary package`
26//! - cargo clean  && cargo run  p1 p2
27//! - OR run builded binary package
28//!
29//! ### The Result
30//!
31//! <br/>=============== z1info extended data ====================
32//! <br/>| Extended data added to binary file through z1info.
33//! <br/>|--------------- z1info parameter ----------------------
34//! <br/>| z1info=version:1.2.3,compiler:myzero1
35//! <br/>|--------------- git info ------------------------------
36//! <br/>| commit id: 94896476ea1696f9b8764cd845f225e4af586bc4
37//! <br/>|--------------- build time ----------------------------
38//! <br/>| 1621770625
39//! <br/>=========================================================
40//!
41
42use std::io::Write;
43use std::process::{Command, Stdio};
44use std::time::{SystemTime, UNIX_EPOCH};
45
46/// Add or display additional information
47///
48/// # Examples
49///
50/// ```no_run
51/// z1info_rust::run("z1template");
52/// // z1info_test::run("z1_info:{z1_info},git_info:{git_info},build_time:{build_time}");
53/// ```
54///
55pub fn run(template: &str){
56    let args :Vec<String> = std::env::args().collect();
57
58    if !is_runtime(&args){
59        let mut content_template = "
60            =============== z1info extended data ====================
61            | Extended data added to binary file through z1info.
62            |--------------- z1info parameter ----------------------
63            | {z1_info}
64            |--------------- git info ------------------------------
65            | commit id: {git_info}
66            |--------------- build time ----------------------------
67            | {build_time}
68            =========================================================
69        ";
70
71        if "z1template"!=template {
72            content_template = template;
73        }
74
75        let mut content = str::replace(content_template,"{z1_info}",&args[args.len()-1]);
76        content = str::replace(&content[..],"{git_info}",&get_commit_id());
77        content = str::replace(&content[..],"{build_time}",&format!("{}",get_current_time()));
78
79        // let mut file = std::fs::File::create("z1info_tmp").unwrap();
80        // file.write_all(content.as_bytes()).expect("write z1info failed");
81
82        write_to_tmp(&content,)
83    } else {
84        println!("{}",include_str!("../z1info_tmp"));
85    }
86}
87
88fn is_runtime(args: &Vec<String>)->bool{
89    let lenght = args.len();
90
91    if 0 < lenght {
92        let flag = "z1info=";
93        let flag_length = flag.len();
94        let last_length = args[lenght-1].len();
95        if last_length >= flag_length {
96            return !(flag == &args[lenght-1][0..flag_length]);
97        }
98    }
99
100    return true;
101}
102
103fn get_commit_id()->String{
104    // cmd_str可以是从输入流读取或从文件里读取
105    let cmd_str = "git rev-parse HEAD";
106    let out_str: String;
107
108    if cfg!(target_os = "windows") {
109        let output = Command::new("cmd")
110        .arg("/c")
111        .arg(&cmd_str)
112        .stdout(Stdio::piped())
113        .output()
114        .expect(&format!("cmd exec error!"));
115
116        out_str = format!("{}", String::from_utf8_lossy(&output.stdout));
117    } else {
118       let output= Command::new("sh")
119        .arg("/c")
120        .arg(&cmd_str)
121        .stdout(Stdio::piped())
122        .output()
123        .expect(&format!("sh exec error!"));
124
125        out_str = format!("{}", String::from_utf8_lossy(&output.stdout));
126    };
127
128    let ret_end = str::replace(&out_str[..],"\n","");
129
130    return ret_end;
131}
132
133fn get_current_timestamp()->u64{
134    let start = SystemTime::now();
135    let since_the_epoch = start
136        .duration_since(UNIX_EPOCH)
137        .expect("Time went backwards");
138
139    return since_the_epoch.as_secs();
140}
141
142fn path_exist(path: &str) -> bool {
143    return match std::path::Path::new(path).canonicalize() {
144        Ok(_buf) => true,
145        Err(_error) => false,
146    };
147}
148
149fn write_to_tmp(content: &str) {
150    let cargo_toml = format!("{:?}", std::fs::read_to_string("Cargo.toml"));
151    let mut write_to_crate = true;
152
153    let cargo_toml_info: Vec<&str> = cargo_toml.split("z1info_rust = ").collect();
154    if cargo_toml_info.len()>1{
155        let cargo_toml_info2: Vec<&str> = cargo_toml_info[1].split("\\\"").collect();
156
157        if cargo_toml_info2.len()>1{
158            let cargo_toml_info2: Vec<&str> = cargo_toml_info[1].split("\\\"").collect();
159            let mut cargo_registry = String::from("");
160
161            match std::env::var("CARGO_HOME") {
162                Ok(val) => cargo_registry = format!("{}/registry/src", val),
163                Err(_e) => println!("{:?}",_e),
164            }
165
166            let paths = std::fs::read_dir(cargo_registry).unwrap();
167            for path in paths {
168                let tmp_file = &format!("{}/z1info_rust-{}/z1info_tmp", path.unwrap().path().display(),cargo_toml_info2[1])[..];
169
170                if path_exist(tmp_file){
171                    let mut file = std::fs::File::create(tmp_file).unwrap();
172                    file.write_all(content.as_bytes()).expect("write z1info failed");
173
174                    write_to_crate = false;
175                }
176            }
177        }
178    }
179
180    if write_to_crate{
181        let mut file = std::fs::File::create("z1info_tmp").unwrap();
182        file.write_all(content.as_bytes()).expect("write z1info failed");
183    }
184}
185
186fn get_current_time()-> String {
187    let out_str: String;
188
189    if cfg!(target_os = "windows") {
190        let output = Command::new("cmd")
191        .arg("/c")
192        .arg("echo %date:~0,4%-%date:~5,2%-%date:~8,2% %time:~0,2%:%time:~3,2%:%time:~6,2%")
193        .stdout(Stdio::piped())
194        .output()
195        .expect(&format!("cmd exec error!"));
196
197        out_str = format!("{}", String::from_utf8_lossy(&output.stdout));
198    } else {
199       let output= Command::new("sh")
200        .arg("/c")
201        .arg("echo $(date '+%Y-%m-%d %H:%M:%S')")
202        .stdout(Stdio::piped())
203        .output()
204        .expect(&format!("sh exec error!"));
205
206        out_str = format!("{}", String::from_utf8_lossy(&output.stdout));
207    };
208
209    let ret_end = str::replace(&out_str[..],"\n","");
210
211    return ret_end;
212}