substrate_build_script_utils/
git.rs1use std::{
19 env, fs,
20 fs::File,
21 io,
22 io::Read,
23 path::{Path, PathBuf},
24};
25
26pub fn rerun_if_git_head_changed() {
32 let mut manifest_dir = PathBuf::from(
33 env::var("CARGO_MANIFEST_DIR").expect("`CARGO_MANIFEST_DIR` is always set by cargo."),
34 );
35 let manifest_dir_copy = manifest_dir.clone();
36
37 while manifest_dir.parent().is_some() {
38 match get_git_paths(&manifest_dir) {
39 Err(err) => {
40 eprintln!("cargo:warning=Unable to read the Git repository: {}", err);
41
42 return
43 },
44 Ok(None) => {},
45 Ok(Some(paths)) => {
46 for p in paths {
47 println!("cargo:rerun-if-changed={}", p.display());
48 }
49
50 return
51 },
52 }
53
54 manifest_dir.pop();
55 }
56
57 println!(
58 "cargo:warning=Could not find `.git/HEAD` searching from `{}` upwards!",
59 manifest_dir_copy.display(),
60 );
61}
62
63fn get_git_paths(path: &Path) -> Result<Option<Vec<PathBuf>>, io::Error> {
65 let git_dir_or_file = path.join(".git");
66
67 if let Ok(metadata) = fs::metadata(&git_dir_or_file) {
68 if metadata.is_dir() {
69 let git_head_path = git_dir_or_file.join("HEAD");
71
72 let mut f = File::open(&git_head_path)?;
74 let mut git_head_contents = String::new();
75 let _ = f.read_to_string(&mut git_head_contents)?;
76 let ref_vec: Vec<&str> = git_head_contents.split(": ").collect();
77
78 if ref_vec.len() == 2 {
79 let current_head_file = ref_vec[1];
80 let git_refs_path = git_dir_or_file.join(current_head_file);
81
82 Ok(Some(vec![git_head_path, git_refs_path]))
83 } else {
84 Err(io::Error::new(
85 io::ErrorKind::Other,
86 "You are most likely in a detached HEAD state",
87 ))
88 }
89 } else if metadata.is_file() {
90 let mut git_file = File::open(&git_dir_or_file)?;
92 let mut git_contents = String::new();
93 let _ = git_file.read_to_string(&mut git_contents)?;
94 let dir_vec: Vec<&str> = git_contents.split(": ").collect();
95 let git_path = dir_vec[1].trim();
96
97 let git_head_path = PathBuf::from(git_path).join("HEAD");
99
100 let mut actual_git_dir = PathBuf::from(git_path);
102 actual_git_dir.pop();
103 actual_git_dir.pop();
104
105 let mut f = File::open(&git_head_path)?;
107 let mut git_head_contents = String::new();
108 let _ = f.read_to_string(&mut git_head_contents)?;
109 let ref_vec: Vec<&str> = git_head_contents.split(": ").collect();
110
111 if ref_vec.len() == 2 {
112 let current_head_file = ref_vec[1];
113 let git_refs_path = actual_git_dir.join(current_head_file);
114
115 Ok(Some(vec![git_head_path, git_refs_path]))
116 } else {
117 Err(io::Error::new(
118 io::ErrorKind::Other,
119 "You are most likely in a detached HEAD state",
120 ))
121 }
122 } else {
123 Err(io::Error::new(
124 io::ErrorKind::Other,
125 "Invalid .git format (Not a directory or a file)",
126 ))
127 }
128 } else {
129 Ok(None)
130 }
131}