github.com/muhammedhassanm/blockchain@v0.0.0-20200120143007-697261defd4d/sawtooth-core-master/validator/build.rs (about)

     1  /*
     2   * Copyright 2017 Intel Corporation
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   * ------------------------------------------------------------------------------
    16   */
    17  
    18  extern crate glob;
    19  extern crate protoc_rust;
    20  
    21  use std::error::Error;
    22  use std::fs;
    23  use std::io::prelude::*;
    24  use std::path::Path;
    25  use std::time::{Duration, UNIX_EPOCH};
    26  
    27  use protoc_rust::Customize;
    28  
    29  const PROTO_FILES_DIR: &str = "../protos";
    30  const PROTOBUF_TARGET_DIR: &str = "src/proto";
    31  const GENERATED_SOURCE_HEADER: &str = r#"
    32  #![cfg_attr(rustfmt, rustfmt_skip)]
    33  
    34  /*
    35   * THIS IS A GENERATED FILE: DO NOT MODIFY
    36   *
    37   * This is the module which contains the generated sources for the Protocol
    38   * buffers messages.
    39   */
    40  "#;
    41  
    42  #[derive(Debug, Clone)]
    43  struct ProtoFile {
    44      module_name: String,
    45      file_path: String,
    46      last_modified: Duration,
    47  }
    48  
    49  fn main() {
    50      // Generate protobuf files
    51      let proto_src_files = glob_simple(&format!("{}/*.proto", PROTO_FILES_DIR));
    52      let last_build_time = read_last_build_time();
    53  
    54      let latest_change = proto_src_files.iter().fold(
    55          Duration::from_secs(0),
    56          |max, ref proto_file| {
    57              if proto_file.last_modified > max {
    58                  proto_file.last_modified
    59              } else {
    60                  max
    61              }
    62          },
    63      );
    64  
    65      if latest_change > last_build_time {
    66          println!("{:?}", proto_src_files);
    67          fs::create_dir_all(PROTOBUF_TARGET_DIR).unwrap();
    68          protoc_rust::run(protoc_rust::Args {
    69              out_dir: PROTOBUF_TARGET_DIR,
    70              input: &proto_src_files
    71                  .iter()
    72                  .map(|proto_file| proto_file.file_path.as_ref())
    73                  .collect::<Vec<&str>>(),
    74              includes: &["src", PROTO_FILES_DIR],
    75              customize: Customize {
    76                  ..Default::default()
    77              },
    78          }).expect("unable to run protoc");
    79  
    80          let mod_file_name = format!("{}/mod.rs", PROTOBUF_TARGET_DIR);
    81          let mod_file_path = Path::new(&mod_file_name);
    82          let mut file = match fs::File::create(&mod_file_path) {
    83              Err(err) => panic!(
    84                  "Unable to create file {}: {}",
    85                  mod_file_name,
    86                  err.description()
    87              ),
    88              Ok(file) => file,
    89          };
    90  
    91          let content = format!(
    92              "{}\n{}\n",
    93              GENERATED_SOURCE_HEADER,
    94              proto_src_files
    95                  .iter()
    96                  .map(|proto_file| format!("pub mod {};", proto_file.module_name))
    97                  .collect::<Vec<_>>()
    98                  .join("\n")
    99          );
   100          match file.write_all(content.as_bytes()) {
   101              Err(err) => panic!(
   102                  "Unable to write to {}: {}",
   103                  mod_file_name,
   104                  err.description()
   105              ),
   106              Ok(_) => println!("generated {}", mod_file_name),
   107          }
   108      } else {
   109          println!(
   110              "No proto files changed; latest modification: {}, last build: {}",
   111              latest_change.as_secs(),
   112              last_build_time.as_secs()
   113          );
   114      }
   115  }
   116  
   117  fn glob_simple(pattern: &str) -> Vec<ProtoFile> {
   118      glob::glob(pattern)
   119          .expect("Search did not result in files")
   120          .map(|g| protofile_info(g.expect("item").as_path()))
   121          .collect()
   122  }
   123  
   124  fn protofile_info(path: &Path) -> ProtoFile {
   125      let module_name = path.file_stem()
   126          .expect("Unable to get file stem")
   127          .to_str()
   128          .expect("File name should be utf-8")
   129          .to_owned();
   130  
   131      let file_path = path.to_str().expect("utf-8").to_owned();
   132  
   133      let file = fs::File::open(path).expect("Unable to open file");
   134      let last_modified = get_modified_time(file);
   135  
   136      ProtoFile {
   137          module_name,
   138          file_path,
   139          last_modified,
   140      }
   141  }
   142  
   143  fn read_last_build_time() -> Duration {
   144      let mod_file_name = format!("{}/mod.rs", PROTOBUF_TARGET_DIR);
   145      match fs::File::open(Path::new(&mod_file_name)) {
   146          Err(err) => {
   147              println!(
   148                  "unable to open {}: {}; defaulting to 0",
   149                  mod_file_name,
   150                  err.description()
   151              );
   152              Duration::new(0, 0)
   153          }
   154          Ok(file) => get_modified_time(file),
   155      }
   156  }
   157  
   158  fn get_modified_time(file: fs::File) -> Duration {
   159      file.metadata()
   160          .expect("File should have metadata")
   161          .modified()
   162          .map(|sys_time| {
   163              sys_time
   164                  .duration_since(UNIX_EPOCH)
   165                  .expect("System time should be after UNIX_EPOCH")
   166          })
   167          .expect("File should have modified time")
   168  }